Hallo zusammen,
an meinem Arduino (Mega 2560) möchte ich den TLC5940 betreiben, um ein
paar zusätzliche PWM-Ausgänge zu haben.
Soweit ich das verstanden habe, läuft das ganze so ab:
* Dot Correction (DC) Register befüllen
* Greyscale (GS) Register befüllen
* Dann die ganze Zeit durch pulsen
Das DC habe ich befüllt. Anscheinend auch korrekt, denn wenn ich über
SOUT die eingetakteten Daten einlesen, dann bekomme ich die korrekten
Werte raus.
Aber leider bekomme ich aus dem Ausgang OUT0 für meine LED kein Signal.
Die Taktung über den GSCLK und auch die Steuerung des BLANK scheinen
aber zu funktionieren (zumindest sehe ich auf dem Oszilloskop, dass dort
was ankommt). Leider kann ich im Gegensatz zu dem DC nicht die
eingetakteten Werte auslesen um zu sehen, ob alles richtig übernommen
wurde.
Ich kann mir eigentlich nur vorstellen, dass ich doch irgendwo im Code
einen Fehler drin habe, finde ihn aber nicht.
Hier mal der Code für die DC. Der ist aber vermutlich in Ordnung.
Hinweis: "Say" sind Debug-Meldungen (einfach ignorieren) und hinter "c"
verbergen sich die jeweils 6 bits pro Kanal.
1 | void setDC() {
|
2 | // set SCLK to low
|
3 | sclkL();
|
4 | // set XLAT to low
|
5 | digitalWrite(xlatPin, LOW);
|
6 | say("xlatPin LOW");
|
7 | // DCPRG is HIGH
|
8 | // set VPRG to VCC
|
9 | digitalWrite(vprgPin, HIGH);
|
10 | say("vprgPin HIGH");
|
11 | // Dot Correction Data Input Mode selected
|
12 | // Target is DC Register, since CDPRG is HIGH
|
13 | // send 96 bits of data
|
14 | for (int r=0; r<numberOfChannels; r++) {
|
15 | say("Channel " + r + " selected");
|
16 | for (int c=2; c<=7; c++) {
|
17 | // set SIN Pin
|
18 | // Serial.println("c=" + String(c) + String(": ") + String(channelValues[r][c]));
|
19 | say("sending value " + channelValues[r][c]);
|
20 | digitalWrite(sinPin, channelValues[r][c]);
|
21 | // clock
|
22 | say("old value: " + digitalRead(soutPin));
|
23 | sclkHL();
|
24 | }
|
25 | }
|
26 | // Shift Data into the register by setting XLAT to HIGH
|
27 | digitalWrite(xlatPin, HIGH);
|
28 | say("xlatPin HIGH");
|
29 | // SCLK and SIN must not be changed while XLAT is HIGH!
|
30 | digitalWrite(xlatPin, LOW);
|
31 | say("xlatPin LOW");
|
32 | //say("DC übertragen");
|
33 | }
|
Und hier dann noch die GS Routine. Hinter "c" stehen die 12 bit für den
GS.
1 | void setGS() {
|
2 | // DCPRG is HIGH
|
3 | // set VPRG to GND
|
4 | digitalWrite(vprgPin, LOW);
|
5 | // Greyscale PWM Mode selected
|
6 | // Target is DC Register, since CDPRG is HIGH
|
7 | // set SCLK to low
|
8 | sclkL();
|
9 | // set XLAT to low
|
10 | digitalWrite(xlatPin, LOW);
|
11 | // send 192 bits of data
|
12 | // r = channel
|
13 | for (int r=0; r<numberOfChannels; r++) {
|
14 | // c = bit value
|
15 | for (int c=9; c<=20; c++) {
|
16 | // set SIN Pin
|
17 | digitalWrite(sinPin, channelValues[r][c]);
|
18 | // SCLK high, low
|
19 | sclkHL();
|
20 | }
|
21 | }
|
22 | digitalWrite(blankPin, HIGH);
|
23 | // Shift Data into the register by setting XLAT to HIGH
|
24 | digitalWrite(xlatPin, HIGH);
|
25 | digitalWrite(xlatPin, LOW);
|
26 | if (gsFirstrun) {
|
27 | // Manual: "The first GS data input cycle after dot correction requires an additional SCLK
|
28 | // pulse after the XLAT signal to complete the grayscale update cycle."
|
29 | // SCLK high, low
|
30 | sclkHL();
|
31 | gsFirstrun = false;
|
32 |
|
33 | }
|
34 | say("GS written");
|
35 | }
|
Wenn ich dann beide einmal aufgerufen habe, dann lasse ich in der loop()
ständig diese Routine hier aufrufen:
1 | void clockGSCLK() {
|
2 | // set GSCLK = low (default)
|
3 | gsclkL();
|
4 | // Start the Cycle by setting blankPin high > low
|
5 | digitalWrite(blankPin, HIGH);
|
6 | digitalWrite(blankPin, LOW);
|
7 | // Clock...
|
8 | for (int i=1; i<=4096; i++) {
|
9 | gsclkHL();
|
10 | }
|
11 | //say("clockGSCLK durchlaufen");
|
12 | }
|
Ich habe den Code etwas ausführlichen kommentiert, damit er einfacher zu
verstehen ist.
Soweit ich das verstanden habe, muss ich setDC() sowie sowie setGS() ja
nur ein einziges Mal aufrufen, wenn ich die Werte nicht ändern will. Nur
die clockGSCLK() muss ja ständig aufgerufen werden, korrekt?
Die komplette Beschreibung des Treibers ist hier:
https://www.mikrocontroller.net/attachment/454200/TLC5940.pdf
Hat jemand eine Idee, warum ich am OUT0 nichts bekomme?