Hi, ich versuche mich gerade an dem Aufbau einer seriellen komunikation
zwischen einem atmega88 und dem rechner.
einzelne zeichen zu senden war nicht das problem. Bei dem versuch eine
Zeile zu senden stoße ich auf probleme.
ziel ist es, den String in einen puffer zu kopieren und den dann nach
und nach zu senden. dass soll alles im hintergrund geschehen, gesteuert
durch den interrupt vector "USART_TX_vect".
mein code sieht wie folgt aus:
1 | #ifndef F_CPU
|
2 | #define F_CPU 12000000UL // Systemtakt in Hz - Definition als unsigned long beachten
|
3 | // Ohne ergeben sich unten Fehler in der Berechnung
|
4 | #endif
|
5 |
|
6 | #define BAUDRATE 9600UL // Baudrate
|
7 |
|
8 | // Berechnungen
|
9 | #define BAUD_PRESCALE (F_CPU/(16*BAUDRATE)-1)
|
10 | #define BAUD_REAL (F_CPU/(16*(BAUD_PRESCALE+1))) // Reale Baudrate
|
11 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUDRATE) // Fehler in Promille, 1000 = kein Fehler.
|
12 |
|
13 | #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
|
14 | #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
|
15 | #endif
|
16 |
|
17 | #include <avr/io.h>
|
18 | #include <avr/interrupt.h>
|
19 | #include <util/delay.h>
|
20 |
|
21 | char inbuffer[32]; //einganspuffer
|
22 | char *inbufferpos=&inbuffer[0]; //positions zeiger
|
23 | char outbuffer[32]; //ausgangspuffer
|
24 | char *outbufferpos=&outbuffer[0]; //positionszeiger
|
25 |
|
26 | void send(char * pstr){
|
27 | while ((1<<TXCIE0)& UCSR0B); //warten bis Senderoutine fertig ist
|
28 | outbufferpos=&outbuffer[0]; //Zeiger auf Anfang setzen
|
29 | while (*pstr!=0x00){ //prüfe auf String Ende
|
30 | *outbufferpos = *pstr; //kopiere Zeichen
|
31 | outbufferpos++; //zeiger incrementieren
|
32 | pstr++;
|
33 | }
|
34 | *outbufferpos=0x00; //String-Ende in Puffer schreiben
|
35 |
|
36 | outbufferpos=&outbuffer[0]; //Zeiger auf Anfang setzen
|
37 |
|
38 | UCSR0B |= (1<<TXCIE0); //Erfolgreich gesendet interrupt aktiviren
|
39 |
|
40 | UDR0= *outbuffer; //erstes Zeichen senden
|
41 | outbufferpos++; //zeiger auf 2. Zeichen setzen
|
42 | }
|
43 |
|
44 | void long_delay(uint16_t ms) {
|
45 | for(; ms>0; ms--) _delay_ms(1);
|
46 | }
|
47 |
|
48 | int main()
|
49 | {
|
50 | //USART Initialisieren
|
51 | UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry
|
52 | UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01); // Use 8-bit character sizes
|
53 | UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
|
54 | UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
|
55 | UCSR0B |= (1 << RXCIE0); // Enable the USART Recieve Complete interrupt (USART_RXC)
|
56 |
|
57 | sei();
|
58 | char str[]="Hallo Welt";
|
59 |
|
60 | while (1) {
|
61 |
|
62 | while (!(UCSR0A & (1<<UDRE0)));
|
63 | send(& str[0]);
|
64 |
|
65 | long_delay(500);
|
66 | PORTB |= (1<<PORTB0);
|
67 | long_delay(500);
|
68 | PORTB &=~(1<<PORTB0);
|
69 |
|
70 | }
|
71 | }
|
72 |
|
73 | ISR(USART_TX_vect)
|
74 | {
|
75 |
|
76 | if (*outbufferpos!=0x00)
|
77 | {
|
78 | while (!(UCSR0A & (1<<UDRE0)));
|
79 | UDR0=*outbufferpos;
|
80 | outbufferpos++;
|
81 | }
|
82 | else
|
83 | {
|
84 | while (!(UCSR0A & (1<<UDRE0)));
|
85 | UDR0=0x0a;
|
86 | while (!(UCSR0A & (1<<UDRE0)));
|
87 | UDR0=0x0d;
|
88 | while (!(UCSR0A & (1<<UDRE0)));
|
89 | UCSR0B &= ~(1<<TXCIE0);
|
90 |
|
91 | }
|
92 | }
|
Nach dem Reset wird genau einmal "Hallo Welt" übertragen. Dannach
erhalte ich nur noch das "H" im sekundentakt.
also laut dem internen debugger von avr-studio funktioniert die
angelegenheit, auch mehrmals, aber die realität sieht leider anders aus
Jemand ne idee, wo mein fehler liegt?
grüße klaus