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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.