WinAvr - Variable wird nicht von einer *.c in die andere übernommen

OP #3503190
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 :(
#3503339
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. :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren