Hallo!
Ich habe eine grundsätzliche Frage zum Thema UART und Interrupt. Wie
kann ich den Empfangsinterrupt beim Atmega austricksen?
Ich bin relativ neu bei C/C++ und Mikrocontroller. Habe mich aber glaub
einigermaßen in die Materie reingewurstelt und baue aktuell einen
LED-Tisch mit folgender Hardware:
-100 ws2812b RGB-LED in einer 10x10 Matrix
-Atmega1284P@16MHz mit Quarz
-verschiedener Kleinkram für Touch-Erkennung, Kommunikation,
Stromversorgung etc
Mein Programm funktioniert soweit. Sicherlich nicht schön und effizient
programmiert, aber ich kann durch ein Menü verschiedene Animationen
aufrufen, Einstellungen im EEPROM vornehmen, Signalquelle umschalten und
später kommen noch eine handvoll einfache Spiele hinzu.
Nun will ich gerne eine RS232-Schnittstelle implementieren um
Steuerbefehle empfangen zu können. Hardware mit Max232 ist bereits
vorhanden. Grundsätzlich denke ich, der Code ist machbar, zumal es ja
offenbar viele gute Libs hat. Ich stehe aber an der Stelle vor einer
Verständnissfrage:
Die LEDs werden über BitBanging angesteuert mit der Lib light_ws2812
https://github.com/cpldcpu/light_ws2812/blob/master/README.md
Die Sequenz für 100 LED dauert etwa 3ms. Aufruf erfolgt aktuell noch in
einem Timer-Interrupt, der mit ~51Hz ausgeführt wird. Da die LED
empfindlich auf Timing reagieren darf die Sequenz nicht unterbrochen
werden. Also ist ein Aufruf in der main mit abgeschaltenen Interrupts
auch nicht Besser.
Bei Standard-9600Baud können ja aber in den ~3ms Zeit fast 30 Zeichen
reintrudeln und den RX-Speicher hoffnungslos überlaufen lassen. Ein
Interrupt um empfangene Zeichen in einen größeren Puffer wegzuschreiben
geht nicht, da er ja die LED-Sequenz unterbrechen würde.
Habt ihr Ideen, wie ich das Problem umgehen könnte? Einen Attiny814 als
Puffer dazwischen?
(DSub->RX Attiny, TX Attiny->RX Mega1284, TX Mega1284->DSub) Scheint mir
aber übertrieben, aufwendig, kompliziert und Fehleranfällig.
Gibt es eine Art TTL-Baustein, der die Daten "Zwischenspeichern" und
wenn Zeit ist (also auf Befehl vom 1284P) weiterleiten kann?
Oder habt ihr Vorschläge, wie ich das ganze einfach in Software lösen
kann?
Oder sehe ich das alles einfach nur zu kritisch und das geht alles
problemlos?
Viele Grüße,
Sum
Möchtest du die Datenrate des UART noch einmal nachrechnen? Baud ist
nicht Byte/s sondern Bit/s.
Du könntest als primitivsten Ansatz die Baudrate herunter setzen auf zB
ungefährliche 2400Bd.
Falls die HW sich noch ändern lässt: Teile deine 10x10 Pixel auf in 4
Quadranten mit 5x5 pixel, und steuere die eins nach dem anderen. Jedes
Quadrant braucht dann weniger als 1ms zum ansteuern, und dir bleibt noch
ein bisschen Zeit um zu schauen ob beim UART was angekommen ist.
Nachdem alle 4 Quadrandten angesteuert sind nimmst du dir Zeit um die
UART-Zeichen auszuwerten, Kaffee zu trinken usw, bis die 20ms (bei deine
~50Hz) vergangen sind.
Etwa so:
Sum schrieb:> Habt ihr Ideen, wie ich das Problem umgehen könnte?
In Assembler programmieren und die Ausgabe an die LEDs nicht per
dümmlichem Bitbanging abwickeln.
> Oder habt ihr Vorschläge, wie ich das ganze einfach in Software lösen> kann?
Einfach ist relativ. Kommt ganz auf die Fähigkeiten des Betrachters an.
Einen Teil brauchst du jedenfalls nicht mehr selber entwickeln. Die
unterbrechbare WS28xx-Ausgabe für bis zu 1024 WS28xx in Assembler habe
ich schon fertig und bereits vor einiger Zeit hier gepostet. Ist zwar
für einen Tiny4313@20MHz designed, läßt sich aber ganz sicher auch auf
einen Mega1284P@16MHz anpassen, wenn deine Kohle nicht reicht, um einen
20MHz-Quarz für 23 Cent zu kaufen. Wenn du dir ihn hingegen leisten
kannst, brauchst du sogar bloss zwei Zeilen (die ersten beiden) zu
ändern und der Code läuft sofort nach Neuassemblierung auch auf einem
Mega1284P.
Allzu viel Luft für weitere Interupts neben dem für die LED-Ausgabe
benutzten ist zwar nicht, aber einer geht auf jeden Fall noch. Ich habe
z.B. in einem Projekt eine DDS-Soundausgabe mit 78kHz
Interruptfolgefrequenz parallel zu der LED-Ausgabe drin. UART mit selbst
115,2 kBit/s sollte also keinerlei Probleme bereiten, da ist die
maximale Interruptfolgefrequenz ja nur lächerliche 11,5kHz. Allerdings
muss die ISR hochoptimiert sein, ähnlich wie es auch die der LED-Ausgabe
ist.
Viel weniger kritisch ist Code, der auschließlich in main() läuft. Du
hast bei 20Mhz ungefähr 45% der Rechenzeit dort zur Verfügung und der
Code dort kommt auch ziemlich regelmäßig zum Laufen, die längste Pause
habe ich jetzt nicht im Kopf, sie ist aber in jedem Fall deutlich kürzer
als die Dauer der Übertragung des "Datenpaketes" für eineLED. Also
deutlich kürzer als 24/800000=30µs.
@Sum (Gast)
>Ich habe eine grundsätzliche Frage zum Thema UART und Interrupt. Wie>kann ich den Empfangsinterrupt beim Atmega austricksen?
Warum sollte man das?
>Ich bin relativ neu bei C/C++ und Mikrocontroller.
Eben DARUM sollte man eher weniger tricksen.
>Nun will ich gerne eine RS232-Schnittstelle implementieren um>Steuerbefehle empfangen zu können.
Da muss man rein gar nichts tricksen.
>Die LEDs werden über BitBanging angesteuert mit der Lib light_ws2812>https://github.com/cpldcpu/light_ws2812/blob/maste...
Hmm.
>Die Sequenz für 100 LED dauert etwa 3ms. Aufruf erfolgt aktuell noch in>einem Timer-Interrupt, der mit ~51Hz ausgeführt wird.
Da liegt schon das erste Problem. Diese Aktion gehört in die
Hauptschleife!
Siehe Interrupt.
> Da die LED>empfindlich auf Timing reagieren darf die Sequenz nicht unterbrochen>werden.
Für EINE LED! Aber man muss nicht die drei ms durchweg senden.
> Also ist ein Aufruf in der main mit abgeschaltenen Interrupts>auch nicht Besser.
Doch. Denn man kann, sinnvolle Programmierung vorausgesetzt, an weniger
zeitkritischen Stellen den UART abfragen (neudeutsch polling) und die
Daten zwischenspeichern, z.B. in einem FIFO.
>Bei Standard-9600Baud können ja aber in den ~3ms Zeit fast 30 Zeichen>reintrudeln
DREI! Siehe Baud.
>und den RX-Speicher hoffnungslos überlaufen lassen. Ein>Interrupt um empfangene Zeichen in einen größeren Puffer wegzuschreiben>geht nicht, da er ja die LED-Sequenz unterbrechen würde.
Ja.
>Habt ihr Ideen, wie ich das Problem umgehen könnte? Einen Attiny814 als>Puffer dazwischen?
NÖ.
>(DSub->RX Attiny, TX Attiny->RX Mega1284, TX Mega1284->DSub) Scheint mir>aber übertrieben, aufwendig, kompliziert und Fehleranfällig.
Eben.
>Gibt es eine Art TTL-Baustein, der die Daten "Zwischenspeichern" und>wenn Zeit ist (also auf Befehl vom 1284P) weiterleiten kann?
Hirn 2.0 mit gescheiter Programmierung. GGf. nutzt man das SPI, um die
Daten in die LEDs zu takten, das entspannt die Sache auch nochmal
deutlich.
>Oder sehe ich das alles einfach nur zu kritisch und das geht alles>problemlos?
Es geht, wenn gleich man schon ein paar KONZEPTE kennen und umsetzen
muss. Mit tricksen hat das wenig zu tun.
Da der Resetcode erst nach 50us erkannt wird, hat man zwischen jedem BIT
für die LEDs 50us Zeit, andere Dinge zu tun. Praktisch reicht es
wahrscheinlich, nach jedem Byte oder gar jeder LED oder einer Anzahl N
LEDs eine kleine Pause zu machen und den UART abzufragen. Langweilig,
zumal 50us bei 16 MHz eine kleine Ewigkeit sind ;-)
Sum schrieb:> Die Sequenz für 100 LED dauert etwa 3ms.
Ja.
> Bei Standard-9600Baud können ja aber in den ~3ms Zeit fast 30 Zeichen> reintrudeln und den RX-Speicher hoffnungslos überlaufen lassen.>
Nein, es sind (fast) 3 Zeichen.
> Aufruf erfolgt aktuell noch in> einem Timer-Interrupt, der mit ~51Hz ausgeführt wird.
In der ISR irgendetwas ausführen, vor allem etwas, das 3ms dauert, ist
eine schlechte Idee.
> Habt ihr Ideen, wie ich das Problem umgehen könnte? Einen Attiny814 als> Puffer dazwischen?
Nein.
51Hz = 19ms - 3ms = 16ms für andere Sachen.
Also, Steuerbefehl (1 Byt) wird gesendet - nur ein Byte und dann wird
auf Antwort gewartet.
Dieses Byte landet in UART Data Register, RXC Flag wird gesetzt.
Nachdem Daten für WS2812 raus sind, wird TXC geprüft.
Falls gesetzt, hat dein uC noch 16ms Zeit um eine Bestätigung raus
zuschicken, kompleten Steuerbefehl zu empfangen und auszuführen.
Wo ist da ein Problem ?
Falk B. schrieb:
Etwas vorweg:
Musst du immer 50 Zeilen zitieren, um dann ein "Hmmm" oder "Ja" von
sich zu geben ?
>> Da die LED>>empfindlich auf Timing reagieren darf die Sequenz nicht unterbrochen>>werden.>> Für EINE LED! Aber man muss nicht die drei ms durchweg senden.
LOL.
Natürlich muss man das.
Falk B. schrieb:> Da der Resetcode erst nach 50us erkannt wird, hat man zwischen jedem BIT> für die LEDs 50us Zeit, andere Dinge zu tun. Praktisch reicht es> wahrscheinlich, nach jedem Byte oder gar jeder LED oder einer Anzahl N
Selbstverständlich sind das keine 50us, besonders WS2812B sind da sehr
zickig, alles über 20us ist schon reines Gluck.
Und warum soll er dauernd hin und her springen, wenn zwischen
Auffrischen 16ms Zeit ist (etwa 800 Mal so lange).
Falk B. schrieb:> Hirn 2.0 mit gescheiter Programmierung.
Ja, anstatt 1000 Worte schreiben ohne etwas gescheites zu sagen
oder eine konkrete Lösung anzubieten.
> GGf. nutzt man das SPI, um die> Daten in die LEDs zu takten, das entspannt die Sache auch nochmal> deutlich.
Selbstverständlich nicht.
WS2812 mit SPI ohne DMA ansteuern ist und bleibt Blödsinn.
Entweder man bleibt in der SPI Schleife, dann ist da kein Unterschied
zu Bitbanging, oder man arbeitet mit Interrupt, dann kann der uC von
laufendem Hin- und Herspringen zwischen main() und ISR sowieso nichts
gescheites machen.
@ Marc Vesely (Firma: Vescomp) (logarithmus)
> Musst du immer 50 Zeilen zitieren, um dann ein "Hmmm" oder "Ja" von> sich zu geben ?
Hmmm, vielleicht ;-)
>>> Da die LED>>>empfindlich auf Timing reagieren darf die Sequenz nicht unterbrochen>>>werden.>>> Für EINE LED! Aber man muss nicht die drei ms durchweg senden.> LOL.> Natürlich muss man das.
Nö. Siehe Datenblatt. Reset wird erst nach 50us Sendepause auf LOW
erkannt. Schrieb ich bereits.
Falk B. schrieb:> Nö. Siehe Datenblatt. Reset wird erst nach 50us Sendepause auf LOW> erkannt. Schrieb ich bereits.
Ja, das steht da. Aber die meisten WS2812b haben das Datenblatt leider
nicht gelesen.
@ Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
>> Nö. Siehe Datenblatt. Reset wird erst nach 50us Sendepause auf LOW>> erkannt. Schrieb ich bereits.>Ja, das steht da. Aber die meisten WS2812b haben das Datenblatt leider>nicht gelesen.
Selbst wenn es nur 20us sind, ist das mehr als ausreichend.
Falk B. schrieb:> Da der Resetcode erst nach 50us erkannt wird
[...]
> Praktisch reicht es> wahrscheinlich, nach jedem Byte oder gar jeder LED oder einer Anzahl N> LEDs eine kleine Pause zu machen und den UART abzufragen.
Das hast du niemals wirklich selber probiert, soviel ist mal sicher. Ein
typisches Dummschwätzer-Posting.
Tatsächlich ist es nämlich so: Man darf sich keinesfalls darauf
verlassen, dass erst ab 50µs ein Reset erkannt wird, das passiert viel
früher. Nämlich bei der erstenLED der Kette. Dort zuerst und in der
Folge auch bei den weiteren LEDs...
Die 50µS des DB beschreiben nämlich die Anforderungen an den Reset für
eine Kette maximaler Länge. Erst ab dieser Resetdauer ist garantiert,
dass auch die letzteLED einer Kette maximaler Länge den Reset noch
als solchen erkennt.
Trotzdem ist dein Ansatz nicht völlig daneben. Man kann tatsächlich
anderen Code in einer dümmlichen Bitbanging-Ausgabe unterbringen, der
das Timing verzerrt, ohne die LED-Ausgabe insgesamt aus dem Tritt zu
bringen. Das liegt daran, dass die "Sensitivität" der WS28xx generell
auf die Dauer der *Low*-Pegel im Signal geeicht ist, nicht nur bezüglich
des Reset, sondern auch bezüglich der Daten.
Das ermöglicht es, die High-Phasen eines jeden Datenbit DB-widrig zu
verlängern. Allerdings nur in Maßen, irgendwann kommen die LEDs aus dem
Tritt. Je länger die Kette und je länger die High-Phase, desto
wahrscheinlicher. Bei voller Kettenlänge ist dieser Trick praktisch
nicht mehr anwendbar, da sollte man tunlichst auch in dieser Beziehung
an das vom DB vorgegebene Timing halten.
> Langweilig,> zumal 50us bei 16 MHz eine kleine Ewigkeit sind ;-)
Es geht nicht um die 50µs, die frei sind, sondern um die 3ms (bei 100
LEDs), die es nicht sind. Das wenigstens solltest du doch begriffen
haben...
Leider muss ich Falk recht geben. Ein falsches Hardwarekonzept macht
die Sache schwieriger. Es würde schon gehen wenn man die Rs232 mit
Flusskontrolle benutzt. So werden immer dann Zeichen gelesen wenn die
Daten auf den Streifen geschrieben wurden. Die Flusskontrolle ist aber
so ziemlich aus der Mode gekommen.
@ c-hater (Gast)
>Das hast du niemals wirklich selber probiert, soviel ist mal sicher. Ein>typisches Dummschwätzer-Posting.
Das sagt der Richtige ;-)
Nimm deine Pillen und verschone uns mit deinen Beiträgen. Danke.
Falk B. schrieb:> Selbst wenn es nur 20us sind, ist das mehr als ausreichend.
Wofür ?
Aber selbst wenn es 50us sind, warum und wozu ?
Es besteht ganz einfach keine Notwendigkeit, UART in dieser Zeit
abzufragen.
Taster usw. vielleicht, da magst du Recht haben, aber UART muss
bestimmt nicht abgefragt werden.
Kann natürlich, bringt aber überhaupt keine Vorteile.
@Sum (Gast)
>-100 ws2812b RGB-LED in einer 10x10 Matrix>Die LEDs werden über BitBanging angesteuert mit der Lib light_ws2812>Die Sequenz für 100 LED dauert etwa 3ms.
Nun ja, es ist wohl eher KEINE LED-Matrix, so wie es der Rest der
Welt versteht, sondern eine Kette aus 100 intelligenten LEDs. Die 100
LEDs könnte man in 4x25 Stränge aufteilen, dann dauert es nur noch
~750us pro Kette. Dazwischen kann man in Ruhe andere Dinge tun, ganz
ohne Stress. Und da du es so oder so Bitbanging machst, geht das auch
mit mehreren, verschiedenen Pins.
Ob das diese Lib kann weiß ich nicht.
@ Marc Vesely (Firma: Vescomp) (logarithmus)
>> Selbst wenn es nur 20us sind, ist das mehr als ausreichend.> Wofür ?
Um den UART abzufragen, schrieb ich schon mehrfach.
> Es besteht ganz einfach keine Notwendigkeit, UART in dieser Zeit> abzufragen.
Doch, vor allem wenn man, warum auch immer, höhere Baudraten OHNE
Flußkontrolle nutzen will. Kann man machen, muss man nicht.
> Taster usw. vielleicht, da magst du Recht haben, aber UART muss> bestimmt nicht abgefragt werden.> Kann natürlich, bringt aber überhaupt keine Vorteile.
Doch, siehe oben.
Falk B. schrieb:> Nimm deine Pillen und verschone uns mit deinen Beiträgen. Danke.
Nein, das werde ich ganz sicher nicht tun. Im Gegenteil, dieses Posting
von dir liefert mir die Steilvorlage, dich komplett zu demontieren.
Denn ich kann durch Code jede meiner Aussagen in diesem Thread für jeden
nachvollziehbar beweisen. Was dir hingegen äußerst schwerfallen
dürfte...
Willst du wirklich für jeden offensichtlich als Vollarsch mit
Gottkomplex dastehen oder bist du bereit jetzt einen Rückzieher zu
machen?
Last chance...
Falk B. schrieb:>> Kann natürlich, bringt aber überhaupt keine Vorteile.>> Doch, siehe oben.
Nein, siehe unten.
PC (oder wer auch immer) sendet ein einziges Byte und wartet auf
Antwort (wobei es gar kein warten ist, sondern nur Abfrage von Zeit
zu Zeit ob ein Zeichen empfangen worden ist).
Kann sowieso nicht länger als 3ms dauern.
Danach hat der PC (oder wer auch immer) 16ms Zeit um den Rest zu
senden und der uC hat genauso viel Zeit, um das auszuführen.
>> Es besteht ganz einfach keine Notwendigkeit, UART in dieser Zeit>> abzufragen.>> Doch, vor allem wenn man, warum auch immer, höhere Baudraten OHNE> Flußkontrolle nutzen will.
Was haben höhere Baudraten damit zu tun ?
Und warum sollte die andere Seite Kilobits ohne Flußkontrolle
losschicken ?
Und mit Flusskontrolle bist du genausoweit wie mit 1 Byte und
anschliessender Bestätigung, weil der PC (oder wer auch immer)
immer auf RTS oder CTS warten muss.
Wo siehst du da irgendwelche Vorteile ?
Hältst du beim Autofahren auch alle paar Km an, um Sprit aus
dem Kanister nachzufüllen, anstatt eine Tankstelle anzufahren
wenn es Zeit dazu ist ?
Da die UART ja bis zu 3 Byte puffern kann, sollte das doch mit den 3ms
und 9600 Baud noch gerade so hinhauen.
Vorzugsweise schreibt man den RX-Interrupt als do{}while() Schleife und
spart so den Prolog/Epilog-Overhead ein, falls wirklich 3 Byte
angekommen sind.
Und mit Parity und 2 Stopbits hat man etwas mehr Luft (2,4Byte/3ms).
P.S.:
Ist doch nicht so einfach, es können ja schon 9 Bits gekommen sein, wenn
der Timerinterrupt zuschlägt. Man müßte also noch mit Pin-Change den
RXD-Pin überwachen und gegebenenfalls den Timerinterrupt verzögern, bis
das Byte komplett ist.
D.h. Pin-Change Interrupt sperrt den Timerinterrupt und der RX-Interrupt
gibt ihn wieder frei.
4800Baud wäre die einfachere Lösung.
Peter D. schrieb:> Da die UART ja bis zu 3 Byte puffern kann
Nein, das kann sie nicht. Es sind nur (knapp) 2 Byte. Nämlich ein volles
Byte in (received) UDR und alle Datenbits eines zweiten Bytes im
Empfangsschieberegister, abzüglich des Stop-Bits dieses Bytes, Denn
dessen Eintreffen verwirft bereits den Inhalt von UDR und ersetzt ihn
durch den Inhalt des Scheiberegisters.
Und selbst wenn es wirklich drei wären:
Was machst du mit diesem Ansatz, wenn es sich nicht um 100, sondern um
200 WS28xx-LEDs handelt. Die UART-Bitrate halbieren? Und wenn es 1024
sind, noch zweimal halbieren?...
Das wäre zumindest dann ziemlich kontraproduktiv, wenn über eben diesen
Kanal die Daten für die LEDs reinkommen sollen, findest du nicht auch?
Meine Fresse, warum gebt ihr nicht einfach zu, dass C hier einfach mal
Scheisse ist. Selbst noch mit dem Trick, den ich euch verraten habe, der
es euch ermöglichen würde, die unsägliche C-Schwäche bei ISRs zumindest
für kurze Ketten hinreichend gut auch in dümmlichen Bitbanging-Ausgaben
zu umschiffen. Jedenfalls wenn man ihn (im Gegensatz zu diesem unsäglich
inkompetenten Brunner-Typen wenigstens begreift und sinnvoll
anwendet...)
Peter D. schrieb:> D.h. Pin-Change Interrupt sperrt den Timerinterrupt und der RX-Interrupt> gibt ihn wieder frei.> 4800Baud wäre die einfachere Lösung.
Nein.
Die einfachere (und einzig sinnvolle) Lösung habe ich schon
genannt. Dieses rumhantieren mit Rx- und Pinchange Interrupts
verkompliziert die Sache nur unnötig.
Ohne DMA gehen immer 3ms verloren, es sei denn, man macht es mit
Assembler und Tricks (wie c-hater).
Und selbst dann muss es durchdacht und miteinander verschachtelt
sein, damit auch was sinnvolles daraus wird.
Das alles ist aber ganz einfach unnötig - es ist genügend Zeit
vorhanden, vor allem da man (nach Bestätigung) das Ganze mit 250KB
oder mit 500KB anstatt mit 4800B rausjagen kann...
c-hater schrieb:> Peter D. schrieb:>>> Da die UART ja bis zu 3 Byte puffern kann>> Nein, das kann sie nicht. Es sind nur (knapp) 2 Byte. Nämlich ein volles> Byte in (received) UDR und alle Datenbits eines zweiten Bytes im> Empfangsschieberegister, abzüglich des Stop-Bits dieses Bytes, Denn> dessen Eintreffen verwirft bereits den Inhalt von UDR und ersetzt ihn> durch den Inhalt des Scheiberegisters.
Vielleicht solltest du doch mal einen Blick ins Datenblatt riskieren,
c-hater. So steht's im Abschnitt zur USART:
...
The Data OverRun (DORn) Flag indicates data loss due to a receiver
buffer full condition. A Data OverRun occurs when the receive buffer is
full (two characters), it is a new character waiting in the Receive
Shift Register, and a new start bit is detected.
...
Macht drei, wenn ich mich nicht verrechnet habe, und der Overrun tritt
erst beim darauffolgenden Startbit auf.
c-hater schrieb:> Nein, das kann sie nicht. Es sind nur (knapp) 2 Byte.
OMG.
Probiers doch wenigstens mal aus, eh Du solchen Schmarrn erzählst.
Schreib eine Schleife aus 5s Delay und Senden solange RX-Puffer nicht
leer.
Und dann gibt z.B. "12345" ein.
Die '1' und '2' landen im Doppelpuffer. Die '3' bleibt solange im
Schieberegister, bis das nächste Startbit erkannt wird.
Wenn Du alles innerhalb der 5s gesendet hast, kriegst Du somit nach 5s
"125" zurück.
Rainer B. schrieb:> Macht drei, wenn ich mich nicht verrechnet habe, und der Overrun tritt> erst beim darauffolgenden Startbit auf.
Nein, du hast dich nicht verrechnet aber das ist auch egal.
Wenn DOR Flag gesetzt wird, ist es unmöglich festzustellen,
wieviele Bytes schon ev. verlorengegangen sind - es kann ja schon
2 Bytes vorher gesetzt worden sein.
Und wenn so etwas passiert, dann ist irgendetwas mit deinem Program
falsch.
Anstatt eine 100% sichere und ungefähr 100 Mal schnellere Prozedur
mit Bestätigung zu implementieren, wird auf einer überaus langsamen
und unsicheren Prozedur bestanden.
Macht Ihr das beruflich auch so ?
Danke für eure Hinweise.
Ich hab mich an ein paar Stellen blöd ausgedrückt, sorry dafür.
Also, erstens: natürlich keine 30 Zeichen, da habe ich in der Eile
Symbolrate mit Zeichen vertan, aber Symbole hier gleich Bit.
Sehe ich das richtig, dass ein 8N1 Datenbyte bei 9600baud incl
Start/Stop dann 1042 Mikrosekunden benötigt?
Zweitens: die Senderoutine kommt auch wieder aus dem Int raus, ist mir
durchaus bewusst. Den Timertick habe ich ja schon. Hatte nur Probleme im
Code und zur Fehlersuche hatte ich umgebaut.
@Falk Brunner
Ja, elektrisch gesehen eine Kette aus 100 LEDs. Mechanisch als 10x10
Matrix aufgebaut, nicht in snakelines.
Dass der Aber feud in main nicht besser ist meinte ich in Bezug auf den
Sende-Code, der nicht unterbrochen werden darf.
@Eric B.
Deine Idee gefällt mir eigentlich. Leider geht es nicht, die externe
Quelle ist ein "LEDPlayer" auf den ich per Relais umschalten kann,
dieser hat nur einen Ausgang. Für die komplexen Bilder wird der per USB
vom PC angesteuert.
@c-hater
Wie kann man deinen Code unterbrechen? Kann man deinen asm-Code in C
einbinden? Ich habe von Assembler keine Ahnung, werde also in C
weitermachen. Aber soweit ich weiß ist die von mir verwendete Lib auch
in (mindestens teilweise) in Assembler geschrieben.
@Marc Vesely
Ich muss mal schauen, ob ich noch einen Pin freiräumen kann für
Flusskontrolle. Unterstützt denn jeder USB-RS232 Adapter die
Flusskontrolle von Haus aus? Wenn ich mit dem com-Port verbinde, wollte
ich nichts justieren müssen, daher auch die 9,6kbaud.
Wenn das jeder com-Port standardmäßig unterstützt wäre das ja auch eine
saubere Lösung.
Sum schrieb:> Flusskontrolle
Ehe du lötest oder programmierst, sieh dir mal die Spezifikation an. Es
ist mitnichten so, dass der Sender verstummt, sobald CTS wegfällt. Je
nach UART Bauform kann da noch einiges tröpfeln.
Flowcontrol per RTS-CTS oder per Software ist nicht trivial.
Sum schrieb:> @Marc Vesely> Unterstützt denn jeder USB-RS232 Adapter die> Flusskontrolle von Haus aus?
Nein.
> Wenn ich mit dem com-Port verbinde, wollte> ich nichts justieren müssen, daher auch die 9,6kbaud.
Brauchst du auch nicht, du hast ja einen Quarz.
Sum schrieb:> Wenn das jeder com-Port standardmäßig unterstützt wäre das ja auch eine> saubere Lösung.
Wozu ?
Marc V. schrieb:> Nein.> 51Hz = 19ms - 3ms = 16ms für andere Sachen.>> Also, Steuerbefehl (1 Byt) wird gesendet - nur ein Byte und dann wird> auf Antwort gewartet.> Dieses Byte landet in UART Data Register, RXC Flag wird gesetzt.> Nachdem Daten für WS2812 raus sind, wird RXC geprüft.> Falls gesetzt, hat dein uC noch 16ms Zeit um eine Bestätigung raus> zuschicken, kompleten Steuerbefehl zu empfangen und auszuführen.
Du kannst es natürlich machen, wie es dir beliebt, anstatt so:
Marc V. schrieb:> Das alles ist aber ganz einfach unnötig - es ist genügend Zeit> vorhanden, vor allem da man (nach Bestätigung) das Ganze mit 250KB> oder mit 500KB anstatt mit 4800B rausjagen kann...
P.S.
Deine MEGA hat mit 16MHz Quarz von 250Kbps bis 1Mbps einen Fehler
von genau keinen, nämlich 0,0%.
Georg G. schrieb:> Baud ist> nicht Byte/s sondern Bit/s.
Nö.... sondern Schrittgeschwindigkeit. Also Schritte pro Sekunde. Es
gibt Verfahren die mehrere Bits pro Schritt übertragen können. Zum
Beispiel 8 Bits bei Bei 256-QAM.
BlaBla schrieb:> Nö....
Bei dem hier in 99.9% aller Fälle verwendeten Verfahren besteht kein
Unterschied. Und wenn wir schon bei kleinen Rosinen sind: Nicht Schritte
sondern Symbole wäre korrekt.