Forum: Mikrocontroller und Digitale Elektronik UART RXC Interrupt


von Alex V. (bastel_alex) Benutzerseite


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...

von Dennis X. (Gast)


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.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Die delay habe ich da nur wegen dem led-blinken drin - und das wollte 
ich gerne in der ISR damit ich weiß wenn sie aufgerufen wird. Das kommt 
da später schon noch raus, ist aber jetzt nicht der grund für das 
nicht-funktionieren oder?

von Karl H. (kbuchegg)


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!

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Herzlichen Dank Karl Heinz!
Ich schreibs mir hinter die Ohren!

von Dennis X. (Gast)


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);

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Dennis X. schrieb:
> Bit-UND realisieren:
> UCSR0B |= (1<<RXCIE0);

ist ein Bit-ODER oder? Danke aber, der übersichtlichkeit halber nutze 
ich das vll. manchmal

von Dennis X. (Gast)


Lesenswert?

Zu früh am Morgen... ;-)

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

;P kenne ich

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.