Software TX 1 bit Pause einbauen, C

Gast #964323
Lesenswert?

Hallo,

ich habe hier im Forum eine kleine Routine für eine serielle 
Schnittstelle gefunden.
1
volatile uint16_t stxdata = 0;
1
void sputchar(uint8_t val){
2
  while(stxdata);
3
  stxdata = 0x200 | (val<<1);
4
}

Wird im Timerinterrupt mit Baudrate aufgerufen:
1
  if (stxdata){
2
    if (stxdata & 1)
3
    {
4
      PORTB &= ~(1<<TX);  // off
5
    }
6
    else
7
    {
8
      PORTB |= (1<<TX);  // on
9
    }
10
    stxdata >>= 1;
11
  }

Jetzt würde ich gerne noch ein Bit Pause anhängen, damit es keine 
Probleme beim Empfänger gibt. Hat jemand eine Idee?
#964343
Lesenswert?

@ kalle (Gast)

>ich habe hier im Forum eine kleine Routine für eine serielle
>Schnittstelle gefunden.

Das ist ein Soft-UART:

1
void sputchar(uint8_t val){
2
  while(stxdata);
3
  stxdata = 0x400 | (val<<1);
4
}

>Jetzt würde ich gerne noch ein Bit Pause anhängen, damit es keine
>Probleme beim Empfänger gibt. Hat jemand eine Idee?

Siehe oben.

MFG
Falk
#964359
Lesenswert?

@ Falk Brunner:

> Das ist ein Soft-UART:
>
1
> void sputchar(uint8_t val){
2
>   while(stxdata);
3
>   stxdata = 0x400 | (val<<1);
4
> }
5
>

Mit einer 0 als Stopbit?
0x200 war schon richtig.


@ kalle:

> Jetzt würde ich gerne noch ein Bit Pause anhängen, damit es keine
> Probleme beim Empfänger gibt.

Ändere das 0x200 in 0x600.
#964385
Lesenswert?

kalle wrote:

> Jetzt würde ich gerne noch ein Bit Pause anhängen, damit es keine
> Probleme beim Empfänger gibt. Hat jemand eine Idee?

Das einzige Problem, daß Du damit lösen kannst ist das, daß der 
Empfänger 2 Stopbits erwartet.

Probleme mit Baudratenfehlern (RC-Oszillator statt Quarz, kein 
Baudratenquarz bei hohen Baudraten) oder wegen fehlendem Protokoll 
lassen sich damit natürlich nicht lösen.


Peter
Gast #964398
Lesenswert?

Hallo, das ist richtig, das Ganze ist invertiert.
Und danke, mir ist gerade aufgefallen dass ich übersehen habe, dass das 
Stop Bit ja = Ruhepegel ist. Die Invertierung hat mir einen Strich 
durchs Gehirn gemacht ;-)
#964404
Lesenswert?

kalle wrote:

> Hallo, das ist richtig, das Ganze ist invertiert.

Invertiert funktioniert aber dein Timerinterrupt nicht, weil du ja in 
stxdata eine 1 als Endemarke brauchst, und diese 1 wird dann ja als 0 
ausgegeben und vom Empfänger als neues Startbit erkannt.

1
  if (stxdata){
2
  ...
3
  }

Müsstest du ändern in (um die letzte 1 zu ignorieren):
1
  if (stxdata > 1){
2
  ...
3
  }
4
  else
5
    stxdata = 0;

Außerdem musst du in sputchar 0x200 in 0x401 ändern (oder 0x801, wenn du 
2 Stopbits möchtest).
Gast #964455
Lesenswert?

Danke trotzdem!

Evtl sollte man die Funktion interruptsicher machen:
1
void sputchar(uint8_t val)
2
{
3
  while(stxdata);
4
  cli();
5
  stxdata = 0x200 | (val<<1);
6
  sei();
7
}

Löst aber noch nicht mein Problem. Ich forsche weiter.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren