Forum: Mikrocontroller und Digitale Elektronik TLC5940 LED Driver liefert keinen Output


von Sebastian E. (sebert)


Lesenswert?

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?

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.