Forum: Mikrocontroller und Digitale Elektronik UART-Zeichenempfang wenn ISR gesperrt ist, möglich?


von Sebbi (Gast)


Lesenswert?

Hallo,

ich betreibe einige WS2812 an einem atmega328p. Nun möchte ich nach 
aussen hin eine Kommunikationsschnittstelle haben, bei der Daten hin und 
her geschrieben werden können.

Bislang lese ich das ganze auf dem mega mit der ISR Lösung (aus dem 
Wiki) ein. Nur kommen hier ab und zu Fehler.

Gibt es eine Möglichkeit, Daten zu empfangen über UART, ohne dass diese 
durch das deaktivieren der Interrupts (light ws2812b) gestört werden?

Ggf. einen vorgeschalteten µC mit Uart (wahlweise einen 16u2 mit 
direktem usb Interface). Der alle Daten empfängt. Sobald der µC mit den 
Leds senden fertig ist.

Denke da so an so etwas.


Master beschickt die Leds mit Daten.
Ein Pin wechselt nun ihren Zustand. Nun muss der Slave (an der USB 
Schnittstelle) die nächsten Daten senden, ehe der Pin erneut wechselt.

Andere Möglichkeiten? Möchte bei avr bleiben, da ich mit arm bzw. 
anderne Herstellern keine Erfahrung habe.

von Klaus (Gast)


Lesenswert?

Bei allem menschlichen Respekt, aber wer Ahnung hat, der weiß die 
Antwort; hat aber vor allem erst einmal eine Vorstellung davon, wo es 
eigentlich genau hakt - oder zumindest eine nicht unplausible Hypothese. 
Dazu hat er mindestens einige Monate gebraucht um dahin zu kommen, 
Schweiss und Tränen vergossen und einige Hektorliter Kaffee.

Der Rest, zu dem Du augenscheinlich gehörst, hat sich irgendwas 
irgendwoher zusammenkopiert; weiß nicht, warum es geht und ist daher 
verloren, wenn es nicht geht. Dafür sind wir hier nicht die Feuerwehr. 
Entweder Du analysierst, - durchaus mit unserer Hilfe -, das Problem und 
löst es, - wiederum, falls nötig, mit unserer Hilfe -, oder Du lernst es 
alleine.

Aber was Du fragst, ist eine der hier mit Recht so unbeliebten 
Rundumschlagprobleme: Die Antwort ist: Ja. Nein. Kommt darauf an. Sollte 
man lieber nicht. Wozu eigentlich (im Prinzip sollte sich ein AVR dabei 
zu Tode langweilen)?

Also, was genau passiert? Was erkennst Du am Debugger oder auf sonst 
eine Weise? Welcher ungewollte Zustand tritt ein (in Begriffen des 
Programmes)? Was ist der Quellcode? Was das zugrundeliegende 
Systemdesign? Was die Schaltung?

von дамрфкнилх (Gast)


Lesenswert?

Weshalb sollten die Interrupts deaktiviert werden ? Das macht man 
eignetlich nicht.

von Thomas E. (picalic)


Lesenswert?

дамрфкнилх schrieb:
> Weshalb sollten die Interrupts deaktiviert werden ? Das macht man
> eignetlich nicht.

Ich denke, daß seine WS2812-Library das erfordert, weil die LEDs per 
Bitbanging angesteuert werden und das Timing so kritisch ist, daß eine 
ISR es durcheinanderbringen würde.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

Thomas E. schrieb:
> weil die LEDs per
> Bitbanging angesteuert werden und das Timing so kritisch ist, daß eine
> ISR es durcheinanderbringen würde.

Er könnte auch das regelmäßige Polling des UART (und wegschreiben des 
empfangenen Bytes) in die WS2812-Routinen einbauen, das sollte zeitlich 
locker ausreichen. Auswerten kann er sie dann wenn er mit einer 
kompletten Sequenz durch ist und Zeit hat.

