Hallo, ich habe ein vllt ganz triviales Problem. Ich bekomme seriell Daten (9600)von einem PC auf einen Mega16 (8MHz). Das Problem ist jetzt, dass ich nur das erste Byte mitbekomme. Danach empfange ich nur noch Nullen. Kann es sein dass der MC zu langsam ist? Die ISR wird ja auch erst aufgrufen wenn Daten im Puffer sind oder? Dann kommen je bereits die nächsten an, während ich noch die ersten verabreiten will? Stimmt das so weit und wie kann man das lösen? Vielen Dank schon mal Florian
Wenn Du bei 9600 Baud einen Buffer-Overflow kriegst, dann stimmt mit großer Wahrscheinlichkeit in Deinem Programm etwas fundamentales nicht. Da Du uns den Programmcode aber nicht zeigst, kann man da auch nicht viel zu sagen! Bei 9600 Baud dauert die Übertragung eines Zeichens ungefähr 1 ms. Das ist für einen µC ne halbe Ewigkeit, wenn man nicht gerade innerhalb der ISR mit sperrigen Bibliotheksfunktionen arbeitet, was man generell nicht tun sollte. Einen Buffer-Overflow kann man übrigens detektieren, dafür gibts ein extra Flag...
> ich habe ein vllt Ein was? > Ich bekomme seriell Daten (9600)von einem PC auf einen Mega16 (8MHz). > Das Problem ist jetzt, dass ich nur das erste Byte mitbekomme. Danach > empfange ich nur noch Nullen. Kann es sein dass der MC zu langsam ist? Eher nicht. Bei 9600 Baud und 8 Mhz hat dein AVR pro Byte über 8000 Taktzyklen zur Verfügung. > Die ISR wird ja auch erst aufgrufen wenn Daten im Puffer sind oder? Ja. > Dann kommen je bereits die nächsten an, während ich noch die ersten > verabreiten will? Ja, aber das macht nichts, da die Schnittstelle double buffering verwendet. Die beiden Puffer werden nicht getauscht, solange du nicht gelesen hast. > Stimmt das so weit und wie kann man das lösen? Keine Ahnung. Du hast ja nicht gezeigt, wie du es machst.
Danke erstmal allen. Hier mein Programm:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | |
5 | #define SYSCLK 8000000
|
6 | #define BAUD 9600UL
|
7 | #define UBRR_BAUD ((SYSCLK/(16*BAUD))-1)
|
8 | |
9 | void uart_init(void); |
10 | |
11 | uint8_t BYTE0 = 0; |
12 | uint8_t BYTE1 = 0; |
13 | |
14 | |
15 | int main(){ |
16 | |
17 | uart_init(); |
18 | sei(); |
19 | |
20 | |
21 | while(1){ |
22 | |
23 | if(BYTE1 != 0){ |
24 | while ( !( UCSRA & (1<<UDRE)) ); |
25 | UDR = BYTE0; |
26 | while ( !( UCSRA & (1<<UDRE)) ); |
27 | UDR = BYTE1; |
28 | |
29 | BYTE0 = 0; |
30 | BYTE1 = 0; |
31 | }
|
32 | |
33 | }
|
34 | |
35 | return 0; |
36 | }
|
37 | |
38 | |
39 | void uart_init(void) |
40 | {
|
41 | |
42 | UBRRH = (unsigned char) (UBRR_BAUD>>8); |
43 | UBRRL = (unsigned char) UBRR_BAUD; |
44 | |
45 | UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); |
46 | UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); |
47 | }
|
48 | |
49 | |
50 | |
51 | |
52 | ISR(USART_RXC_vect) |
53 | {
|
54 | uint8_t tmp_sreg = SREG; |
55 | |
56 | cli(); |
57 | |
58 | if (BYTE0 == 0){ |
59 | BYTE0 = UDR; |
60 | } else { |
61 | BYTE1 = UDR; |
62 | }
|
63 | |
64 | SREG = tmp_sreg; |
65 | }
|
Nicht Bekannt wrote: > Danke erstmal allen. Hier mein Programm: > ISR(USART_RXC_vect) > { > uint8_t tmp_sreg = SREG; > > cli(); > > if (BYTE0 == 0){ > BYTE0 = UDR; > } else { > BYTE1 = UDR; > } > > SREG = tmp_sreg; > } Lass das SREG in Ruhe. Du programmierst in C und musst dich nicht mit so niedrigen Dingen wie den tatsächlichen CPU Registern herumschlagen. Auch der cli() ist unnötig. Wenn eine ISR betreten wird, dann werden die Interrupts von Haus aus disabled und beim verlassen der ISR wieder angeschaltet. Mach mal die beiden Variablen BYTE1 und BYTE0 als volatile Variablen: volatile uint8_t BYTE0 = 0; volatile uint8_t BYTE1 = 0;
Das cli() und das SREG-Sichern in der ISR übernimmt der Compiler(*). Das solltest Du weglassen. Abgesehen davon solltest Du mal überlegen, wie das mit senden und empfangen läuft und v.a. dran denken, was passiert, wenn gerade nach dem Ende des Sendens die ISR aufgerufen wird und nach dem Rücksprung beide BYTEs auf 0 gesetzt werden... (*)Das cli() macht genaugenommen die Hardware und nicht der Compiler...
Kann es leider erst wieder am WE testen, werden dann berichten...
Das mit dem Senden ist im Moment nur um zu sehen ob er beide bekommen hat.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.