Forum: Mikrocontroller und Digitale Elektronik Serielle Verbindung synchronisieren


von Jetta (Gast)


Lesenswert?

Hallo,

ich habe eine kleine Anfängerfrage.
Da ich Lust hatte zu Basteln, habe ich mir eine 2D LED-Matrix zusammen 
gebaut. Diese werden im Multiplexverfahren durch einen Prozessor 
gesteuert. Jetzt habe ich mir eine sehr spärliche GUI mit QT 
zusammengeklickt und kam auf die Idee die Daten direkt an den Prozessor 
zu übertragen.

D.h. ich will Daten vom PC aus an den µC senden. Billigen China USB-TLL 
Wandler und eine Comport Lib aus dem Internet habe ich bereits am 
Laufen.
Leider werden doch recht viele Daten geschickt und irgendwie klappt das 
nicht so recht.

Wie ich es gemacht habe:
8Bit werden übertragen: Code wird gesendet mit 1xxx xxxx um anzukündigen 
das ein Befehl kommt. Daten fangen immer mit 0 an.
Dann habe ich die ca. 150 LEDs in 7 Bit Blöcke zerlegt (d.h. 7 Leds auf 
einmal) und übertrage die hintereinander. Fertig. Funktioniert leider 
aber nicht so richtig. Wenn zu schnell zweimal gesendet wird, gibts 
Murks. Manchaml gibts einfach so Murks. Mit 200 Delays gehts, aber 
schnarch langsam.

Wie macht man so was einigermaßen ordentlich (ohne Hardware Handshake). 
Oder soll man sich jedes Datenpaket, per Rückmeldung bestätigen lassen, 
sowas wie ein eigenes Protokoll???

Danke von einem der das noch nie gemacht hat :-)

von Falk B. (falk)


Lesenswert?

@ Jetta (Gast)

>zusammengeklickt und kam auf die Idee die Daten direkt an den Prozessor
>zu übertragen.

Dann tu das doch ;-)

>8Bit werden übertragen: Code wird gesendet mit 1xxx xxxx um anzukündigen
>das ein Befehl kommt. Daten fangen immer mit 0 an.

Kann man machen.

>Dann habe ich die ca. 150 LEDs in 7 Bit Blöcke zerlegt (d.h. 7 Leds auf
>einmal) und übertrage die hintereinander. Fertig. Funktioniert leider
>aber nicht so richtig. Wenn zu schnell zweimal gesendet wird, gibts
>Murks. Manchaml gibts einfach so Murks. Mit 200 Delays gehts, aber
>schnarch langsam.

>Wie macht man so was einigermaßen ordentlich (ohne Hardware Handshake).

Einfach schnell, sinnvollerweise mit einem UART-Interrupt.
Geh erstmal mit der Baudrate runter, sagen wir auf 9k6 oder so.

>Oder soll man sich jedes Datenpaket, per Rückmeldung bestätigen lassen,

Kann man machen, muss man aber nicht.

>sowas wie ein eigenes Protokoll???

Hast du doch schon.

von Rolf Magnus (Gast)


Lesenswert?

Jetta schrieb:
> Wie ich es gemacht habe:
> 8Bit werden übertragen: Code wird gesendet mit 1xxx xxxx um anzukündigen
> das ein Befehl kommt. Daten fangen immer mit 0 an.

Also wie bei MIDI.

> Dann habe ich die ca. 150 LEDs in 7 Bit Blöcke zerlegt (d.h. 7 Leds auf
> einmal) und übertrage die hintereinander. Fertig. Funktioniert leider
> aber nicht so richtig. Wenn zu schnell zweimal gesendet wird, gibts
> Murks. Manchaml gibts einfach so Murks. Mit 200 Delays gehts, aber
> schnarch langsam.

Welche Bitrate ist denn eingestellt, und was ist das für ein µC?

von Jonas B. (jibi)


Lesenswert?

Aha also quasi MIDI für Arme? :D
Find ich gut.

