Forum: Mikrocontroller und Digitale Elektronik serieller TX mit delay in Software (AVR, UART)


von floh boing (Gast)


Lesenswert?

Für's schnelle Debuggen ohne Debugger.
Der Vorteil: braucht keinen Timer oder Interrupts.
Der Nachteil: hat keinen Timer.

Kann man das noch schicker schreiben, so dass die Wartezeit samt 
Schleifendurchlauf und Vergleich näher an der tatsächlichen Bitzeit dran 
ist (so dass 1/BAUDRATE-CONST genutzt werden kann)?
CONST könnte noch mit F_CPU angepasst werden.

Ich hatte zuvor Schieben mit variablem i drin (d&(1<<i)), so sind's 
schonmal 32 Byte weniger (neues Timing noch nicht getestet, Takt 1MHz):
1
    uint16_t d = 0b1000000000 | (c<<1);  // stop, data LSB first, start
2
    for(uint8_t i=0; i<10; i++){
3
        if( d & 1 )
4
            PORT |= (1<<PIN);
5
        else
6
            PORT &= ~(1<<PIN);
7
        d>>=1;
8
        _delay_us(70/*104*/);
9
    }

von floh boing (Gast)


Lesenswert?

PS: GCC mit -Os

von Falk B. (falk)


Lesenswert?

Herzlichen Glückwunsch zur Wiederentdeckung des Soft-UARTs!

von floh boing (Gast)


Lesenswert?

Falk B. schrieb:
> Herzlichen Glückwunsch

Danke. Kannst du auch was Sinnvolles beitragen, wie z.B. einen Link oder 
gar eine Verbesserung des Codes?

von Stefan F. (Gast)


Lesenswert?

floh boing schrieb:
> Kannst du auch was Sinnvolles beitragen,

Ich verstehe auch nicht, was du uns mit diesem Thread großartiges 
mitteilen willst. Da ist seit Erfindung der Mikroprozessoren nichts 
neues oder interessantes dran.

Du solltest Interrupts sperren, die versauen dir sonst das Timing.

von A. S. (Gast)


Lesenswert?

Hallo,

ganz solide. Die 70µs sind gewürfelt?

Du könntest das genauso auch mit dem d laufen lassen und auf i 
verzichten, zumindest wenn c uint8 ist. Ist aber kaum besser.
1
uint16_t d = 0b1000000000 | (c<<1);  // stop, data LSB first, start
2
3
    while(d) {
4
        if(d&1) {PORT |=  (1<<PIN);}
5
        else    {PORT &= ~(1<<PIN);}
6
        d>>=1;
7
        _delay_us(70);
8
    }

von wendelsberg (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Du solltest Interrupts sperren, die versauen dir sonst das Timing.

Zum Debuggen? Unzweckmaessig.

wendelsberg

von Axel S. (a-za-z0-9)


Lesenswert?

wendelsberg schrieb:
> Stefan ⛄ F. schrieb:
>> Du solltest Interrupts sperren, die versauen dir sonst das Timing.
>
> Zum Debuggen? Unzweckmaessig.

Und? Was nützt eine nicht funktionierende Debugausgabe?

von Falk B. (falk)


Lesenswert?

Axel S. schrieb:
> Und? Was nützt eine nicht funktionierende Debugausgabe?

Die kann man dann Debuggen ;-)

von Stefan F. (Gast)


Lesenswert?

Textausgaben untersuchen ist auch eine Variante des Debugging. Lange 
Zeit ging es gar nicht anders. Ich kam in meiner Jugendzeit noch 
zwangsweise zu diesem unerquicklichen Genuss.

Eproms mit Kippschaltern zu programmieren ist auch aus der Mode gekommen 
:-)

Kennt ihr noch die Computerzeitschriften mit Spielen zum Abschreiben? 
Also wo man seitenweise Hex-Zahlen abtippen musste.

Wenn das Programmieren heute noch so mühsam wäre, würden alle nur noch 
vor dem Fernseher sitzen. Den Stress tut sich heute niemand mehr an.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Hier meine Version:
1
void sputchar(unsigned char c)
2
{
3
  c = ~c;                                       // complement to send 0 = stop bit(s)
4
  STXD_oe = 1;                                  // output
5
  STXD = MARK;                                  // start bit
6
  for (uint8_t i = 9 + STOP_BITS; i; i--)       // start + data + stop bits
7
  {
8
    _delay_us(1e6 / BAUD);                      // bit duration
9
    if (c & 1)
10
      STXD = MARK;
11
    else
12
      STXD = !MARK;                             // = Space
13
    c >>= 1;                                    // next bits or stop bit(s)
14
  }
15
}