von Thomas E. (picalic)


Lesenswert?

Wenn man die ISR kurz hält (< 4µs), sollte es sogar ausreichen, in der 
Lib an geeigneter Stelle (= bei Low-Pegel des Ausgangs) die Interrupts 
kurz zuzulassen.

von eagle user (Gast)


Lesenswert?

Sebbi schrieb:

> Gibt es eine Möglichkeit, Daten zu empfangen über UART, ohne dass diese
> durch das deaktivieren der Interrupts (light ws2812b) gestört werden?

Die "offizielle" Lösung für UART-Schnittstellen nennt sich Hardware 
Handshake. Dabei wartet der sendende Rechner (hier wohl ein PC) bis sein 
Handshake-Eingang aktiv wird.

> Denke da so an so etwas.
> Master beschickt die Leds mit Daten.
> Ein Pin wechselt nun ihren Zustand. Nun muss der Slave (an der USB
> Schnittstelle) die nächsten Daten senden, ehe der Pin erneut wechselt.

Dieser Pin ist der Handshake-Ausgang des Masters und nennt sich RTS. Der 
wird mit dem CTS-Eingang des PC verbunden. Ein zwischengeschalteter 
Slave ist dafür nicht nötig.

Natürlich muss das Programm auf dem PC die Schnittstelle richtig 
bedienen, was leider nicht immer funktioniert. Aber Versuch macht 
kluch...

von дамрфкнилх (Gast)


Lesenswert?

Eine Beleuchtung kommuniziert ja nicht dauern, daher ist ein 
zweimikrosekunden Zucken nicht stoerend.

von Georg (Gast)


Lesenswert?

дамрфкнилх schrieb:
> Weshalb sollten die Interrupts deaktiviert werden ? Das macht man
> eignetlich nicht.

Natürlich macht man das, nur ist der Programmierer dafür verantwortlich, 
dass es nur an kritischen Stellen (z.B. Read-Modify-Write oder Wert 
lesen/Status rücksetzen) geschieht und nur für wenige Takte bzw. µs. 
Dann kann das aber unmöglich den UART-Empfang stören.

Wo du recht hast: längeres Deaktivieren ist IMMER ein Fehler, der muss 
zuerst beseitigt werden.

In jedem Fall muss der TO erst mal lokalisieren wo der Fehler liegt 
statt im Nebel herumzustochern. Ist natürlich schwer, wenn man bloss 
unverstandene Code-Bruchstücke per Cut-and-Paste aneinanderreiht, aber 
ohne Verständnis kann man halt nicht Programme schreiben.

Georg

von Thomas E. (picalic)


Lesenswert?

дамрфкнилх schrieb:
> Eine Beleuchtung kommuniziert ja nicht dauern, daher ist ein
> zweimikrosekunden Zucken nicht stoerend.

Die WS2812 zucken aber nicht nur, sondern zeigen völligen Blödsinn an, 
wenn mal ein kurzer High-Impuls durch das Zwischenfunken einer ISR von 
0.625µs auf einige µs gedehnt wird. Wenn man WS2812 mit 
Datenblatt-konformen Timing per Bit-Banging ansteuern will, geht das 
nicht mit Interrupts

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Thomas E. schrieb:
> Die WS2812 zucken aber nicht nur, sondern zeigen völligen Blödsinn an,
> wenn mal ein kurzer High-Impuls durch das Zwischenfunken einer ISR von
> 0.625µs auf einige µs gedehnt wird.

Na und, das ist doch ein Standardfall: IE aus - 0,6 s Impuls erzeugen - 
IE wieder an. Null Problemo würde Alf sagen. Und der UART-Empfang wird 
sicher nicht gestört, wenn Interrupts 1 µs lang nicht erlaubt sind.

Georg

von Christian (dragony)


Lesenswert?

@Sebbi