>Geh erstmal mit der Baudrate runter, sagen wir auf 9k6 oder so.
Wo steht wie schnell er gerade unterwegs ist?

Gruß Jonas

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Kann es sein, dass das Timing in deinem Controller auf Delays basiert?

von Jetta (Gast)


Lesenswert?

Sorry, war gestern unterwegs und muss auch heute Arbeiten.

Deswegen in kürze:
Controller LPC1766
Baudrate ist 115200 (also viell. ein bisschen flott)
Uartinterrupt wollte ich mir sparen, da ich dachte das ist nicht 
zeitkritisch und frage es einfach in der main ab. Der LPC hat wohl einen 
Hardwarebuffer...
Code poste ich nachher.

von Jim M. (turboj)


Lesenswert?

Jetta schrieb:
> Controller LPC1766
> Baudrate ist 115200 (also viell. ein bisschen flott)

LOL. Ich habe hier LPC1768 mit 1,8 MBaud (RS485) zu laufen, und zwar 
beim minimalen CCLK von 29,49 MHz. Da geht nicht ein Bit verloren.

> Uartinterrupt wollte ich mir sparen

Dann sollte man aber genau wissen, wie lange die Hauptschleife warten 
darf. Hint: Nicht allzu lange. Ein Delay() ist dann ziemlich ungeeignet.

> Der LPC hat wohl einen Hardwarebuffer...

Den man übrigens erst über ein Register einschalten muss. Der 16 Byte 
FIFO ist dann durchaus nützlich - Deine Hauptschleife muss ihn aber auch 
schnell genug leeren können.

von Karl H. (kbuchegg)


Lesenswert?

>  Wenn zu schnell zweimal gesendet wird, gibts Murks.

Kommt mir komisch vor.

Was hat denn der µC sonst noch so zu tun?
Das Mutiplexing kanns nicht wirklich sein. Wenn man das nach den Regeln 
der Kunst macht (in einem Timer-Interrupt), dann verbraucht das fast 
keine Rechenzeit. Auf jeden Fall nicht so viel Rechenzeit, dass man 
damit Probleme mit einer UART kriegt, weil man diverse Hardaware-Buffer 
nicht rechtzeitig entleeren kann.


Ich denke mal, dein eigentliches Problem besteht darin, dass dein 
Multiplexing Murks ist. Die Probleme mit der UART sind nur Symptome, die 
ihre Ursache im Multiplexing-Murks haben.

von Daniel V. (danvet)


Lesenswert?

Jim Meba schrieb:
> Jetta schrieb:
>> Controller LPC1766
>> Baudrate ist 115200 (also viell. ein bisschen flott)
>
> LOL. Ich habe hier LPC1768 mit 1,8 MBaud (RS485) zu laufen, und zwar
> beim minimalen CCLK von 29,49 MHz. Da geht nicht ein Bit verloren.
>

RS485 != RS232
http://de.wikipedia.org/wiki/RS-232#Leitungsl.C3.A4nge_und_.C3.9Cbertragungsrate

Bei 115200 darf das Kabel nicht allzu lang sein und auch die 
Steckverbindungen sollten was taugen. Ansonsten wird das bei der 
Geschwindigkeit (rein hardwaremässig) nichts.

von Falk B. (falk)


Lesenswert?

@ Daniel V. (danvet)

>RS485 != RS232

Ach ne?

>Bei 115200 darf das Kabel nicht allzu lang sein und auch die
>Steckverbindungen sollten was taugen. Ansonsten wird das bei der
>Geschwindigkeit (rein hardwaremässig) nichts.

C'mon! 115k2 geht über den rostigsten Klingeldraht, den du dir 
vorstellen kannst. Das hat mit HF nichts zu tun. Auch an die Stecker 
werden keine nennenswerten Anforderungen gestellt. Wenn es sein muss, 
läuft das über einen Schukostecker ;-)

von Falk B. (falk)


Lesenswert?

@ Karl Heinz (kbuchegg) (Moderator)

