Hallo, im Anhang ist meine Routine um das Universal Serial Interface der diversen AVRs zum UART-Daten (8N1) versenden zu überreden. Im Moment läuft es wunderschön auf einem ATTiny25. Wäre super wenn ihr es euch anschauen bzw. Testen würdet. Wenn keine Fehler auftauchen / alles Optimiert wurde, würde ich es in die Codesammlung stellen. Gruß --Daniel [Mod: defekte Version im Anhang zu diesem Beitrag entfernt. Korrigierte Version im folgenden Beitrag.]
:
Verschoben durch Moderator
Ups, da fehl ein .equ in der 34. Zeile. Korrigierte Version im Anhang (wieso kann man seine eigenen Anhänge nicht ändern?!).
Mir ist das mit dem USI viel zu aufwendig. Ich mach das einfach mit Delay:
1 | #define F_CPU 8e6
|
2 | #define BAUD 9600
|
3 | #define STX_PORT PORTB
|
4 | #define STX_BIT 0
|
5 | |
6 | #include <util/delay.h> |
7 | #include <avr/io.h> |
8 | |
9 | void sputchar( uint8_t c ) |
10 | {
|
11 | c = ~c; |
12 | STX_PORT &= ~(1<<STX_BIT); // start bit |
13 | for( uint8_t i = 10; i; i-- ){ // 10 bits |
14 | _delay_us( 1e6 / BAUD ); // bit duration |
15 | if( c & 1 ) |
16 | STX_PORT &= ~(1<<STX_BIT); // data bit 0 |
17 | else
|
18 | STX_PORT |= 1<<STX_BIT; // data bit 1 or stop bit |
19 | c >>= 1; |
20 | }
|
21 | }
|
Das erzeugte Assemblerlisting sieht dann so aus:
1 | void sputchar( uint8_t c ) |
2 | {
|
3 | c = ~c; |
4 | 22: 80 95 com r24 |
5 | STX_PORT &= ~(1<<STX_BIT); // start bit |
6 | 24: c0 98 cbi 0x18, 0 ; 24 |
7 | 26: 9a e0 ldi r25, 0x0A ; 10 |
8 | milliseconds can be achieved. |
9 | */
|
10 | void
|
11 | _delay_loop_2(uint16_t __count) |
12 | {
|
13 | __asm__ volatile ( |
14 | 28: e0 ed ldi r30, 0xD0 ; 208 |
15 | 2a: f0 e0 ldi r31, 0x00 ; 0 |
16 | 2c: 31 97 sbiw r30, 0x01 ; 1 |
17 | 2e: f1 f7 brne .-4 ; 0x2c <sputchar+0xa> |
18 | for( uint8_t i = 10; i; i-- ){ // 10 bits |
19 | _delay_us( 1e6 / BAUD ); // bit duration |
20 | if( c & 1 ) |
21 | 30: 80 ff sbrs r24, 0 |
22 | 32: 02 c0 rjmp .+4 ; 0x38 <__CCP__+0x4> |
23 | STX_PORT &= ~(1<<STX_BIT); // data bit 0 |
24 | 34: c0 98 cbi 0x18, 0 ; 24 |
25 | 36: 01 c0 rjmp .+2 ; 0x3a <__CCP__+0x6> |
26 | else
|
27 | STX_PORT |= 1<<STX_BIT; // data bit 1 or stop bit |
28 | 38: c0 9a sbi 0x18, 0 ; 24 |
29 | |
30 | void sputchar( uint8_t c ) |
31 | {
|
32 | c = ~c; |
33 | STX_PORT &= ~(1<<STX_BIT); // start bit |
34 | for( uint8_t i = 10; i; i-- ){ // 10 bits |
35 | 3a: 91 50 subi r25, 0x01 ; 1 |
36 | 3c: 11 f0 breq .+4 ; 0x42 <__SREG__+0x3> |
37 | _delay_us( 1e6 / BAUD ); // bit duration |
38 | if( c & 1 ) |
39 | STX_PORT &= ~(1<<STX_BIT); // data bit 0 |
40 | else
|
41 | STX_PORT |= 1<<STX_BIT; // data bit 1 or stop bit |
42 | c >>= 1; |
43 | 3e: 86 95 lsr r24 |
44 | 40: f3 cf rjmp .-26 ; 0x28 <sputchar+0x6> |
45 | 42: 08 95 ret |
Peter
Peter Dannegger schrieb: > Ich mach das einfach mit Delay Genial einfach, einfach genial ;-) Damit werden auch die Baudraten möglich, die normalerweise mit dem USART nicht so recht funktionieren (z.B. 9600 oder 19200 Baud mit 1MHz) Danke für den Code. Grüße, Rudi
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.