Ich steh gerade mal im Wald [C] #include <avr/io.h> #include <avr/delay.h> #define SYSCLK 1048576 //intern 1Mhz = 2^20 #define BAUD 9200 #define UBRR_BAUD ((SYSCLK/(16*BAUD))-1) /* USART initialisieren */ void uart_init(void); int main(void) { unsigned char buffer; DDRD |= (1 << DDD7); //Ausgang PORTD |= (1 << PD7); //High /* USART initialisieren */ uart_init(); while (1) { /* Warten bis Daten empfangen wurden */ while ( !(UCSRA & (1<<RXC)) ); PORTD &= ~(1 << PD7); _delay_ms(300); /* Empfangsregister auslesen */ buffer = UDR; /* Warten bis der Sendepuffer frei ist */ while ( !( UCSRA & (1<<UDRE)) ); PORTD |= (1 << PD7); /* Daten in den Puffer schreiben und damit senden */ UDR = buffer; } } /* USART initialisieren */ void uart_init(void) { /* Baudrate einstellen ( Normaler Modus ) */ UBRRH = (unsigned char) (UBRR_BAUD>>8); UBRRL = (unsigned char) UBRR_BAUD; /* Aktivieren von receiver und transmitter */ UCSRB = (1<<RXEN)|(1<<TXEN); // 8 Datenbits, 1 Stoppbit UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); [\C] Wenn ich über Bray-Terminal was sende, leuchtet eine LED und das Empfangene wird wieder zurück gesendet. Nur ... die LED leuchtet brav so wie es sein soll. Aber das Empfangene im Terminal ist 0x00 und darauf folgend 0xC0, egal was ich sende. Auch wenn ich einen String sende. Was ist falsch ??
> #define SYSCLK 1048576 //intern 1Mhz = 2^20
Nein, 1 MHz ist 1 MHz ist 1 MHz und nicht 1 MiHz = 1,049 MHz.
#define SYSCLK 1000000ul
oder besser
#define F_CPU 1000000ul
(dieser Makro hat sich irgendwie eingebürgert dafür).
Ich dachte erst, > #define SYSCLK 1048576 //intern 1Mhz = 2^20 > #define BAUD 9200 > #define UBRR_BAUD ((SYSCLK/(16*BAUD))-1) könnte zufällig den richtigen Wert liefern, aber: 1048576/(9200*16)=7, Gegenprobe: 1000000/(7*16)=8928 und das ist daneben genug... Falk P.S.: RS232 ist alles andere als trivial. Wenn man alle Möglichkeiten berücksichtigt, einen Fehler zu machen, kommt man auf eine Erfolgsquote von ca. 2^10:1 ;-)
Danke. Ich habs jetzt abgeändert. Funktioniert auch. Aber eine kleine Frage hab ich noch. Ich habe stehen:
1 | // 8 Datenbits, 2 Stoppbit
|
2 | UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); |
Nach dem AVR-GCC Tutorial und einigen Beispielen im WWW müsste das Terminal-Programm auch auf 8Daten, 2Stopp eingestellt werden. Stelle ich es auf 8Daten,2Stopp kommen alle Ziffern zurück. Buchstaben jedoch werden verfälscht. Binär für ein 'a' kommt an: 11100001b Stelle ich es auf 7Daten,2Stopp kommt alles richtig zurück. Jetzt kommt für 'a': 01100001b (?? 8te bit nicht gesendet ??) Warum??
"Stelle ich es auf 8Daten,2Stopp kommen alle Ziffern zurück. Buchstaben jedoch werden verfälscht." Das liegt daran: #define SYSCLK 1048576 //intern 1Mhz = 2^20 Genauer an dem Wörtchen "intern" Mehr sag ich dazu nicht, zweimal die Woche reicht mir, hab ja schon Fusseln am Mund. Peter
Homer: > "Stelle ich es auf 8Daten,2Stopp kommen alle Ziffern zurück. > Buchstaben jedoch werden verfälscht." Peter: > Das liegt daran: > #define SYSCLK 1048576 //intern 1Mhz = 2^20 > Genauer an dem Wörtchen "intern" Er hat ja "etwas" abgeändert. Die wahrscheinlichsten Fehler: 1) 9600Bd mit ca. 1MHz ergibt einen Fehler >7% (Wenn U2X==0) 2) 9200 != 9600, 2^20 != 10^6 3) Der RC-Oszillator ist für sowas nicht gut geeignet. Wenn 1) und 2) korrigiert sind, könnte es trotz 3) sogar oft funktionieren. > Mehr sag ich dazu nicht, zweimal die Woche reicht mir, hab ja > schon Fusseln am Mund. Deswegen tippe ich mit den Fingern, das gibt zwar Hornhaut, aber die Tasten bleiben trocken ;-) Falk
1 | #include <avr/io.h> |
2 | |
3 | #define F_CPU 1000000ul
|
4 | #define BAUD 9600
|
5 | #define UBRR_BAUD ((F_CPU/(16l*BAUD))-1)
|
6 | |
7 | /* USART initialisieren */
|
8 | void uart_init(void); |
9 | void uart_send(unsigned char buffer); |
10 | unsigned char uart_receive(void); |
11 | |
12 | int main(void) |
13 | {
|
14 | unsigned char buffer; |
15 | //DDRD |= (1 << DDD7)|(1 << DDD6); //Ausgang
|
16 | //PORTD |= (1 << PD7)|(1 << PD6); //High
|
17 | |
18 | /* USART initialisieren */
|
19 | uart_init(); |
20 | |
21 | while (1) |
22 | {
|
23 | /*
|
24 | // Warten bis Daten empfangen wurden
|
25 | |
26 | PORTD &= ~(1 << PD7);
|
27 | while ( !(UCSRA & (1<<RXC)) );
|
28 |
|
29 | // Empfangsregister auslesen
|
30 | PORTD |= (1 << PD7);
|
31 | buffer = UDR;
|
32 | |
33 | // Warten bis der Sendepuffer frei ist
|
34 | PORTD &= ~(1 << PD6);
|
35 | while ( !( UCSRA & (1<<UDRE)) );
|
36 | |
37 | PORTD |= (1 << PD7)|(1 << PD6);
|
38 | |
39 | // Daten in den Puffer schreiben und damit senden
|
40 |
|
41 | UDR = (buffer);
|
42 | */
|
43 | buffer = uart_receive(); |
44 | uart_send(buffer); |
45 | |
46 | }
|
47 | }
|
48 | |
49 | /* USART initialisieren */
|
50 | void uart_init(void) |
51 | {
|
52 | /* Baudrate einstellen ( Normaler Modus ) */
|
53 | UBRRH = (unsigned char) (UBRR_BAUD>>8); |
54 | UBRRL = (unsigned char) UBRR_BAUD; |
55 | |
56 | /* Aktivieren von receiver und transmitter */
|
57 | UCSRB = (1<<RXEN)|(1<<TXEN); |
58 | |
59 | // 8 Datenbits, 2 Stoppbit
|
60 | UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); |
61 | }
|
62 | void uart_send(unsigned char buffer) |
63 | {
|
64 | // Warten bis Daten empfangen wurden
|
65 | while ( !(UCSRA & (1<<RXC)) ); |
66 | |
67 | /* Warten bis der Sendepuffer frei ist */
|
68 | while ( !( UCSRA & (1<<UDRE)) ); |
69 | |
70 | /* Daten in den Puffer schreiben und damit senden */
|
71 | UDR = (buffer); |
72 | while ( !( UCSRA & (1<<UDRE)) ); |
73 | }
|
74 | |
75 | unsigned char uart_receive(void) |
76 | {
|
77 | // Warten bis Daten empfangen wurden
|
78 | while ( !(UCSRA & (1<<RXC)) ); |
79 | |
80 | // Empfangsregister auslesen
|
81 | // buffer = UDR;
|
82 | |
83 | // Wert zurückgeben
|
84 | return UDR; |
85 | }
|
Ich habs jetzt abgeändert. Funktioniert bei 7Datenbits. Danke also schon mal. 7Datenbits 01100010 'a' 8Datenbits 11100001 'a' (?? 8te Bit nicht gesendet ??)
> #define F_CPU 1000000ul > #define BAUD 9600 > #define UBRR_BAUD ((F_CPU/(16l*BAUD))-1) Rechnen wir mal: 1.000.000/(16*9600)=6,51041 --> UBRRL=6, UBRRH=0 > UBRRH = (unsigned char) (UBRR_BAUD>>8); > UBRRL = (unsigned char) UBRR_BAUD; Und damit stellst Du 1.000.000/(6*16)=10416,66666 --> 10416 Baud ein. Schreibe mal UCSRA |= (1 << U2X); UBRR = 12; //Statt UBRRL=... und UBRRH=... in die Initialisierung. Warum das dann klappt, steht in http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf genau erklärt. Falk
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.