Forum: Mikrocontroller und Digitale Elektronik AVR UART auf AT90CAN Problem mit Interrupt?


von Uwe (Gast)


Lesenswert?

Hallo zusammen,

ich versuche gerade, den UART eines AT90CAN ans Laufen zu bringen. Ich 
versuche mich dabei an der Library von Peter Fleury. Ich habe sie nicht 
vollkommen übernommen, sondern nur die entsprechenden Funktionen. Die 
ganze Initialisierung für die verschiedensten Controller habe ich 
rausgenommen und initialisiere ben nur den AT90CAN.

Leider habe ich noch Probleme sie ans Laufen zu bekommen. Es liegt wohl 
weniger an der Lib, als an meiner Initialisierung des UART.

In meiner main.c, will ich testweise folgendes versenden:
1
cli();                       
2
initUSART();                        
3
sei();
4
  
5
uart_puts("String aus SRAM\n");
6
uart_putc('a');

Hier nun das Problem und unten dann der Code.

Wenn ich in der Funktion "uart_putc" das "UDR0= 'x';" einkommentiere, 
wird das 'x' gesendet und vom PC empfangen, wenn ich, wie oben
angegeben, uart_putc('a'); z.B. angebe. Die Sache ist nun, dass der 
String oder das 'a' von oben nicht gesendet werden.
Dadurch, dass das 'x' testweise gesendet werden kann, sieht man ja, dass 
es grundsätzlich funktioniert.
Anscheinend kommen die Interrupts nicht, weswegen der oben angegebene 
String oder auch nur das 'a' nicht gesendet werden, wie es scheint. Die 
ISR(USART0_TX_vect) wird anscheinend nicht aufgerufen.
Somit denke ich, dass es vielleicht an der Initialisierung der 
Interrupts des UART liegt. Leider fällt mir da weiter nichts auf.

Ich würde mich freuen, wenn jemand drüber schauen und vielleicht sogar 
den Fehler finden würde.

Vielen dank schon einmal.

Uwe

In der Datei uart.c habe ich folgenden Code (Auszug):
1
void initUSART(void)        
2
{
3
    UART_Tx_Head = 0;
4
    UART_Tx_Tail = 0;
5
    UART_Rx_Head = 0;
6
    UART_Rx_Tail = 0;
7
  
8
  
9
  UART0_MODE |= (1<<UCSZ01)|(1<<UCSZ00);  
10
                                            
11
                      // 1 Stoppbit                        
12
    UBRR0 = UBRR_VAL;     // UBRR_VAL  -> ((F_CPU+UART_BAUD*8)/(UART_BAUD*16)-1)        
13
    UART0_CONTROL |= (1<<RXCIE0)|(1<<TXEN0)|(1<<RXEN0);    
14
                        // UART TX,RX Pin einschalten
15
                        // UCSRnB – USART Control and Status Register n B
16
                        // RXCIEn: RX Complete Interrupt Enable
17
                        // TXCIEn: TX Complete Interrupt Enable
18
                        // RXENn:  Receiver Enable n
19
                        // TXENn:  Transmitter Enable n
20
21
  
22
}
23
24
/***********************************/
25
26
void uart_putc(unsigned char c)
27
{
28
    unsigned char tmphead;
29
     
30
    tmphead = (UART_Tx_Head + 1) & UART_TX_BUFFER_MASK;
31
    
32
    while (tmphead == UART_Tx_Tail)
33
  {
34
        ;/* wait for free space in buffer */
35
    }/* while (tmphead == UART_Tx_Tail) */
36
    
37
    UART_Tx_Buf[tmphead] = c;
38
    UART_Tx_Head = tmphead;
39
  //UDR0= 'x';    // Zum Test eingefügt. Dieses 'x' wird gesendet und vom PC empfangen, wenn man es wieder
40
                //  einkommentiert.
41
    UART0_CONTROL |= 1<<UDRIE0;  // Bit 5 – UDRIEn: USARTn Data Register Empty Interrupt Enable
42
}
43
44
/***********************************/
45
46
void uart_puts(unsigned char *s)    
47
{                                       
48
  while(*s)                           
49
  {
50
    uart_putc(*s++);                
51
  }/* while(*s) */                        
52
}
53
54
55
/***********************************/
56
57
ISR(USART0_TX_vect)
58
{
59
    unsigned char tmptail;
60
   
61
    if (UART_Tx_Head != UART_Tx_Tail) 
62
  {
63
        /* calculate and store new buffer index */
64
        tmptail= (UART_Tx_Tail + 1) & UART_TX_BUFFER_MASK;
65
        UART_Tx_Tail = tmptail;
66
        /* get one byte from buffer and write it to UART */
67
        UART0_DATA = UART_Tx_Buf[tmptail];  /* start transmission */
68
    }
69
  else
70
  {
71
        /* tx buffer empty, disable UDRE interrupt */
72
        UART0_CONTROL &= ~(1<<UART0_UDRIE);
73
    }
74
}/* ISR(USART0_TX_vect) */

