Forum: Mikrocontroller und Digitale Elektronik WinAvr - Variable wird nicht von einer *.c in die andere übernommen


von Markus W. (kornbanane)


Lesenswert?

Hallo,

ich programmiere meinen Atmega16 in C mit WinAvr und stehe gerade voll 
auf dem Schlauch.

Also nur kurz zum Programm

Es geht einfach nur darum ein Telegramm über die UART0 Schnittstelle was 
vom PC an den µC empfangen wird solange in einen Empfangsbuffer zu 
schreiben, bis das Telegrammendezeichen (CR) empfangen wird.
Wenn das Telegramm fertig empfangen ist wird die Variable 
uart0_rxd_complete auf 1 gesetzt und das nachfolgende Programm kann 
irgendwas machen.

Ich habe 4 Dateien: main.c main.h uart.c uart.h

Hier jetzt nur mal die für mein Problem relevanten Codeausschnitte

uart.c:
1
//---------------------------------------------------------------------------
2
// ISR(USART_TXC_vect)
3
//
4
// functiondescription:  Interrupt für USART0 recieve. Schreibt die empfangenen Zeichen in einen Empfangsbuffer bis das Endezeichen (CR=0x0D) erkannt wurde
5
//
6
// hand over:
7
//  - input parameters: nothing
8
// returns:
9
//  - return parameter: nothing
10
//---------------------------------------------------------------------------
11
ISR(USART_RXC_vect)
12
{
13
  if(UDR!=0x0D)     // Kein Endezeichen empfangen ?
14
  {
15
    uart0_rx_buffer[uart0_rx_buffer_pointer]=UDR;
16
    uart0_rx_buffer_pointer++;
17
    if(uart0_rx_buffer_pointer>255) uart0_rx_buffer_pointer=0;    // Zur Sicherheit, kann hier aber nicht passieren, da unsigned char sowieso überläuft 
18
  }
19
  else        // Wenn ein Endezeichen empfangen wurde
20
  {
21
    uart0_rx_buffer[uart0_rx_buffer_pointer]=UDR;          // Das Endezeichen (CR=0xOD) wird als letztes in den Empfangsbuffer geschrieben
22
    uart0_rx_buffer_pointer=0;
23
    uart0_rxd_complete=1;
24
    PORTC=0x0A;
25
  }
26
}

main.h
1
//-------------------
2
// begin extern vars 
3
//-------------------
4
5
extern unsigned char uart0_rxd_complete;
6
7
//-----------------
8
// end extern vars 
9
//-----------------


main.c
1
while (1)
2
  {
3
  
4
      if(uart0_rxd_complete==1)
5
    {
6
    
7
      PORTC=0xFF;
8
      uart0_rxd_complete=0;
9
      putstring("\nFolgende Daten wurden empfangen: \n",0);
10
      
11
      while(uart0_rx_buffer[i]!=0x0D)
12
      {
13
        putch(uart0_rx_buffer[i],0);
14
      }
15
      
16
      putch('\n',0);
17
    }
18
    
19
  }


So also nun zum Problem. In der uart.c steckt der empfangsinterrupt. Das 
ganze funktioniert auch, das sehe ich an meinen LED's die ich am PortC 
angeschlossen habe. Wenn das Telegrammendezeichen empfangen wurde wird 
Portc auf 0x0A gesetzt. Gleichzeitig setze ich uart0_rxd_complete=1;.

Jetzt müsste in der main.c die Abfrage if(uart0_rxd_complete==1) true 
ergeben, aber nix da. Für die main.c ist uart0_rxd_complete immer 0 !
Es liegt auch nicht an der Abfrage die Variable ist dort wirklich immer 
0 aber wieso ? Ich habe sie doch in main.h "eingebungen" und main.c ruft 
main.h auf.

Ich dachte das aus irgendeinen Grund generell keine Variable von der 
uart.c in die main.c übertragen werden kann. Hab ich überprüft und es 
geht. Aber wieso dort nicht ? Das Programm ist sehr klein. Die Variable 
wird 100%ig nirgendswo auf 0 gesetzt.

Jetzt hab ich echt kein Plan mehr :(

von Achim K. (aks)


Lesenswert?

Versuchs mal mit
1
extern volatile unsigned char uart0_rxd_complete;

von Markus W. (kornbanane)


Lesenswert?

Danke, man wie blöd ....

Sag mal versteh ich das richtig, dass das jetzt nur eine 
Optimierungssache war die halt in meinem Fall daneben ging. Mit anderen 
Worten bei einem anderem Compiler oder auch bei WinAvr mit anderen 
Einstellungen hätte es auch ohne volatile funktioniert ?

von Thomas M. (langhaarrocker)


Lesenswert?

Naja, ob die Optimierung nun 'daneben' ging, ist Ansichtssache. Es ist 
ja durchaus gut und richtig, wenn ein Compiler nicht unnötig Variablen 
mit vergleichsweise teuren Ram Zugriffen nochmal holt, wenn sie ohnehin 
schon gerade in einem flotten Register gepuffert sind. Nur wenn dann 
durch einen Interrupt diese Pufferung unterwandert wird, gibt's 
Probleme. Genau das zu vermeiden, dafür ist so ein volatile halt gut. 
Die Alternative wäre ja auf Optimierungen zu verzichten.

Man könnte auch auf die Idee kommen dem Compiler die Pufferung zu 
verbieten indem man ihn anweist ein Register für solch eine Variable zu 
reservieren:
register unsigned char uart0_rxd_complete asm("r2");
Aber das ist nicht zu empfehlen, da der Compiler sich durchaus auch 
erlaubt trotzdem das Register für andere Zwecke zu verwenden, wenn ihm 
freie Register ausgehen. Wenn dann ein Interrupt stattfindet und völlig 
andere Werte überschreibt ... viel Spaß bei der Fehlersuche. :)

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.