von floh boing (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Du solltest Interrupts sperren, die versauen dir sonst das Timing.

Guter Hinweis.

A. S. schrieb:
> ganz solide. Die 70µs sind gewürfelt?
>
> Du könntest das genauso auch mit dem d laufen lassen und auf i
> verzichten, zumindest wenn c uint8 ist. Ist aber kaum besser.

Ja, ausprobiert. Darin steckt aber auch die Abweichung des internen RCs 
bei meinem AVR.
Danke für's Feedback.

Peter D. schrieb:
> Hier meine Version:

Danke Peter, die hatte ich gestern in 
Beitrag "Re: ATtiny44 -Software Uart - nur senden" ff. gefunden, und 
wollte gerade den Link posten.
Im Beitrag von Schorsch werden auch die offenbar 9 Takte für Schleife 
und Ausgabe berücksichtigt.

Falk B. schrieb:
>
.
Das habe ich mir gedacht.


Thema erledigt. Danke!

von Martin (Gast)


Lesenswert?

Wer Interrupts nicht sperren möchte nimmt:

1
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
2
{
3
4
    ...
5
6
}

von Georg (Gast)


Lesenswert?

Martin schrieb:
> Wer Interrupts nicht sperren möchte nimmt:

Da darin ein Delay steckt sind die Nebenwirkungen ev. drastisch, da dann 
der Interrupt nicht mehr annähernd Real Time ist, jedenfalls manchmal - 
das ganze ist eben ein Weg aus der Computersteinzeit. Zuletzt habe ich 
das gesehen bei ZX80 und C64.

Georg

von Stefan F. (Gast)


Lesenswert?

Bei einem Steuergerät in einem Verteilzentrum hatten die das mal clever 
mit der Power-LED kombiniert (war offenbar anfangs nicht eingeplant 
gewesen).

Man konnte ein USB-UART Adapterkabel anstelle der Power-LED anstecken. 
Dieses hatte einen Taster, der die beiden Pins miteinander verband. 
Dadurch konnte man Debug Ausgaben auf eben diesem LED-Pin aktivieren.

Mein Motorrad hat etwas ähnliches. Da baumelt aus dem Steuergerät ein 
kleiner zweipoliger Stecker, an den man ein Diagnosegerät anschließen 
kann. Wer dieses Gerät nicht hat, kann dort einfach eine Drahtbrücke 
einsetzen. Dann gibt das Gerät hilfreiche Morsecodes auf der gelben 
Kontroll-Leuchte aus. Und diese Codes sind in der Betriebsanleitung alle 
dokumentiert (was leider nicht mehr selbstverständlich ist).

Klar hat so eine Soft-UART Seiteneffekte. Sie kann trotzdem in 
bestimmten Anwendungsfällen äußerst nützlich sein.

von Peter D. (peda)


Lesenswert?

Je nach Anwendung kann man 2 Varianten vorsehen:
- kurze Interrupthandler, geringe Baudrate
- Byte senden atomar gekapselt, hohe Baudrate

von floh boing (Gast)


Lesenswert?

Peters Algorithmus hat mindestens zwei Vorteile:

- es gibt keine (überflüssige) Wartezeit am Ende
- es muss nur ein Byte geschoben werden, denn das Stopbit gibt es 
"kostenlos" beim Schieben (durch die Invertierung)

von A. S. (Gast)


Lesenswert?

floh boing schrieb:
> Peters Algorithmus hat mindestens zwei Vorteile:
>
> - es gibt keine (überflüssige) Wartezeit am Ende
> - es muss nur ein Byte geschoben werden, denn das Stopbit gibt es
> "kostenlos" beim Schieben (durch die Invertierung)

a) die Wartezeit am Ende ist nicht überflüssig. Das weiß Peter auch. 
Darum versteckt er das im Schleifenzähler. Rechne mal nach.

b) Dafür braucht er einen Schleifenzähler.

(c) Es gibt 2 verschiedene Stellen, in denen die Leitung gesetzt wird.

Peters Code ist (wieder mal) sehr pfiffig und kaum zu toppen. Bei der 
Aufgabe sind die Möglichkeiten aber auch überschaubar ... und sinnlos. 
Das Problem bleibt das Delay: Damit ist kein Interrupt erlaubt und und 
Rechenzeit spielt keine Rolle.

von floh boing (Gast)


Lesenswert?

Stimmt!

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.