Forum: Mikrocontroller und Digitale Elektronik Array übergeben


von Max (Gast)


Lesenswert?

Servus beinand,

also ich habe ein vielleicht banales Problem, komm aber echt grad auf 
kein grünen Zweig.

Ich habe in einer .h-Datei eine PWM funktion definiert, welche die Werte 
aus einem Array verwendet.
Der kniff an der Sache ist nun, der Benutzer kann zu Beginn zwischen 3 
verschiedenen Arrays auswählen (hat mit der Helligkeitsanpassung zu 
tun). Die Auswahl habe ich als switch case in der main.c-Datei 
verbastelt.
(In main.c wird später des öfteren auch die PWM-Funktion aufgerufen)

Mein Problem ist nun, dass ich nicht so ganz checke, wie ich dem 
Programm klar mache, dass er in der PWM-Funktion die zuvor ausgewählten 
Werte verwendet. Also wie ich die Übergabe von main.c an die funktion in 
pwm.h mache.

Habe schon einiges Probiert, aber das Zusammenspiel zwischen .h und .c 
mit der Werteübergabe funktioniert irgendwie nicht.

Kann mir da jemand vielleicht einen grünen Zweig reichen?

von Max (Gast)


Lesenswert?

Ach ja, hier die einzelnen Teile ausm Code:

pwm.h
1
//long delays
2
void my_delay(uint16_t milliseconds)
3
{
4
  for(; milliseconds > 0; milliseconds--) 
5
  _delay_ms(1);
6
}
7
8
9
void DimmLed(uint16_t delay)
10
  {
11
  int16_t tmp;
12
  
13
  //-->LED Dimmen
14
    for(tmp=0; tmp<=255; tmp++){
15
      OCR1A = pgm_read_word(pwmtable_16+tmp);
16
      my_delay(delay);
17
    }
18
  }

die auswahl in main.c
1
    uint16_t pwmtable_16[]={};
2
    a = uart_getc();  
3
    switch(a)
4
    {
5
      case 'a':
6
          pwmtable_16[190] = x,x,x,x,x,x;
7
          
8
          ComText("Helle Umgebung\n\r");
9
          
10
      break;
11
      
12
      case 'b':
13
          pwmtable_16[190] = y,y,y,y,y,y;  
14
      
15
          ComText("Mittlere Helligkeit\n\r");
16
17
      break; 
18
      
19
      case 'c':
20
          pwmtable_16[190] = z,z,z,z,z,z;
21
          
22
          ComText("Dunkle Umgebung\n\r");
23
24
      break;
25
26
      default:
27
          
28
          ComText("Diese Eingabemöglichtkeit besteht nicht!!!\n\r");
29
30
    }


und hier der Aufruf in der main.c datei
1
for(i=0; i<3; i++) DimmLed(step_time);
2
OCR1A = 0; 
3
                  //LED-Dimm, anschließend Lichtal aus

von Random .. (thorstendb) Benutzerseite


Lesenswert?

> Array übergeben
und wer macht den Mist hinterher wieder sauber? :-)

Also.

C Grundlagen, 1. Stunde:
Die .c Dateien enthalten den Quellcode.
Die .h Dateien enthalten idR. Prototypen zwecks Austausch an andere 
Module (also andere .c Dateien) und #defines etc.

Man nehme also an, du hast main.c/.h und pwm.c/.h

In main.c liegt irgendwo ein array vor, meinenthalber:
1
char buf[16];

Jetzt willst du das an eine Fkt. im Modul pwm.c übergeben.

Der prototyp schaut dann wie folgt aus:
1
void PWM_Func(char *buf);
aufgerufen wird das ganze als:
1
PWM_Func(buf);

in der PWM_Func kannst du jetzt "wie gehabt" mit dem Array 
weiterarbeiten:
1
void PWM_Func(char *buf)
2
{
3
  int i;
4
  char localBuf[16];
5
6
  for(i=0; i<16; i++) {
7
    localBuf[i] = buf[i];
8
  }
9
}
Der Compiler berechnet sich den Offset selbst, weil er weiss, wie gross 
"char" ist, und multipliziert das mit deinem Index.

Sauberer wirds natürlich, wenn du die "16" als
1
#define BUF_SIZE   16
in main.h anlegst, und diese dann in pwm.c includierst. Dann kannst du 
dort die 16 durch BUF_SIZE ersetzen, und durch geringfügige Änderungen 
den Buffer vergrössern oder verkleinern.

von Max (Gast)


Lesenswert?

Jo, des klappt mittlerweile, nur will schreibt er die Werte aus der 
switch-case nicht in "buf" bevor er sie an die "PWM_Func" übergibt?!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Und was vermutest Du, was hier passieren soll?
1
uint16_t pwmtable_16[]={};
2
3
...
4
5
pwmtable_16[190] = x,x,x,x,x,x;

Du definierst ein leeres Array, und Du weist dem 191. Element dieses 
Arrays einen Wert zu (und hast offensichtlich merkwürdige Vorstellungen 
davon, was der Kommaoperator so macht).

von Karl H. (kbuchegg)


Lesenswert?

Das ist auch in main.c der falsche Ansatz.

Du hast die 3 Arrays grundsätzlich immer vorliegen
1
uint8_t pwmtable_16_A[190] = x,x,x,x,x,x;
2
uint8_t pwmtable_16_B[190] = y,y,y,y,y,y;
3
uint8_t pwmtable_16_C[190] = z,z,z,z,z,z;

und bei der Auswahl entscheidest du nur noch, welches Array zu benutzen 
ist.
1
   ...
2
   uint8_t* useTable;
3
4
   ...
5
6
   switch(a)
7
    {
8
      case 'a':
9
        useTable = pwmtable_16_A;
10
        ComText("Helle Umgebung\n\r");
11
        break;
12
      
13
      case 'b':
14
        useTable = pwmtable_16_B;
15
        ComText("Mittlere Helligkeit\n\r");
16
        break; 
17
      
18
      case 'c':
19
        useTable = pwmtable_16_C;
20
        ComText("Dunkle Umgebung\n\r");
21
        break;
22
23
     default:
24
       ComText("Diese Eingabemöglichtkeit besteht nicht!!!\n\r");
25
   }
26
27
   ....
28
29
   PWM_Func( useTable );
30
   ...

PS: und gewöhn dir grundsätzlich an, dass du 3(!) Character Datentypen 
hast.

 *   'char'    diesen Datentyp benutzt du, wenn du es mit Zeichen
               im Sinne von Textberarbeitung zu tun hast

 *   'uint8_t' (oder auch unsigned char). Diesen Datentyp benutzt du
               wenn du einen 'kleinen Integer' ohne Vorzeichen
               benötigst. Also das, was traditionell ein Byte ist.

 *   'int8_t'  (oder auch signed char). Diesen Datentyp benutzt du
               wenn du einen 'kleinen Integer' mit Vorzeichen
               benötigst. Also dann wenn du zb Umgebungstemperaturen
               bei uns speichern musst. Die sind 'selten' ausserhalb
               des Bereichs -128 bis +127 Grad Celsius.


Deine PWM Werte sind im weitesten Sinne einfach nur Bytes. Also 'kleine 
Integer ohne Vorzeichen'. Daher ist uint8_t der richtige Datentyp dafür. 
Du hast es hier nicht mit Textverarbeitung zu tun (ala an den String 
"Hallo " den String "World" anhängen), daher solltest du NICHT char 
benutzen!

von Max (Gast)


Lesenswert?

Ok, danke erstmal!!
Habs jetzt folgendermaßen geändert:

main.c
1
uint8_t pwmtable_16_A[190] = {X,X,X,X,X};                //<--A
2
    uint8_t pwmtable_16_B[190] = {Y,Y,Y,Y};  //<--A
3
    uint8_t pwmtable_16_C[190] = {Z,Z,Z,Z};  //<--A
4
    
5
    char a;
6
    uint8_t useTable;
7
    a = uart_getc();  
8
    
9
    switch(a)
10
    {
11
      case 'a':
12
            
13
          useTable = pwmtable_16_A;  //<--B
14
          ComText("Helle Umgebung\n\r");
15
          
16
      break;
17
      
18
      case 'b':
19
              
20
          useTable = pwmtable_16_B;  //<--B
21
          ComText("Mittlere Helligkeit\n\r");
22
23
      break; 
24
      
25
      case 'c':
26
          
27
          useTable = pwmtable_16_C;  //<--B
28
          ComText("Dunkle Umgebung\n\r");
29
30
      break;
31
32
      default:
33
          
34
          ComText("Diese Eingabemöglichtkeit besteht nicht!!!\n\r");
35
36
    }

Funktion in pwm.h
1
void DimmLed(uint16_t delay, uint8_t* useTable)
2
  {
3
  int16_t tmp;
4
  
5
  //-->LED Dimmen
6
  for(tmp = 1; tmp < ARRAY_SIZE(useTable); tmp++)
7
    {
8
    OCR1A = useTable[ARRAY_SIZE(useTable) - tmp];
9
    my_delay( delay );
10
    }
11
    
12
  }

funktionsaufruf in main.c
1
            DimmLed(useTable, step_time);
2
            OCR1A = 0;                  //LED-Dimm, anschließend Lichtal aus

Ach ja sorry, hab vorhin die alte version der Funktion geschickt, aber 
das tut ja nichts zur Sache eigentlich.

Aber jetzt bekomme ich folgende Fehlermeldungen:
A: large integer implicitly truncated to unsigned type
B: assignment makes integer from pointer without a cast

Außerdem kommen im Terminalprogramm nur noch komische Zeichen an, was 
mich auch sehr verwirrt...

Ich probier die ganze Zeit rum und habe auch viel mit dem C-Buch 
probiert, eine Lösung jedoch nicht gefunden... Vielleicht kann mir ein 
geschultes Auge weiterhelfen?

Danke schonmal

von Karl H. (kbuchegg)


Lesenswert?

Max schrieb:

> uint8_t pwmtable_16_A[190] = {X,X,X,X,X};                //<--A
>     uint8_t pwmtable_16_B[190] = {Y,Y,Y,Y};  //<--A
>     uint8_t pwmtable_16_C[190] = {Z,Z,Z,Z};  //<--A
>
>     char a;
>     uint8_t useTable;

