UART RXC Interrupt

OP Persönliche Seite #3489998
Lesenswert?

Hallo,

ich versuche mich grade das erste mal mit der USART Schnittstelle meines 
atmega644.

Senden und emfpangen einzelner Zeichen per Polling funktioniert, jetzt 
wollte ich mich an die Interrupts herantrauen. Der Code (siehe Unten) 
läuft aber noch nicht, ich bin nur nicht sicher wieso - die 
Receive-Complete (RXC)-ISR wird irgendwie nicht aufgerufen (LED-Blinker 
als Kontrolle).
Woran kann das liegen?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdlib.h>
4
#include "Mainboard_UART_functions.h"
5
#include <util/delay.h>
6

7
unsigned char buffer;
8

9

10
ISR (USART0_RX_vect)
11
{
12
  buffer = UART_receive();
13
  LED2_on();
14
  _delay_ms(500);
15
  LED2_off();
16
  _delay_ms(500);
17
}
18

19
 void UART_Init()
20
 {
21
   // baud Calculation: baud = (fosc/ 16*Baudrate)-0.5
22
   // baud = (20 MHz / 16*9600)-0.5 = 129.708 --> = baud = 130
23
   unsigned int baud = 130;
24
   
25
   //* Set baud rate */
26
   UBRR0H = (unsigned char)(baud>>8);
27
   UBRR0L = (unsigned char)baud;
28
   /* Enable receiver and transmitter */
29
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);
30
   /* Set frame format: 8data, 2stop bit */
31
   UCSR0C = (1<<USBS0)|(3<<UCSZ00);
32
   /* Set Interrupts: RXCIE - RX-Complete, TCVIE - TX-Complete */
33
   UCSR0B = (1<<RXCIE0);
34
   
35
 }
36
 
37
void UART_transmit (unsigned char c) 
38
{
39
  while (!(UCSR0A & (1<<UDRE0))) {}      // Wait until UDRE (UART Data Register Empty)- Bit is set.
40
  UDR0 = c;
41
}
42

43
unsigned char UART_receive (void)        
44
{
45
  // while(!(UCSR0A & (1<<RXC0))) {}        // Wait until RXC (Receive Complete) Flag is set.
46
  return UDR0;
47
}
48

49

50
int main(void)
51
{
52
  /*********************** Initialization ***********************/
53
  //Port Directions        
54
  DDRC= 0b01010001;        // SPI Slave select, LEDs                    
55
  DDRD= 0b00001010;        // UART
56
  
57
  UART_Init();          // UART Initialisierung
58
  sei();              // Globale Interrupts enable
59
  
60
    while(1)
61
    {
62
    
63
    UART_transmit(buffer);
64
    _delay_ms(1000);        
65

66
    
67
    }
68
}

Was ich mit dem code oben erreichen wollte:
Im Terminal einen bytewert senden - µC bekommt ihn und spiegelt ihn 
(sendet alle sekunde den letzten eingegebenen Wert zurück).
Wieso wird die ISR nicht aufgerufen? das RXCIE Bit in UCSRB habe ich 
gesetzt...
Gast #3490009
Lesenswert?

Setze dir doch zuerst mal ein Flag, dass überhaupt etwas übertragen 
wurde und lass die _delay_ms aus den Interuppts raus. Das kann man alles 
in der Main laufen lassen. Einfach warten solange bis das Flag gesetzt 
ist und dann zurück schicken.
#3490016
Lesenswert?

1
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);
2
   /* Set frame format: 8data, 2stop bit */
3
   UCSR0C = (1<<USBS0)|(3<<UCSZ00);
4
   /* Set Interrupts: RXCIE - RX-Complete, TCVIE - TX-Complete */
5
   UCSR0B = (1<<RXCIE0);

Gratulation. Mit der zweiten Zuweisung an UCSR0B um den Interrupt 
einzuschalten, hast du soeben Sender und Empfänger wieder abgeschaltet.

Mein Tipp wäre: vermeide solche Mehrfach-Operationen. Wenn du in einem 
Register BIts setzen willst, dann mach das in EINER Anweisung.
Das ist beim Schreiben besser, weil es den Fehler verhindert, den du 
hier gemacht hast. Und es ist auch beim Lesen besser, weil man den Code 
dann nicht absuchen muss, ob es neben dem betrachteten Statement noch 
andere Operationen an diesem Register gibt oder nicht.
1
   UCSR0B = (1<<RXEN0)|(1<<TXEN0) |
2
            (1<<RXCIE0);
3
   /* Set frame format: 8data, 2stop bit */
4
   UCSR0C = (1<<USBS0)|(3<<UCSZ00);

ist nicht besser oder schlechter zu lesen als deine Version. Aber sie 
hat weniger Fehlerpotential!
Gast #3490024
Lesenswert?

Karl Heinz schrieb:
> UCSR0B = (1<<RXEN0)|(1<<TXEN0);
>    /* Set frame format: 8data, 2stop bit */
>    UCSR0C = (1<<USBS0)|(3<<UCSZ00);
>    /* Set Interrupts: RXCIE - RX-Complete, TCVIE - TX-Complete */
>    UCSR0B = (1<<RXCIE0);

Wenn du es dennoch so machen WILLST, solltest du das ganze über eine 
Bit-UND realisieren:
UCSR0B |= (1<<RXCIE0);

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