Forum: Projekte & Code UART per USI


von Der D. (derdaniel)


Lesenswert?

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
von Der D. (derdaniel)


Angehängte Dateien:

Lesenswert?

Ups, da fehl ein .equ in der 34. Zeile.
Korrigierte Version im Anhang (wieso kann man seine eigenen Anhänge 
nicht ändern?!).

von Peter D. (peda)


Lesenswert?

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

von Rudi M. (rudimentaer)


Lesenswert?

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
Noch kein Account? Hier anmelden.