>Was hat denn der µC sonst noch so zu tun?
>Das Mutiplexing kanns nicht wirklich sein. Wenn man das nach den Regeln
>der Kunst macht (in einem Timer-Interrupt), dann verbraucht das fast
>keine Rechenzeit.

So lange im Forum unterwegs und immer noch so optimistisch? 
Beeindruckend!

>Auf jeden Fall nicht so viel Rechenzeit, dass man
>damit Probleme mit einer UART kriegt, weil man diverse Hardaware-Buffer
>nicht rechtzeitig entleeren kann.

Nicht wenige Kandidaten haben hier schon mit einer blinkenden LED einen 
32 Bit Kern in die Knie gezwungen ;-)

von Karl H. (kbuchegg)


Lesenswert?

Falk Brunner schrieb:
> @ Karl Heinz (kbuchegg) (Moderator)
>
>>Was hat denn der µC sonst noch so zu tun?
>>Das Mutiplexing kanns nicht wirklich sein. Wenn man das nach den Regeln
>>der Kunst macht (in einem Timer-Interrupt), dann verbraucht das fast
>>keine Rechenzeit.
>
> So lange im Forum unterwegs und immer noch so optimistisch?
> Beeindruckend!

Ich wollte höflich sein und nicht gleich mit der Tür ins Haus fallen :-)

von Jetta (Gast)


Lesenswert?

Soooo...

ich habe alles bis auf die Multiplexinggeschichte ausgestellt... daran 
kanns nicht liegen..
Meine Interruptroutine ist nicht die kürzeste, aber auch nicht sooooo 
schlecht.

Danke für die vielen Antworten, ich denke ich weiß woran es liegt. Es 
ist wirklich das Problem, dass der Empfang von Daten nicht über einen 
Interrupt abgearbeitet wird. Die main macht noch andre Sachen und die 
Daten, welche in der Zwischenzeit gesendet werden, gehen verloren. Warum 
es dann unsynchron ist weiß ich noch nicht genau (eigentlich müsste ja 
der nächste SendAll Befehl abgewartet werden.

Ich poste trotzdem mal den Code, vielleicht fällt einem ja noch was auf 
...
1
void video_controller(void)
2
{
3
  static uint8_t row = 0;
4
5
  const uint8_t row_pins[row_max] = {ROW00, ROW01, ROW02, ROW03, ROW04, ROW05, ROW06};
6
7
  //static uint8_t col = 0;
8
9
  // DIMMEN?
10
11
  if (row < row_max-1)
12
    row++;
13
  else
14
    row = 0;
15
16
  // alle Reihen deaktivieren
17
  ROW_PORT->FIOPIN &= ~((1 << ROW00)|(1 << ROW01)|(1 << ROW02)|(1 << ROW03)|(1 << ROW04)|(1 << ROW05)|(1 << ROW06));
18
  // Masken aktivieren
19
  //COL1_PORT->FIOMASK = ~(0x00);
20
  LPC_GPIO1->FIOMASK = COL1_PORT_MASK;
21
  COL2_PORT->FIOMASK = COL2_PORT_MASK;
22
  // Daten anlegen
23
  COL1_PORT->FIOPIN = P_videoRam_read[row] << (COL11-7);// & 0x0007FF80;
24
  COL2_PORT->FIOPIN = P_videoRam_read[row] << COL18;// & 0x0000007F;
25
  // Masken deaktivieren
26
  COL1_PORT -> FIOMASK = 0x0000;
27
  COL2_PORT -> FIOMASK = 0x0000;
28
29
  // aktuelle Reihe aktivieren
30
  ROW_PORT->FIOPIN |= (1 << row_pins[row]);
31
32
33
}

Das Dekativieren sollte man wohl mal in eine Konstante schreiben, 
eventuell erkennt das der Compiler aber auch ....

Hauptteil der Main auf dem Prozessor
1
      if (received_data == SEND_ALL)
2
      {
3
        // Empfange Datenblöcke
4
        // zuerst wird ROW0 COL0 - COL6 übertragen (7 Bit) // Rest muss Null sein
5
        // dann ROW0 COL7 - COL13           (7 Bit) // Rest muss Null sein
6
        // dann ROW0 COL14 - COL18           (5 Bit) // Rest muss Null sein
7
        clear_memory();
8
        uint32_t row_buffer = 0;
9
        uint8_t ii = 0;
10
        //write_row
11
        for (ii = 0; ii < 7; ii++)
12
        {
13
          row_buffer = 0;
14
          // Empfange erstes Datenpaket
15
          row_buffer |= uart_get_char_block() << 12;
16
          row_buffer |= uart_get_char_block() << 5;
17
          row_buffer |= uart_get_char_block() << 0;
18
          write_row(ii, row_buffer);
19
        }
20
21
        swap_memory_pointer();
22
      }



Das ist ein Teil aus meinem C Programm was auf dem PC läuft.
1
void MyWidget::SendDataRS232()
2
{
3
    ArrayToVideoRam();
4
    ComWrite(COM,0x80); // Send all Befehl
5
    for (int i = 0; i < rowCount; i++){
6
        RS232Write(COM,P_videoRam_write[i]>> (7+5));
7
        RS232Write(COM,(P_videoRam_write[i]>> (5)) & 0xFF);
8
        RS232Write(COM,P_videoRam_write[i]>> (0) & 0x1F);
9
    }
10
}

von Daniel V. (danvet)


Lesenswert?

Falk Brunner schrieb:
> @ Daniel V. (danvet)
>
>>RS485 != RS232
>
> Ach ne?
>
>>Bei 115200 darf das Kabel nicht allzu lang sein und auch die
>>Steckverbindungen sollten was taugen. Ansonsten wird das bei der
>>Geschwindigkeit (rein hardwaremässig) nichts.
>
> C'mon! 115k2 geht über den rostigsten Klingeldraht, den du dir
> vorstellen kannst. Das hat mit HF nichts zu tun. Auch an die Stecker
> werden keine nennenswerten Anforderungen gestellt. Wenn es sein muss,
> läuft das über einen Schukostecker ;-)