Das ich in meiner Version da einen * reingemacht habe, ist kein Zufall 
und auch kein Tippfehler.

Du solltest wenigstens versuchen zu verstehen, was ich dir da 
vorprogrammiert habe. Das ist alles Grundlagen C, 5. Stunde: Arbeiten 
mit Arrays und Array-Pointer Dualismus.

> und habe auch viel mit dem C-Buch probiert
Wenn du es nicht systematisch durcharbeitest (am besten auf einem PC), 
dann ist das genausogut, wie wenn du es dir unter den Kopfpolster legst. 
Programmiersprachen sind systematisch aufgebaut! Nur dann wenn man das 
System kennt und auch systematisch lernt, fügen sich die Einzelteile zu 
einem Ganzen zusammen. Vorher sind das nur ein Haufen Einzelteile eines 
Puzzle.

Und nein: Bis auf ganz wenige Ausnahmeprogramme, kann man in C auf 
Pointer nicht verzichten. In der einen oder anderen Form tauchen sie 
immer irgendwie auf.

von Max (Gast)


Lesenswert?

Ohh misst, ja Tippfehler, tut mir leid!

Aber leider ändert sich dadurch auch nix, am Monitor kommen immer noch 
hyroglyphen und die werte aus den pwmtable verwendet er auch net... Also 
Fehlermeldung A: ist immer noch da

von Karl H. (kbuchegg)


Lesenswert?

Da du dein Programm nicht in seiner vollen Pracht herzeigst, kann man 
dazu auch herzlich wenig sagen.

uint8_t pwmtable_16_A[190] = {X,X,X,X,X};

Die Fehlermeldung sagt:
A: large integer implicitly truncated to unsigned type

'A large integer' und aus dem Zusammenhang ist klar das es sich dabei 
nur um eine der Zahlen auf der rechten Seite des = handeln kann, 
'implicitly truncated'  diese wird also implizit (d.h. 'ohne das du es 
hingeschrieben hast'), 'truncated to unsigned type'  abgeschnitten auf 
den Datentyp und zwar auf unsigned, so dass er in einen uint8_t passt, 
denn auf der linken Seite wird ja ein Array von uint8_t angelegt.

Was ist an dieser Fehlermeldung missverständlich?



PS: Ich hab mich bei den Datentypen an 'Random' orientiert. Das war 
keine so gute Idee, denn ich sehe gerade, dass dein Original ein 
uint16_t gewesen wäre.

von Max (Gast)


Lesenswert?

Ok, dann machts Sinn... habe das ganze jetzt auf uint16_t geändert => 
keine Fehlermeldung mehr im AVR Studio, doch leider auch gar nix mehr im 
Terminalprogramm und kein mux vom µC.

Das ganze Programm kann ich hier leider nicht reinstellen, weil es Teil 
von mehreren Bachelorarbeiten ist und ich dann eins auf den Deckel 
bekomme leider...

Woran könnte des denn noch liegen, oder geht das nur mit vollständigem 
Programmcode?

von Karl H. (kbuchegg)


Lesenswert?

Max schrieb:

> Das ganze Programm kann ich hier leider nicht reinstellen, weil es Teil
> von mehreren Bachelorarbeiten ist und ich dann eins auf den Deckel
> bekomme leider...

Ooops.
Dann bin ich sowieso raus.
Ich hab nämlich ein Problem damit, wenn jemand einen akademischen Grad 
für etwas bekommt, was er nicht beherrscht.

von Max (Gast)


Lesenswert?

Ansich eine sehr lobenswerte Einstellung, in dem Fall für mich bissi 
blöd ;) aber ist ok...muss ich selber weiter basteln und hoffen, dass es 
bald klappt, da bei der BA (3 Monate) ja kaum noch Zeit zum groß 
einarbeiten und probieren bleibt ;)

von STK500-Besitzer (Gast)


Lesenswert?

Max schrieb:
> .muss ich selber weiter basteln und hoffen, dass es
> bald klappt, da bei der BA (3 Monate) ja kaum noch Zeit zum groß
> einarbeiten und probieren bleibt ;

lol

Sollte ein Bachlor wirklich basteln oder szstematisch eine Lösung 
finden?
Meine Diplomarbeit war auch nur für 3 Monate angesetzt, musste aber um 
einen verlängert werden, da damals plötzlich AVR-Controller Mangelware 
waren, und ich einen versehentlich gehimmelt hatte.
Besorg dir die C-Bibel (Kernighan & Ritchie) auch gerne in Deutsch - die 
sollte inzwischen nicht mehr die Wörter "Kellerspeicher" etc. verwenden.
In dem Buch sind wunderbar Arrays erklärt und der Zugriff darauf 
erklärt...

von Max (Gast)


Lesenswert?

Ja basteln ist doch ein synonym für systematische Lösungsfindung oder 
nicht?! :P

Ok danke, ich werde mir dieses Buch dann schleunigst mal besorgen und 
hoffen, dass damit Licht ins Dunkel kommt...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.