ATMega8: USART-RX mit Interrupt

Gast #1107883
Lesenswert?

Hallo,
ich möchte mit einem ATMega8 über die USART Schnittstelle Zeichen lesen 
und das ganze im Interrupt Betrieb. Ein anderer ATMega8 sendet Zeichen, 
was ich mit dem LogicAnalyzer auch überprüft habe. Die Sendefrequenz, 
Parity, Stopbits etc sind natürlich identisch.

Hab schon in anderen Threads gestöbert aber konnte noch nicht finden 
warum das bei mir nicht funktioniert.
Hier der code:
1
#include <avr/io.h>
2

3
#define F_CPU 8000000L 
4

5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#define BAUD 9600L
8

9
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)      //clever runde
10
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //reale Baudrate
11

12
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)      //Fehler in Promille
13

14
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
15
#error Systematischer Fehler in der Baudrate größer 1% und damit zu hoch!
16
#endif
17

18

19
ISR (USART_RXC_vect) {
20
  uint8_t dummy;
21
  dummy = UDR;
22
  PORTB ^= (1<<PB0);   
23
}
24

25

26
int main(void)
27
{
28
   
29
   UBRRH = UBRR_VAL >> 8;
30
   UBRRL = UBRR_VAL & 0xFF;
31
   
32
   
33
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);      //Asynchron 8N1
34
  UCSRA = (1<<U2X);
35
  UCSRB = ( 1 << RXEN ) | (1 << RXCIE);
36
  sei();
37

38
  while (1)
39
  {
40

41
  }
42

43
  return 0;                     
44
}
Gast #1107891
Lesenswert?

Hi!

Jetzt ohne mal deinen Code näher zu betrachten,
du speicherst in
1
ISR (USART_RXC_vect) {
2
  uint8_t dummy;
3
  dummy = UDR;
4
  PORTB ^= (1<<PB0);   
5
}

das Datenbyte nur temporär, dann wird es wieder gelöscht.

Du müsstest z.B. ein globales Array definieren und da die Daten 
reinpacken.

z.B.
1
uint8_t volatile dummy[255];
2
uint8_t volatile Counter;
3

4

5
Counter=0;
6
...
7

8

9
while(1)
10
  {
11
  if (Counter==200)
12
    {
13
    cli(); //nur als Pseudocode zu verstehen
14
    .... //tu irgendwas mit den Daten, ist alles Fehlerfrei??
15
    Counter=0;
16
    ....
17
    sei();
18
    }
19
  }
20

21
ISR (USART_RXC_vect) 
22
{
23
  dummy[Counter] = UDR;
24
  Counter++;
25
  PORTB ^= (1<<PB0);   
26
}
Gast #1107957
Lesenswert?

hehe, man möge mir eine Tischkante reichen ;)

nun jetzt wird der Interrupt nachweislich ausgelöst, aber so ganz das 
erwünschte Ergebnis ist es noch nicht.

Ich hätte jetzt erwartet dass der Interrupt nur pro Byte und nicht pro 
Bit ausgelöst wird.

Denn wenn ich RX und PB0 am LogicAnalyzer anschaue dann sieht das sehr 
ähnlich aus. Sprich wenn sich bei Rx der logische Zustand ändert, tut 
das der beim PB auch. Ich hab mal ein Bild angehängt. Das obere sich 
verändernde Signal ist Rx, das darunter PB0.
Angehängte Dateien:
Gast #1108145
Lesenswert?

also wenn ich eine Variable mitzählen lasse kommt dabei raus dass der 
Interrupt ca 1,6 mal zu oft aufgerufen wird.

Das hier ist der Code des anderen µC der die Bytes sendet:
1
#include <avr/io.h>
2

3
#define F_CPU 8000000L 
4
#include <util/delay.h>
5
#define BAUD 9600L
6

7
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)      //clever runde
8
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //reale Baudrate
9

10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)      //Fehler in Promille
11

12
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
13
#error Systematischer Fehler in der Baudrate größer 1% und damit zu hoch!
14
#endif
15

16

17
int main(void)
18
{
19
   DDRB |= (1<<PB0);
20
   UBRRH = UBRR_VAL >> 8;
21
   UBRRL = UBRR_VAL & 0xFF;
22
  int i = 64;
23
   
24
   
25
  UCSRB = (1<<RXEN)|(1<<TXEN);      //UART TX einschalten
26
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);      //8 data, 2 stop bits
27
  
28
  while (1)
29
  {
30

31
    i++;
32
    if (i>90) i = 65;
33

34
    while (!(UCSRA & (1<<UDRE)))      //warten bis Senden möglich
35
    {
36
    }   
37

38

39
    UDR = i;                     //schreibt das Zeichen x auf die Schnittstelle
40
    PORTB ^= (1<<PB0);
41
    _delay_ms(500);
42
  }
43

44
  return 0;                     
45
}

oder kann das Problem am 8MHz Quarz liegen der bei den 9600 Baud einen 
Fehler macht?
Gast #1108803
Lesenswert?

Quarz?                Quarz?

ja Quarz.

was?


Damit will ich sagen: Ich hab keine Ahnung worauf du hinaus willst.

Aber zu meinem Problem, der Faktor 1,6 hat sich bei genauerer Messung 
als Faktor 2 herausgestellt und kam dadurch zustande, dass beim lesenden 
µC U2X gesetzt war, beim sendenden nicht. Tja.
Jetzt werden sogar die richtigen Zeichen erkannt...Ich bin begeistert :)

Danke für die Hilfestellung.


PS: Das LogicAnalyzer Bild erklärt sich dudurch leider dennoch nicht.

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