Ich habe nicht behauptet, dass 115k2 Hz HF sei. Natürlich kannst du das 
über einen rostigen Nagel übertragen. Oder über deinen Klingedraht vom 
Keller zum Dach schicken.
Die Frage ist, was damit passieren soll. Und wenn das eine RS232 sein 
soll (PC->µC), dann geht das bei 115k2 eben nicht mehr ganz so einfach:
http://de.wikipedia.org/wiki/RS-232#Leitungsl.C3.A4nge_und_.C3.9Cbertragungsrate

Nach 2m ist Ende Gelände.
Aber das scheint ja nicht des TO Problem zu sein.

von Falk B. (falk)


Lesenswert?

@ Daniel V. (danvet)

>>>Bei 115200 darf das Kabel nicht allzu lang sein und auch die
>>>Steckverbindungen sollten was taugen. Ansonsten wird das bei der
>>>Geschwindigkeit (rein hardwaremässig) nichts.

>Ich habe nicht behauptet, dass 115k2 Hz HF sei.

Doch, hast du.

> Natürlich kannst du das
>über einen rostigen Nagel übertragen. Oder über deinen Klingedraht vom
>Keller zum Dach schicken.

Auf einmal? Klang im 1. Beitrag noch ganz anders!

>Die Frage ist, was damit passieren soll.

Ja was wohl? Daten empfangen, wenn's geht fehlerfrei?

> Und wenn das eine RS232 sein
>soll (PC->µC), dann geht das bei 115k2 eben nicht mehr ganz so einfach:
>http://de.wikipedia.org/wiki/RS-232#Leitungsl.C3.A...

>Nach 2m ist Ende Gelände.