Wiedermal viel blabla hier zu lesen. Deshalb auch mal was nützliches:

Du hast ein grundsätzliches Problem, da du zwei Komponenten verwendest, 
die ohne Clock-Signal kommunizieren wollen. Da dies gleichzeitig 
auftreten kann (UART ohne Hardware-Handshake angenommen, was die Regel 
ist), wird es immer mal vorkommen, dass eine Kompoente versagt. Während 
man beim UART-Senden das noch schön vermeiden kann, ist das Empfangen 
unmöglich zu bewerkstelligen, da es "irgendwann" auftreten kann und WENN 
es auftritt, darf die Routine nicht unterbrochen werden, da das Timing 
kritisch ist.

Möglichkeiten:

1. AVR mit UART Modul verwenden. Wenn dein PC an die MCU jeweils nur 1 
Byte sendet (z.B. Statusbyte), ist das die Lösung. Wenn du mehrere Bytes 
sendest, könnte es noch die Lösung sein, wenn die Baudrate gering 
eingestellt ist. (Der AVR Buffer ist nur 1 Byte gross).

2. XMEGA oder sonstige MCU mit DMA verwenden (Anfänger? Lass es.)

3. UART Hardware Handshake

Versteh erstmal das grundsätzliche Problem. Das lässt sich auf viele 
andere Systeme übertragen.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

Christian S. schrieb:
> ist das Empfangen
> unmöglich zu bewerkstelligen, da es "irgendwann" auftreten kann und WENN
> es auftritt, darf die Routine nicht unterbrochen werden

Durch die Tatsache daß man mit dem lesen des empfangenen Bytes warten 
kann bis kurz vor dem Empfang des nächsten entspannt sich das schon 
wieder und ist gar nicht mehr so dramatisch.

Man muss sich halt einfach mal ausrechnen wieviel Zeit zwischen zwei 
empfangenen Bytes vergeht, wieviel Zeit man noch übrig hat zwischen zwei 
Bits für die Lichterkette, wie lange es dauern wird ein Byte vom UART 
abzuholen und wegzuschreiben, notfalls mal ein Timing-Diagramm an die 
Wand malen, einen Schritt zurücktreten und sich überlegen wie man das am 
geschicktesten ineinander verschachtet. Und schon hat man einen Plan. 
Der Rest ist dann Fleißarbeit.

von spess53 (Gast)


Lesenswert?

Hi

>Der AVR Buffer ist nur 1 Byte gross

AVRs haben einen 2-Byte-FIFO für RX.

MfG spess

von Thomas E. (picalic)


Lesenswert?

Die einfachste Lösung ist vielleicht, die Baudrate soweit 
herunterzuschrauben, daß die serielle Übertragung zum Füllen der zwei 
Bytes Empfangspuffer länger dauert, als die Übertagung der Daten an alle 
LEDs.
Für einfache Kommandos reichen 1200 Baud sicher auch aus...

von Stefan K. (stefan64)


Lesenswert?

Hallo Sebbi,

es gibt auch die Möglichkeit, den WS2812 über die SPI-Schnittstelle zu 
betreiben. dabei wird nicht das SPI-Protokoll genutzt, sondern über den 
SPI-Data-Pin das Bitmuster erzeugt, das der WS2812 benötigt.

Such mal hier nach WS2812 und SPI.

Der einzige andere mögliche Weg ist der von Bernd beschriebene, der aber 
auf jeden Fall Asm-Code und eine ziemlich hässliche Verschachtelung 
erfordert:

Bernd K. schrieb:
> Er könnte auch das regelmäßige Polling des UART (und wegschreiben des
> empfangenen Bytes) in die WS2812-Routinen einbauen, das sollte zeitlich
> locker ausreichen. Auswerten kann er sie dann wenn er mit einer
> kompletten Sequenz durch ist und Zeit hat.

