Forum: Compiler & IDEs Software UART mit delay


von Jakob K. (jaykob)


Lesenswert?

hallo liebe community,

habe mir mal überlegt, ob man einen Software UART auchmit der 
Zeitverzögerung delay machen kann, wenn man die BAUDRATE gegeben hat.
Ich meine nur das senden und nicht das empfangen.


Laut meiner Logik wäre das möglich, da man ja nur eine bestimmte 
Bitfolge ausgibt!


Was meint ihr zu meiner Idee, ist sowas möglich oder bin ich da auf dem 
ganz falschen Trip?

Ich bin nämlich auf der Suche nach einem Soft-UART ohne TIMER und 
INTERRUPTS.

von Olaf (Gast)


Lesenswert?

Ja, das kannn man machen. Ist aber programmierung aus
der Steinzeit und funktioniert auch nur solange keine
anderen Interrupts im Programm laufen.

Olaf

von Falk B. (falk)


Lesenswert?

@  Olaf (Gast)

>der Steinzeit und funktioniert auch nur solange keine
>anderen Interrupts im Programm laufen.

Das gilt genauso für die Timerinterruptlösung. Dort dürfen auch keine 
anderen Interrupts dazwischenfunken, sonst ist das Timing im Eimer.

MfG
Falk

von Peter D. (peda)


Lesenswert?

1
void sputchar( uint8_t c )
2
{
3
  c = ~c;
4
  STX_PORT &= ~(1<<STX_BIT);            // start bit
5
  for( uint8_t i = 10; i; i-- ){        // 10 bits
6
    _delay_us( 1e6 / BAUD );            // bit duration
7
    if( c & 1 )
8
      STX_PORT &= ~(1<<STX_BIT);        // data bit 0
9
    else
10
      STX_PORT |= 1<<STX_BIT;           // data bit 1 or stop bit
11
    c >>= 1;
12
  }
13
}


Peter

von Peter D. (peda)


Lesenswert?

Falk Brunner schrieb:
> Das gilt genauso für die Timerinterruptlösung. Dort dürfen auch keine
> anderen Interrupts dazwischenfunken, sonst ist das Timing im Eimer.

Wenn Du die set/clear Pin on Compare Funktion benutzt, müssen die 
Interrupt nur kürzer als eine Bitzeit sein.


Peter

von Simon K. (simon) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
>
1
> void sputchar( uint8_t c )
2
> {
3
>   c = ~c;
4
>   STX_PORT &= ~(1<<STX_BIT);            // start bit
5
>   for( uint8_t i = 10; i; i-- ){        // 10 bits
6
>     _delay_us( 1e6 / BAUD );            // bit duration
7
>     if( c & 1 )
8
>       STX_PORT &= ~(1<<STX_BIT);        // data bit 0
9
>     else
10
>       STX_PORT |= 1<<STX_BIT;           // data bit 1 or stop bit
11
>     c >>= 1;
12
>   }
13
> }
14
>

Hier muss man aber auch aufpassen. Die vergleiche und das 
setzen/zurücksetzen sowie schieben kostet auch noch Takte. Bei hohen 
Baudraten könnten diese ins Gewicht fallen.

von Peter D. (peda)


Lesenswert?

Simon K. schrieb:
> Bei hohen
> Baudraten könnten diese ins Gewicht fallen.

Da würde ich es auch nicht nehmen.
Ich nehme es oft als Debugport bei 9600Baud.

Das Delay sollte dominieren (>100 Zyklen).


Peter

von Jakob K. (jaykob)


Lesenswert?

Hallo nochmal,

vielen Dank für die vielen und hilfreichen Antworten!

Die Verzögerungen durch die Setz- und Löschzyklen, sowie die für die 
Abfrage kann ich vernachlässigen, da meine Baudrate nur 2400 ist.
Und Interrupts habe ich in meinen Programm sowie nicht.

Ich will es vom verständnis so einfach wie möglich halten.


@ Peter Dannegger (peda)

Erstmal vielen Dank für den C-Code, dieser ist sehr hilfreich.
Habe aber noch ein paar Fragen zum Programm.

Ich schalte hinter den uC einen MAX 232, muss ich dann auch die Bits 
invertieren wie bei dir in Zeile 3 ( c = ~c) geschehen?

Muss die for-schleife nicht nur über 9 Bits gehen, da das Start-Bit ja 
schon vorher ausgegeben wird?

Ist im _delay_us(1e6/BAUD) das 1e6 die Prozessorrate (F_CPU)?


Was ist das STX_PORT und STX_BIT? Ist das vorher als PORTx und Pxn 
definiert worden?

Wie muss die Varible c, welche an die Funktion übergeben wird im 
Hauptprogramm definiert sein? Bitweise, ASCII-codiert oder HEX-Zahlen?


Ich hoffe ich nerve nicht durch die ganzen Fragen, aber ich bin leider 
ein Anfänger im uC Programieren.

von funkker (Gast)


Lesenswert?

Hallo, ich bin Anfänger und fand die Lösung mit Delay sehr interessant.

Habe es mal umgesetzt, es werden 20 Buchstaben ausgegeben:

[code]
#include <stdio.h>
#include <string.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define baud 19200
#define sendbit 1

void sputchar( uint8_t c )
{
  c = ~c;

  PORTD &= ~(1 << sendbit);        // start bit
  for( uint8_t i = 10; i; i-- ){     // 10 bits
    _delay_us( 1e6 / baud );        // bit duration

    if( c & 1 )
      PORTD &= ~(1 << sendbit);  // data bit 0
    else
      PORTD |= 1 << sendbit;     // data bit 1 or stop bit
      c >>= 1;
  }
 }


int main (void)
{

  uint8_t zaehler;
  uint8_t i;

  zaehler=85;

  DDRD = (1 << DDD1) ;

  for (i =64 ; i < zaehler; i++) {
    _delay_ms(100);
    sputchar(i);
    _delay_ms(100);
  }
 }

von funkker (Gast)


Lesenswert?

Es ist bei mir ein Atmga32 mti 16mhz.

Gruss

von narf (Gast)


Lesenswert?

und was soll der µC mal noch machen ?
wenn irgendwas in das software UART timing rutscht wars das mit einer 
ausgabe ...

von funkkeld (Gast)


Lesenswert?

Manno..., das ist nur eine Funktionsüberprüfung, ob es geht.


Oh...,Oh..., deutschland.

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.