Forum: Mikrocontroller und Digitale Elektronik TLC5940 am ATmega16


von Michi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich versuche einen TLC5940 (LED-Treiber) an einem ATmega16 zu betreiben. 
Die Verdrahtung habe ich auf einem Steckbrett wie im Schaltplan 
angegeben vorgenommen.
Den Quellcode habe ich größtenteils von Demystifying the TLC5940 
(https://sites.google.com/site/artcfox/demystifying-the-tlc5940) 
übernommen. Dort wird ein ATmega328P verwendet, so dass ich folgende 
Anpassungen gemacht habe:
Für den Grundtakt des TLC wurde beim ATmega328P der CLKO-Pin verwendet, 
an dem der Prozessortakt abgegriffen werden kann. Der ATmega16 hat so 
einen Pin nicht, so dass ich stattdessen mittels eines als 
CTC-konfigurierten Timers mit Prescale 1 und dem Schwellwert 0 (ORC0 = 
0) am Pin OC0 (PB3) den halben Prozessortakt ausgegeben habe.
Alle 4096-TLC-Takte muss der TLC-Blank-Pin kurz auf HIGH gezogen werden, 
wozu ich den Timer2 ebenfalls im CTC-Modus verwendet habe. Dieser hat 
einen Prescaler von 1024 und einen Schwellwert von 7 (OCR2 = 7) -> alle 
8196 Prozessortakte = alle 4096 PB3-Takte.

Leider bleiben alle angeschlossenen LEDs aus. Lediglich wenn ich den 
Prozessor mit dem MKII über JTAG programmiere, leuchten die LEDs für ca. 
eine halbe Sekunde bevor sie dann wieder komplett ausgehen.
Wenn ich den Teil mit der DotCorrection auskommentire, dann sind einige 
LEDs ebenfalls an (die gleichen, die zuvor für eine halbe Sekunde an 
waren), aber egal welche Werte ich dem TLC übergebe, welche und wie 
stark die LEDs leuchten kann ich nicht beeinflussen. Hier mal die 
Funktionen, die die DotCorrection und die GrayScale-Werte setzen:
1
void TLC5940_ClockInDC(void) {
2
  setHigh(DCPRG_PORT, DCPRG_PIN);
3
  setHigh(VPRG_PORT, VPRG_PIN);
4
  for (dcData_t i = 0; i < dcDataSize; i++) {
5
    // Start transmission
6
    SPDR = dcData[i];
7
    // Wait for transmission complete
8
    while (!(SPSR & (1 << SPIF)));
9
    //pulse(SCLK_PORT, SCLK_PIN); // <-------- notwendig?
10
  }
11
  pulse(XLAT_PORT, XLAT_PIN);
12
}
13
14
ISR(TIMER2_COMP_vect) {
15
  static uint8_t xlatNeedsPulse = 0;
16
  setHigh(BLANK_PORT, BLANK_PIN);
17
  if (outputState(VPRG_PORT, VPRG_PIN)) {
18
    setLow(VPRG_PORT, VPRG_PIN);
19
    if (xlatNeedsPulse) {
20
      pulse(XLAT_PORT, XLAT_PIN);
21
      xlatNeedsPulse = 0;
22
    }
23
    pulse(SCLK_PORT, SCLK_PIN);
24
  } else if (xlatNeedsPulse) {
25
    pulse(XLAT_PORT, XLAT_PIN);
26
    xlatNeedsPulse = 0;
27
  }
28
  setLow(BLANK_PORT, BLANK_PIN);
29
  // Below this we have 4096 cycles to shift in the data for the next cycle
30
  for (gsData_t i = 0; i < gsDataSize; i++) {
31
    SPDR = gsData[i];
32
    while (!(SPSR & (1 << SPIF)));
33
    //pulse(SCLK_PORT, SCLK_PIN); // <-------- notwendig?
34
  }
35
  xlatNeedsPulse = 1;
36
}

Hat jmd von euch einen Idee, was ich falsch mache? Ein Oszilloskop habe 
ich leider nicht um die Signale oder deren Timing zu überwachen.

Gruß
Michi

von Frank L. (frank_l)


Lesenswert?

Hallo Michi,

schau Dir mal meinen Code von vor paar Jahren an.

Beitrag "Moodlight mit ATMEGA88 und TLC5940 mit 4096 Farben"

ist mit Sicherheit nicht die beste IMplementierung, läuft aber 
einwandfrei.

Gruß
Frank

von Michi (Gast)


Lesenswert?

Hallo Frank,

danke für deine Antwort.
Mein Fehler war, dass ich bei der Initialisierung von GSCKL 
versehentlich
1
setOutput(GSCLK_PORT, GSCLK_PIN);
statt
1
setOutput(GSCLK_DDR, GSCLK_PIN);

gesetzt habe und dass ich (wahrscheinlich durch eine Fehlkonfiguration) 
den Baustein so überhitzt habe, dass er nicht mehr richtig funktioniert 
hat. Nachdem ich ihn ausgetauscht hab, funktioniert jetzt alles 
einwandfrei.

Gruß
Michi

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.