Gruß, Stefan

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebbi schrieb:
> ich betreibe einige WS2812 an einem atmega328p.
> Master beschickt die Leds mit Daten.

 Wieviele und mit welchen Daten ?
 z.B. 300 LEDs sind 900Bytes RGB.
 UART:   250KB sind 25000Byt = 40us * 900Byt = 36ms.
 WS2812: 300 LEDs * 30us = 9ms
 ===================================================
 Ergibt 45ms.

 Das wird schon mal schwierig mit Daten in Echtzeit.

> Ein Pin wechselt nun ihren Zustand. Nun muss der Slave (an der USB
> Schnittstelle) die nächsten Daten senden, ehe der Pin erneut wechselt.

 Mega328p hat in UCSR0A einen bit (RxC0), den kann man zwischendurch
 mal gemutlich abfragen, anstatt mit ISR zu arbeiten, etwa so:
1
Byt2WS2812:
2
...                   ;*** DataPin fur WS2812 auf High, bit holen (shift) 7 Takte
3
...                   ;*** DataPin entsprechend dem Bitwert setzen        7 Takte
4
...                   ;*** DataPin fur WS2812 wieder auf LOW  (PORT )     1 Takt
5
   lds   r16, UCSR0A  ;                                                   2
6
   dec  BitCnt        ;                                                   1
7
   brne Byt2WS2812    ;                                                   2
8
;=================================================================================
9
;                                                                        20 Takte
10
;*** R-G-B gesendet, jetzt wird UART abgefragt...
11
   lds   r17, UDR0         ; 2   /   2
12
   sbrs  r16, RXC0         ; 1   /   2
13
   rjmp  NoUart            ; 2
14
   st    X+, r17           ;         2
15
   ret
16
NoUart:
17
   nop                     ; 1
18
   ret                     ;===========
19
                           ; 6   /   6 Takte

 Das sind 6 Takte zusatzlich, bei 328p mit 16MHz brauchst du zwischen
 16 und 24 Takte fur einen bit beim WS2812-Bitbanging (20 Takte +/- 4
 Takte), da kann man sogar zwischen den einzelnen bits UART abfragen,
 nur darf die Pause zwischen den einzelnen Bytes nicht langer als 10us
 sein, ansonsten wird Reset ausgelost (WS2812 ist da zickig, nichts mit
 50us wie im DaBla).
 UART braucht beim 250Kb 40us pro Byt, WS2812 aber nur 30us fur R-G-B,
 da konnen auch keine Bytes verloren gehen.

 Das funktioniert so, keine Angst.

von Norbert (Gast)


Lesenswert?

Früher (TM) also viel früher, so im letzten Jahrtausend, da
gab's durchaus die Möglichkeit nur ein Byte an ein Gerät zu senden und 
dann auf das Echo dieses Zeichens zu warten.
Erst dann wurde das nächste Byte gesendet.

Das ist natürlich heutzutage verboten und darum braucht man auch für 
blinkende Leuchtdioden einen vier-Kern ARM.

von Bernd K. (prof7bit)


Lesenswert?

Norbert schrieb:
> dann auf das Echo dieses Zeichens zu warten.
> Erst dann wurde das nächste Byte gesendet.
>
> Das ist natürlich heutzutage verboten und darum braucht man auch für
> blinkende Leuchtdioden einen vier-Kern ARM.

Bullshit. Die gestellte Aufgabe ist locker mit dem kleinsten ATTiny zu 
lösen der gerade eben noch ein UART eingebaut hat. Der PC kann jederzeit 
und so schnell senden wie er kann, die Lichterkette wird nicht flackern.

Alles was man braucht ist sich die Zeit richtig einzuteilen, und von der 
dafür nötigen Zeit ist auch auf dem kleinsten Tiny noch genügend 
vorhanden.

von Thomas E. (picalic)


Lesenswert?