Dummes Gelaber. Schon mal real sowas aufgebaut? Zumal der OP einen 
USB-TTL Wandler hat, da kann allein das USB-Kabel mal problemlos 5m lang 
sein. Auch TTL schafft mit 115k2 deutlich mehr als 2m. RS232 mit +/-12V 
auch, auch wenn es OFFIZIELL nicht so spezifiziert ist.

von Daniel V. (danvet)


Lesenswert?

Falk Brunner schrieb:

> Dummes Gelaber. Schon mal real sowas aufgebaut? Zumal der OP einen
> USB-TTL Wandler hat, da kann allein das USB-Kabel mal problemlos 5m lang
> sein. Auch TTL schafft mit 115k2 deutlich mehr als 2m. RS232 mit +/-12V
> auch, auch wenn es OFFIZIELL nicht so spezifiziert ist.

Du wirst sicherlich Recht haben.

von Karl H. (kbuchegg)


Lesenswert?

Jetta schrieb:

> Danke für die vielen Antworten, ich denke ich weiß woran es liegt. Es
> ist wirklich das Problem, dass der Empfang von Daten nicht über einen
> Interrupt abgearbeitet wird. Die main macht noch andre Sachen

Dann muss man sich die ansehen. Was sind diese 'anderen Sachen'? Wieviel 
Zeit geht da drauf.

> und die
> Daten, welche in der Zwischenzeit gesendet werden, gehen verloren. Warum
> es dann unsynchron ist weiß ich noch nicht genau (eigentlich müsste ja
> der nächste SendAll Befehl abgewartet werden.
>
> Ich poste trotzdem mal den Code, vielleicht fällt einem ja noch was auf
> ...

Multiplexing ist, soweit ich das sehen kann, in Ordnung.

> Das Dekativieren sollte man wohl mal in eine Konstante schreiben,
> eventuell erkennt das der Compiler aber auch ....

Kann man machen. Das ist aber nicht dein Zeitproblem. Dein µC wird ja 
nicht mit ein paar kHz getaktet sein.

>         swap_memory_pointer();

Du betreibst double Buffering?

Das kann natürlich je nach Anforderung sinnvoll sein. Wenn aber der PC 
sowieso immer ein komplettes Bild schickt, könnte man auch mal in die 
Richtung überlegen, ob man das überhaupt braucht. Kein Mensch kann das 
sehen, wenn in einem Bild für ein paar µs die Pixel im oberen Teil nicht 
mit den Pixel vom unteren Teil zum selben Bild gehören. Ist ja beim 
Fernsehen auch nicht anders. Da ist ein Bild auch immer eine prozentual 
wechselnde Mischung aus 2 Bildern.


Es wird schon so sein, wie du das vermutest: Dein 'restlicher' Teil in 
der Hauptschleife braucht zu lange. Daher bist du mit dem Polling der 
UART zu langsam und verpasst ein paar Bytes. Irgendwo weiter oben hat 
mal wer gepostet, dass dein µC eine eingebaute FIFO hat, die man nur 
aktivieren braucht. Hast du das gemacht?

von Falk B. (falk)


Lesenswert?

@ Karl Heinz (kbuchegg) (Moderator)

>Du betreibst double Buffering?

>Das kann natürlich je nach Anforderung sinnvoll sein. Wenn aber der PC
>sowieso immer ein komplettes Bild schickt, könnte man auch mal in die
>Richtung überlegen, ob man das überhaupt braucht. Kein Mensch kann das
>sehen, wenn in einem Bild für ein paar µs die Pixel im oberen Teil nicht
>mit den Pixel vom unteren Teil zum selben Bild gehören.

Das würde ich nicht so einfach sagen, gerade bei schnelleren 
Bildwechseln (aka Animation) kommte dann ggf. zu komischen 
Interferenzen. Ein sauberes Double Buffering ist da nicht verkehr und 
bringt keine Nachteile, vom doppelten Speicherbedarf mal abgesehen.

> Ist ja beim
>Fernsehen auch nicht anders. Da ist ein Bild auch immer eine prozentual
>wechselnde Mischung aus 2 Bildern.

Das "alte" Fernsehen hat auch ausreichend geflimmert ;-)

>s wird schon so sein, wie du das vermutest: Dein 'restlicher' Teil in
>der Hauptschleife braucht zu lange. Daher bist du mit dem Polling der
>UART zu langsam und verpasst ein paar Bytes.

Aus den Codefragmenten wird doch keiner schlau!

von Max D. (max_d)


Lesenswert?

Ich denk mal du wirst keine Zertifizierung deines Projektes anstreben 
(Manche Certs. wollen ein deterministisches Proggi, Ints machen das 
schwer/unmöglich), dann gibt es keinen Grund nicht jeden Interrupt zu 
benutzen.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Multiplexing ist, soweit ich das sehen kann, in Ordnung.

Ich würd da gerne ein bischen zurückrudern.
Die Funktion video_controller wird doch aus einem Timer-Interrupt heraus 
aufgerufen. Oder?
Wenn nicht, dann ist das nicht in Ordnung.


@Falk
>> s wird schon so sein, wie du das vermutest: Dein 'restlicher' Teil in
>> der Hauptschleife braucht zu lange. Daher bist du mit dem Polling der
>> UART zu langsam und verpasst ein paar Bytes.
>
> Aus den Codefragmenten wird doch keiner schlau!

Da hast du grundsätzlich recht. Aus den Codefetzen kann man höchstens 
schliessen, dass das Problem wahrscheinlich nicht da drinnen zu finden 
ist. Drum hab ich mich auch recht unverbindlich ausgedrückt.


Das einzige, wozu ich mich hinreissen lassen würde, ist das hier
1
      if (received_data == SEND_ALL)
2
      {
3
        // Empfange Datenblöcke
4
        // zuerst wird ROW0 COL0 - COL6 übertragen (7 Bit) // Rest muss Null sein
5
        // dann ROW0 COL7 - COL13           (7 Bit) // Rest muss Null sein
6
        // dann ROW0 COL14 - COL18           (5 Bit) // Rest muss Null sein
7
        clear_memory();
8
        uint32_t row_buffer = 0;
9
        uint8_t ii = 0;
10
        //write_row
11
        for (ii = 0; ii < 7; ii++)
12
        {
13
          row_buffer = 0;
14
          // Empfange erstes Datenpaket
15
          row_buffer |= uart_get_char_block() << 12;
16
          row_buffer |= uart_get_char_block() << 5;
17
          row_buffer |= uart_get_char_block() << 0;
18
          write_row(ii, row_buffer);
19
        }
20
21
        swap_memory_pointer();
22
      }

das sieht ein wenig seltsam aus. Wenn da Double Buffering am Werk ist, 
wozu dann noch mal eine UMkopieraktion von einem (offenbar) UART-Buffer 
in den 'Video-Ram'. Man kann doch auch gleich die Bytes von der UART 
direkt in den Video Ram schieben, durch das Double BUffering sieht man 
das ja nicht.
(Immer unter der Voraussetzung, das ich den Rest des Systemaufbaus so 
ungefähr richtig erraten habe)

von was zum lachen (Gast)


Lesenswert?

Hallo Falk,

Danke für die vielen Antworten. Lerne gerne etwas hinzu.

Falk Brunner schrieb:
> Aus den Codefragmenten wird doch keiner schlau!

Ist aber fast alles was relevant ist. Ich habe in die Main jetzt extra 
eine kleine Verzögerung eingebaut, sonst ist da nur der UART quatsch 
drin. Ich will nicht davon ausgehen, dass die immer leerbleibt.

Zur Erklärung:
Das UART Polling ist der relevante Teil der main.
Der video controller wird per timer interrupt regelmäßig aufgerufen.
Der doppelte Speicher macht Sinn, da Fragmente sichtbar waren 
besonderst, wenn der komplette Speicher geleert wurde.
Der Rest sind andere Spielreien, welche deaktviert sind (RTC, DCF, 
Tetris...)
clear_memory löscht den speicher
write_row schreibte eine Zeile in den Schreibspeicher
swap_memory tauscht Schreib und lesespeicher durch Pointertausch.

Ich dachte so wäre es übersichtlicher.

von was zum lachen (Gast)


Lesenswert?

Hallo Karl Heinz

Karl Heinz schrieb:
> Dann muss man sich die ansehen. Was sind diese 'anderen Sachen'? Wieviel
> Zeit geht da drauf.
>

Im Moment eine Warteschleife. Ich mache es jedoch jetzt lieber mit 
Interrupt, soll ja auch in Zukunft noch funktionieren.

>>         swap_memory_pointer();
>
> Du betreibst double Buffering?

Meiner Meinung nach Sinnvoll. Wird für andere Betriebsmodi gebraucht....
Siehe oben.


Karl Heinz schrieb:
> Ich würd da gerne ein bischen zurückrudern.
> Die Funktion video_controller wird doch aus einem Timer-Interrupt heraus
> aufgerufen. Oder?
> Wenn nicht, dann ist das nicht in Ordnung.

Das würde mich dann besonders Interessieren. Was ist dann nicht in 
Ordnung? Ich finde das per Timerinterrupt am saubersten. Immerhin ist 
dies die wichtigste Aufgabe, möchte schon die Specs der LEDs einhalten, 
sonst Rauch. Die sind eh am Limit.



Da hätte ich gleich noch eine Frage. Wie könnte man das Hardwareseitig 
absichern, das bei Ausfall des Multiplexbetriebs Rauch aufsteigt. Würde 
mich schon ärgern :-) Habe schon an flinke Minisicherungen gedacht, die 
knapp am Multiplexstrom ausgelegt sind. Dann würde das die LEDs schon 
wenn alle an sind schützen. Bin aber noch nicht so davon überzeugt :-)
Wenn ich z.B. dern Programmer anschließe, schaltet der gerne mal alle 
Ausgänge auf High, bevor es los geht. Genauso ist es wenn ich den 
Debuggerstarte und er wartet bis ich den Code ablaufen lasse. Im Moment 
habe ich noch 2 Watt Widerstände in jeder Zeile, die habe ich auch schon 
öfters gebraucht.

von was zum lachen (Gast)


Lesenswert?

Karl Heinz schrieb:
> das sieht ein wenig seltsam aus. Wenn da Double Buffering am Werk ist,
> wozu dann noch mal eine UMkopieraktion von einem (offenbar) UART-Buffer
> in den 'Video-Ram'. Man kann doch auch gleich die Bytes von der UART
> direkt in den Video Ram schieben, durch das Double BUffering sieht man
> das ja nicht.

Ja das kann man machen. Der Videobuffer ist aber nicht global. Und ich 
hatte schon eine Funktion, welche eine ganze Zeile schreibt. Deswegen 
habe ich die genommen und eine Zeile, d.h. eine 32bit Variable wird 
jetzt doppelt gebuffert. Finde noch vertretbar, kann ich aber mal durch 
eine neue Funktion austauschen...

von Falk B. (falk)


Lesenswert?

@ was zum lachen (Gast)

>> Aus den Codefragmenten wird doch keiner schlau!

>Ist aber fast alles was relevant ist.

Oft wiederholter Irrtum. Poste vollständige Quelldateien als Anhang.

>Ich dachte so wäre es übersichtlicher.

Siehe oben.

von Falk B. (falk)


Lesenswert?

@ was zum lachen (Gast)

>absichern, das bei Ausfall des Multiplexbetriebs Rauch aufsteigt. Würde
>mich schon ärgern :-)

Duch einen Hardware-Watchdog in Form eines Monoflops, welche nach 
nur wenig mehr als einer Multiplexzeit die Treiber abschaltet, wenn es 
nicht per CPU aktiv neu getriggert wird.

>Habe schon an flinke Minisicherungen gedacht, die
>knapp am Multiplexstrom ausgelegt sind.

Vergiss es, die LEDs werden schneller geschädigt als dein Sicherung 
reagieren kann.

>Wenn ich z.B. dern Programmer anschließe, schaltet der gerne mal alle
>Ausgänge auf High, bevor es los geht.

Nö, er schalltet sie auf Eingang. Damit dein Treiber nicht wild 
schalten, braucht man passende Pull down Widerstände.

>habe ich noch 2 Watt Widerstände in jeder Zeile, die habe ich auch schon
>öfters gebraucht.

Für die Entwicklung sinnvoll. Siehe

http://www.mikrocontroller.net/articles/LED-Matrix#Ansteuerung

von was zum lachen (Gast)


Lesenswert?

Falk Brunner schrieb:
> Oft wiederholter Irrtum. Poste vollständige Quelldateien als Anhang.

Alles klar. Ist ja gut ;-)
Wenn ich mal Zeit habe werde ich den Interrupt einfügen und dann noch 
mal komplett posten.

Falk Brunner schrieb:
> Duch einen Hardware-Watchdog in Form eines Monoflops, welche nach
> nur wenig mehr als einer Multiplexzeit die Treiber abschaltet, wenn es
> nicht per CPU aktiv neu getriggert wird.

Das ist ja ne geile Idee. Da wäre ich nicht drauf gekommen. Mal sehn ob 
ich so einen Kollege in der Bastelkiste finde. Wollte eh noch einen 
Mosfet als Verpolschutz spendieren, viell. kann man das kombinieren, 
dass das Monoflop gleich alles ausschaltet.

Falk Brunner schrieb:
> Nö, er schalltet sie auf Eingang. Damit dein Treiber nicht wild
> schalten, braucht man passende Pull down Widerstände.

Wild zwar nicht, aber die sind immer an. Das habe ich nicht bedacht, 
obwohl mir das schonmal passiert ist. Ich dachte bei einem FPGA reichen 
die internen Pulldowns, bis mir meine Halbbrücke entgegenkam.

Vielen Dank Falk!

Jetzt will nur noch wissen was an meiner Routine so schlecht sein soll 
;-)
Karl Heinz wo bist du ? :-D

von Falk B. (falk)


Lesenswert?

@ was zum lachen (Gast)

>Wenn ich mal Zeit habe werde ich den Interrupt einfügen und dann noch
>mal komplett posten.

Nein, poste den aktuellen Stand, auch wenn er Fehler hat.

>Jetzt will nur noch wissen was an meiner Routine so schlecht sein soll

Genau DARUM sollst du das tun, damit du was lernen kannst.

von Jetta (Gast)


Lesenswert?

Hallo Falk,

Danke für deine Antwort. Kann schon sein, das der Fehler dort steckt, wo 
man ihn nicht vermutet. Und wahrscheinlich hast du Recht das es Sinn 
macht ein Minimalbeispiel zu Posten. Bin jetzt erstmal glücklich und 
eventuell schlauer, werden den Code aber gegen Ende der Woche mal posten 
(wenn ich wieder zu Hause bin).

Vielen Dank für deine Tips!

was zum lachen schrieb:
> Jetzt will nur noch wissen was an meiner Routine so schlecht sein soll
> ;-)
> Karl Heinz wo bist du ? :-D

Karl Heinz schrieb:
> Ich würd da gerne ein bischen zurückrudern.
> Die Funktion video_controller wird doch aus einem Timer-Interrupt heraus
> aufgerufen. Oder?
> Wenn nicht, dann ist das nicht in Ordnung.

Das habe ich leider falsch verstanden. Wer lesen kann ich klar im 
Vorteil, aber für eine doppelte Negierung hat mein Hirnprozi nicht 
gereicht.
-> Wird mit 1kHz aus Timerinterrupt aufgerufen, also in Ordnung (in der 
main steht die Fkt. nicht).

Danke auch dir!

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.