von Karl H. (kbuchegg)


Lesenswert?

>     UART0_CONTROL |= (1<<RXCIE0)|(1<<TXEN0)|(1<<RXEN0);


Irgendwie fehlt mir da die Freigabe des Transmit Interrupts.

von Mac G. (mac_g)


Lesenswert?

Hallo,

hast du mal versucht, ob das Senden funktioniert, wenn du die Lib von 
Peter Fleury unverändert übernimmst?
Normalerweise brauchst du die "unnötigen" Controllerfunktionen nicht zu 
entfernen. Durch die ganzen Preprozessoranweisungen wird nur der Teil 
für den ausgewählten Controller kompiliert.

von Uwe (Gast)


Lesenswert?

Hallo,

ich habe nun einmal folgendes geändert:

>>     UART0_CONTROL |= (1<<RXCIE0)|(1<<TXEN0)|(1<<RXEN0);


>Irgendwie fehlt mir da die Freigabe des Transmit Interrupts.

...wurde zu
1
UART0_CONTROL |= (1<<RXCIE0)|(1<<TXCIE0)|(1<<TXEN0)|(1<<RXEN0);

Die "uart_putc" sieht nun wie folgt aus:

Aber ganz läuft es noch nicht.

Es wird nichts gesendet bei der Kombinaion:
1
//UDR0= 'b';
2
UART0_CONTROL |= 1<<UDRIE0;
3
4
und
5
6
//UDR0= 'b';
7
//UART0_CONTROL |= 1<<UDRIE0;

Bei folgender Kombination wird nur das 'b' gesendet:
1
UDR0= 'b';
2
UART0_CONTROL |= 1<<UDRIE0;

Bei folgender Kombination werden die Daten gesendet, aber eben auch die 
'b's
1
UDR0= 'b';
2
//UART0_CONTROL |= 1<<UDRIE0;

>hast du mal versucht, ob das Senden funktioniert, wenn du die Lib von
>Peter Fleury unverändert übernimmst?

Das  habe ich noch nicht versucht. Ich wollte das Ganze halt einfach 
abspecken, auch wenn beim Compilen natürlich sonst auch der Rest 
wegfällt. Wenn ich den fehler gar nicht finde, werde ich die Lib auf 
jeden Fall komplett testen.

Vielen dank schon einmal.

Uwe

von Karl H. (kbuchegg)


Lesenswert?

Uwe schrieb:
> Hallo,
>
> ich habe nun einmal folgendes geändert:
>
>>>     UART0_CONTROL |= (1<<RXCIE0)|(1<<TXEN0)|(1<<RXEN0);
>
>
>>Irgendwie fehlt mir da die Freigabe des Transmit Interrupts.
>
> ...wurde zu
>
>
1
> UART0_CONTROL |= (1<<RXCIE0)|(1<<TXCIE0)|(1<<TXEN0)|(1<<RXEN0);
2
>
>

mein Fehler.
Diesen Interrupt braucht die Fleury Lib ja gar nicht.

Also nimm ihn wieder raus. Dein Problem ist etwas anderes.
Deine uart_putc gibt den "Data Register Empty" Interrupt frei, was ja 
auch richtig ist. In diesem Interrupt wird ein Zeichen in die UART 
geschaufelt und wenn die UART wieder aufnahmebereit ist, fordert sie das 
nächste Zeichen per ISR Aufruf an.

Soweit so gut.

Nur:

ISR(USART0_TX_vect)

Das ist nicht der Data Register Empty Interrupt Vektor.

(Es sei denn, da gibt es noch ein #define welches du nicht gezeigt hat 
und welches USART0_TX_vect auf den richtigen "Data Register Interrupt 
Vektor" verbiegt)

von Uwe (Gast)


Lesenswert?

Hallo,

vielen Dank! Jetzut funktioniert es!

Das Folgende ist nun wohl das Richtige:
1
ISR(USART0_UDRE_vect)

Vielen Dank!

Uwe

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.