Bernd K. schrieb:
> Alles was man braucht ist sich die Zeit richtig einzuteilen, und von der
> dafür nötigen Zeit ist auch auf dem kleinsten Tiny noch genügend
> vorhanden.

So isses - aber es erfordert eben ein bisschen mehr Gehirnschmalz, als 
bloß eine paar Funktionsaufrufe in fertige vorgekaute 
Standard-Libraries, wie das heute so üblich ist...

von Stefan K. (stefan64)


Lesenswert?

Norbert schrieb:
> Früher (TM) also viel früher, so im letzten Jahrtausend, da
> gab's durchaus die Möglichkeit nur ein Byte an ein Gerät zu senden und
> dann auf das Echo dieses Zeichens zu warten.
> Erst dann wurde das nächste Byte gesendet.

Auch im letzten Jahrtausend war das keine gute Idee:
Im besten Fall halbiert das die Übertragungsgeschwindigkeit. Das setzt 
aber voraus, daß de Host auf jedes Zeichen sofort reagiert. Jede 
Verzögerung auf Seiten des Host wirkt sich massif auf die 
Geschwindigkeit aus.

Bei Verwendung eines FTDI o.ä. wird es noch schlimmer: Über USB werden 
die Daten im 1ms-Raster übertragen. Bei Deinem Verfahren wird in einem 
Frame ein Zeichen an den Host gesendet, daraufhin darf das auf dem Host 
laufende Programm ein Echo generieren, das in einem der nächsten 
USB-Frames wieder zurück an den mc gesendet wird. Auf diese Weise wird 
für die Übertragung eines bytes mindestens 4 USB-Frames == 4ms benötigt, 
entsprechend einer Baudrate von 2500 Baud.

Gruß, Stefan

von M. K. (sylaina)


Lesenswert?

Was spricht hier gegen die Verwendung eines Hardware-Handshakes? Genau 
für solche Fälle wurde das doch erfunden.

von Stefan K. (stefan64)


Lesenswert?

Je nach Hardware kann es sein, daß nach einem gesetzten Handshake noch 
einige Zeichen gesendet werden, z.B. weil der Sende-UART einen FIFO 
besitzt. Wir haben an Windows-Systemen schon bis zu 16 gesendete Zeichen 
nach der Handshake-Flanke gemessen.
Die Intention des Handshake ist ja eigendlich, daß der Empfänger keinen 
Platz mehr im Eingangspuffer hat. In diesem Fall kann ein Sende-FIFO 
leicht kompensiert werden, indem einfach n Bytes vor Buffer-full das 
Handshake gesetzt wird.

Gruß, Stefan

von Karl H. (kbuchegg)


Lesenswert?

Stefan K. schrieb:
> Je nach Hardware kann es sein, daß nach einem gesetzten Handshake noch
> einige Zeichen gesendet werden, z.B. weil der Sende-UART einen FIFO
> besitzt. Wir haben an Windows-Systemen schon bis zu 16 gesendete Zeichen
> nach der Handshake-Flanke gemessen.
> Die Intention des Handshake ist ja eigendlich, daß der Empfänger keinen
> Platz mehr im Eingangspuffer hat. In diesem Fall kann ein Sende-FIFO
> leicht kompensiert werden, indem einfach n Bytes vor Buffer-full das
> Handshake gesetzt wird.

Hier gehts aber eher darum, dass vor rausschieben an die WS2812 die 
Interrupts gesperrt werden sollen. Aber man kann natürlich auch die 
Interrupts sperren, der Gegenstelle per Handshake die Dendefreigabe 
entziehen und dann einfach ein bischen warten, ob noch was kommt. Kommt 
was, dann beginnt die Wartezeit von vorne, kommt innerhalb der Wartezeit 
nichts mehr, dann ist das Handshake-Verbot wirksam und man beginnt auf 
die WS2812 rauszutakten.

Ist eine Möglichkeit. Und ich schliesse mich vollinhaltlich Thomas Elger 
an.

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.