Forum: Mikrocontroller und Digitale Elektronik Problem mit SW UART


von TheMason (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

habe mir einen SW UART zusammengebastelt. Das Teil funktioniert auch 
(senden gar kein problem), aber beim empfangen habe ich das problem das 
sich nur ein paar zeichen (reicht von 12 bis 60) empfangen kann und 
danach ist schicht (es wird nichts weiter empfangen, aber der uC läuft 
noch weiter, hängt also nicht).
ich habe den rx-pin mit int0 verbunden und warte da auf die fallende 
flanke. danach nutze ich timer 2 zum weiteren abtasten. die baudrate ist 
mit 4800 bd auch nichts besonderes.
es scheint so das entweder der int0 oder aber der timer2-ovf nicht mehr 
durchkommen. wüsste allerdings nicht wieso, alle weiteren int's kommen 
durch.
hat jemand ne idee ?

gruß

rene

von Andreas K. (a-k)


Lesenswert?

CTC Mode empfohlen, sonst kumuliert der durch verzögerte Abarbeitung des 
Interrupts entstehende Fehler.

von TheMason (Gast)


Lesenswert?

also im ctc-mode wills auch nicht so richtig klappen.
habe immer noch das problem das mir die routinen hängen. außerdem 
emfpängt er falsch. aber da ist sicherlich noch ein kleiner bug drin.
ist das mit der akkumulation des jitters bei 4800 auch schon so ein 
problem ?! arbeite mit nem cpu takt von 11,0592mhz.

hier mal die geänderten stellen :

void vSWUARTInit (void)
{
  MCUCR |=  (2 << ISC00);
  GICR  |=  (1 << 6);
  PORTD |=  (1 << 2);
  DDRD  &= ~(1 << 2);

  TCCR2  = TIMER2_DIVIDER;

  TCCR2 = TIMER2_DIVIDER | (1<<WGM21) | (0 << WGM20);
  TCNT2 = 0;
  OCR2  = 255;

  TIMSK &= ~(1 << OCIE2);
  ucRxCnt = 0;

  INIT_TX_PIN;
}

void vSetEdgeDetect (void)
{
  TIFR  |=  (1 << OCF2);
  GIFR  |=  (1 << 6);
  TIMSK  &= ~(1 << OCIE2);
  GICR   |=  (1 << 6);
}

ISR (TIMER2_COMP_vect)
{
  OCR2 = RX_TIME_BIT_TIME;
  TIFR |= (1 << OCF2);
  if (ucRxCnt >= 8)
  {
    if (PIN_RX)
    {
      ucSWUARTData = ucInputShiftReg;
      bSWUARTReceived = TRUE;
    }
    ucRxCnt = 0;
    vSetEdgeDetect();
  }
  else
  {
    ucInputShiftReg = ucInputShiftReg >> 1;
    if (PIN_RX) { ucInputShiftReg |= 0x80; }
    ucRxCnt++;
  }
}

ISR (INT0_vect)
{
  TCNT2  =   0;
  OCR2   =   255 - RX_TIME_1ST_BIT;

  GIFR  |=   (1 << 6);
  GICR  &=  ~(1 << 6);
  ucEdgeCnt++;
  ucRxCnt = 0;
  ucInputShiftReg = 0;

  TIFR  |=   (1 << OCF2);
  TIMSK |=   (1 << OCIE2);
}

von Andreas K. (a-k)


Lesenswert?

Bist du sicher, dass deine Bitzeiten so stimmen? Die Variante in 
ISR(INT0_vect) passt nicht ganz zur anderen. Da du die #defines geheim 
gehalten hast...

von TheMason (Gast)


Angehängte Dateien:

Lesenswert?

hups, ähm ...

hier noch das header file.
die bitzeiten sollten eigentlich stimmen.
1. bit = 1.5x bitzeit ,
2-10. bit = 1.0x bitzeit.
bitzeit ist bei mir 11059200/64/4800 = 36.
das empfangen selbst ist nicht das problem (zumindest bei der lösung 
ganz oben)
ich kapier nicht warum die interruptabfolge abreisst.

von TheMason (Gast)


Lesenswert?

noch was zur hardware :

rx-pin ist bei mir auf int0
tx-pin auf int1.
int0 brauche ich wie gesagt nur zur flankenerkennung

von Andreas K. (a-k)


Lesenswert?

Sorry, mit dem Headerfile, ist hatte grad nur noch das zweite gesehen. 
Oben stand das was ich suchte.

Jedenfalls ist
  OCR2 = 255 - RX_TIME_1ST_BIT;
sicherlich nicht richtig.

von TheMason (Gast)


Lesenswert?

oh ... copy&paste fehler.
habs behoben. jetzt empfängt er richtig. allerdings besteht das problem 
das "hängenbleibens" immer noch :-(

von TheMason (Gast)


Lesenswert?

habe mal debugausgaben auf einem lcd display gemacht.
es wird tatsächlich der timer 2 nicht mehr angestossen.
ich zähle die anzahl der timeraufrufe und gebe diese aus.
irgendwann bleibt der zähler einfach stehen. ich vermute es hängt 
irgendwo mit der umschaltung zw. flankenerkennung und timer-int 
anstossen.
hat jemand ne ahnung was das sein kann ?

gruß
rene

von TheMason (Gast)


Lesenswert?

keiner ne idee ?! :-(

von TheMason (Gast)


Lesenswert?

kann mir denn niemand nen tip geben ?!

liegt es daran das ich den INT0 und nicht (wie bei peter danneggers 
version) den ICP verwende ?
liegts vielleicht daran das noch zuviel anderes zeugs in meinem programm 
läuft (wobei das m.m. nach nicht erklärt warum der interrupt "hängen" 
bleibt), und interrupts "verschluckt" werden können (dann sollte es aber 
höchstens zeichenaussetzer geben und nicht ein komplettes stehenbleiben 
der empfangsroutine) ?
was fehlt denn noch an infos ?

von Peter D. (peda)


Lesenswert?

TheMason wrote:
> was fehlt denn noch an infos ?


Ein compilierfähiges Programm wäre nicht schlecht (zip, wenns mehrere 
Files sind).

Mit nur Codeschnipselchen ist das für nen anderen sehr schwer.

Und nach Murphys Gesetzt ist ja der Fehler immer grundsätzlich in dem 
Code, den man nicht zeigt.


Peter

von TheMason (Gast)


Lesenswert?

kann gerne mal den ganzen code posten. dürfte aber "schwere" kost sein, 
weil es recht viel ist (habe mit optimierung ca 30kB asm-code) und z.t. 
auch noch im rohbau, bzw ohne funktion.
bereite den code mal etwas auf und poste ihn dann (muß mir erst noch das 
avr-studio installieren, bin gerade nicht an meinem heimischen rechner)

auf was ist denn besonderes augenmark zu legen damit die 
kommunikationsroutinen sauber laufen.
 - der jitter bzw. jitterakkumulation vermeiden ist klar. (obwohl ich 
denke das bei 4800bd das eher weniger eine rolle spielt als bei 
30-50kbd, oder sehe ich das falsch ?)
 - nach möglichkeit alles im interrupt (1 irq für flankenerkennung, 1 
irq für abtastung und 1 irq für übertragung)
 - code möglichst kurz halten

habe ich noch was vergessen ?

von TheMason (Gast)


Angehängte Dateien:

Lesenswert?

hier mal der gesamte code.
habe ihn kompilierfähig, und die sw-uart routinen wieder einkommentiert 
(hatte diese auskommentiert da ich an anderer stelle weitergemacht habe)

den sw-uart brauche (wenn er denn mal funktioniert) ich zu 
debug-zwecken. der hw-uart wird für die midi-schnittstelle benötigt.

von Peter D. (peda)


Lesenswert?

TheMason wrote:
> kann gerne mal den ganzen code posten.

Nö, mußt Du nicht.

Reduziere mal das Programm nur auf den Test der UART.
Wenn dann der Fehler weg ist, dann liegt der Fehler nicht in der UART.
Wenn der Fehler immer noch da ist, poste ihn, dann wirds ja überschaubar 
sein.

Es ist immer besser die Probleme aufzuteilen, als sich tagelang durch 
einen riesen Wust an Code zu wuseln (Teile und herrsche).


Wenn man denkt, das Programm bleibt irgendwo hängen, dann klemm ein paar 
LEds an und setze sie an den Stellen, wo Du Probleme vermutest.

Und erstmal nichts mit Sleep und Watchdog machen, die können einen super 
das Entwickeln erschweren.
Sowas baut man, wenn überhaupt, erst ganz zum Schluß ein, wenn alle 
Grundfunktionen fertig sind.


Peter

von TheMason (Gast)


Lesenswert?

@peter

erstmal danke für die tips.
- sleep und watchdog verwende ich nicht (nur den sleep ganz am anfang 
einmal)
- debugausgaben und "sichtungen" auf dem scope habe ich schon gemacht 
(daher wende ich mich ja hoffnungsvoll an euch :-))

werde wenn ich wieder an meinem heimischen rechner sitze es nochmal 
austesten (sprich nur den sw uart laufen lassen um zu sehen ob es 
randeffekte mit anderen sw teilen gibt die den uart zum erliegen 
bringen.

gruß
rene

von TheMason (Gast)


Lesenswert?

hab mich mal mit dem problem beschäftigt und das ganze auf ner kleinen 
platine aufgebaut.
also senden ist kein thema soweit (lediglich in der eigentlichen 
anwendung habe ich ein paar falsch gesendete zeichen).
empfangen funktioniert auch prächtig, hat aber auch aussetzer und bleibt 
hängen.
zwar viel seltener als in der eigentlichen anwendung (in der ich den 
source auch getestet habe), bleibt aber trotzdem stehen.
mit stehen meine ich das der empfang "abreisst", der rest des uCs aber 
fröhlich weitermacht.

habe den swuart einmal mit 2 8bit timern (overflow) sowie mit dem 16 bit 
timer (capture) laufen lassen (auf dem test board).
mit dem 16 bit timer habe ich zwar keine aussetzer, aber der verschluckt 
mehrere zeichen. die 8bit timer lösung bleibt irgendwann stehen.

was mich so wurmt ist das es ja prinzipiell funzt, aber das teil eben 
immer irgendwann stehenbleibt ...
aber irgendeine kleinigkeit (hoffe ich zumindest) mache ich anscheinend 
noch falsch, sonst würd ich ja gar nichts empfangen ...

verwende zum erkennen der rx-start-flanke den int0.
gesendet wird als ganz normaler output-portpin auf int1.
frequenz ist 16mhz. baudrate auf 19200. (wäre ja schon froh wenns auf 
4800 funzt :-(( )

hoffe auf hilfe.

gruß
rene

von TheMason (Gast)


Angehängte Dateien:

Lesenswert?

man merkt das es heute früh spät geworden ist ....
hier die fehlenden dateien :-((

von TheMason (Gast)


Lesenswert?

hat denn niemand zeit mal eben drüber zu schauen und nen hinweis was es 
sein könnte ?

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.