Forum: Mikrocontroller und Digitale Elektronik TLC5916 dimmen


von Newbie (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich versuche (mittlerweile schon) verzweifelt, 2x TLC5916 (das sind 
Schieberegister mit Konstantstromsenken ) in "Special Mode" zu 
versetzen, um den Strom an den Ausgängen einzustellen. Die beiden sind 
nacheinander an den USART0 eines ATmega1284P angeschlossen und der wird 
im Master SPI Modus betrieben. Das An- und Ausschalten der LEDs geht, 
also müssten die ICs noch funktionstüchtig sein. Zum versetzen in 
"Special Mode" muss anscheinend SPI bzw. USART abgeschaltet werden und 
die Ansteuerung "manuell" erfolgen. Das macht bei mir die Funktion void 
tlc5916_mode_switch(uint8_t newmode). Um dann den "Configuration Code" 
in die Register zu schieben, kann die USART hardware wieder 
eingeschaltet werden (basierend auf dieser Quelle 
http://softsolder.com/2009/12/22/), ich habe es zuerst gemacht und es 
hat nicht funktioniert (die reingeschobenen Daten wurden wohl als Werte 
für die Ausgangspins übernommen und nicht als Werte für den Strom -> die 
LEDs haben im Testprogramm geblinkt), dann habe ich die Stromwerte auch 
"manuell" reingeschoben und es funktioniert auch nicht... :-(
Hat jemand schon Erfahrungen mit diesen Chips oder vielleicht sogar den 
Code für die Ansteuerung? Würde mich sehr freuen, weil ich sonst bei 
google außer der oben genannten Quelle kaum was zu dem Problem finden 
konnte.
Im Anhang mein nicht funktionierender C-Code :-)

MfG Newbie

von Newbie (Gast)


Lesenswert?


von Martin (Gast)


Lesenswert?

Newbie schrieb:
> Im Anhang mein nicht funktionierender C-Code :-)

Funktioniert dein Code nicht, oder wird er nicht compiliert?
Bei mir kommt als erstes eine Compilerwarnung, weil usart_mspim_init 
nicht in der usart.h auftaucht.

von Newbie (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, Martin, tut mir leid, habe wohl die Warnungen übersehen... hier 
ist die korrigierte Version mit Makefile dazu. Der Code funktioniert 
aber trotzdem nicht :-( Die angeschlossenen LEDs müssten eigentlich im 
Sekundentakt abwechselnd dunkler und heller werden. Bei mir leuchten sie 
immer mit voller Stärke :-(

von Frank Link (Gast)


Lesenswert?

Hallo,
schau Dir mal den Code für die spezielle Initialisierung an.

Der Code an Position 3 und 4 ist identisch. Laut der Seite die Du an 
gehangen hast, müsste LE erst High werden und dann wieder LOW, Du hast 
ihn aber in beiden Fällen auf LOW stehen.

Gruß
Frank

von Frank Link (Gast)


Lesenswert?

Kommando zurück, bin in den falschen Bereich gestolpert...

Gruß
Frank

von Newbie (Gast)


Lesenswert?

LE habe ich nur beim Versetzen in NORMAL MODE in beiden Fällen auf LOW, 
so wie es in der Quelle auch gemacht wird.

Hat denn sonst keiner eine Lösung fürs Problem? Sonst muss ich wohl die 
mit PWM dimmen, was nicht so optimal wäre, weil es nur 1 gemeinsame OE 
Leitung in meiner Schaltung gibt und ich somit nur alle ICs zusammen 
dimmen kann.

von Janos K. (noshky)


Lesenswert?

Hallo,

bei mir ist das ein Weilchen her - aber für die Nacht poste ich dir hier 
mal meinen Code-Schnippsel, der den Modus-Wechsel vollführt.
Auch im Special-Mode kann SPI verwendet werden, nur für den Wechsel muss 
man manuel vorgehen.
Der Code ist für MSP430 gemacht, und ich habe einige viele Makros 
verwendet. Vielleicht hilft er dir ja so schonmal auf die Sprünge - 
ansonsten müssen wir da morgen (abend) nochmal nachhelfen ;-).

Grüße
Janosch
1
/**
2
 * MODE SWITCHING PROCEDURE:
3
 * After !OE goes low for 1 clock cycle, a 1-clock
4
 * wide pulse in clock cycle #4 switches to SPECIAL
5
 * MODE (*). Missing this pulse in clock cycle #4
6
 * switches to NORMAL MODE (**).
7
 * ===============================================
8
 *               #1    #2    #3    #4    #5
9
 *                 --    --    --    --    -- 
10
 * CLK            |  |  |  |  |  |  |  |  |  |
11
 *              --    --    --    --    --    --
12
 * ===============|=====|=====|=====|=====|=======
13
 *              -----       --------------------
14
 * !OE(ED2)       1  |  0  |  1     1     1
15
 *                    -----
16
 * ===============|=====|=====|=====|=====|=======
17
 *                                -----
18
 * LE(ED1) (*)    0     0     0  |  1  |  0
19
 * (->Special)  -----------------       --------
20
 *          
21
 * LE(ED1) (**)   0     0     0     0     0
22
 * (->Normal)   --------------------------------
23
 * ===============|=====|=====|=====|=====|=======
24
 * Phase:         |Actual Mode| Switching | New Mode->
25
 * ===============|=====|=====|=====|=====|=======
26
 * 
27
 * If the driver is operated in SPI mode, then this
28
 * mode has to be exited (left) before mode switching
29
 * can be performed. After mode switching, SPI mode
30
 * has to be re-entered.
31
 */
32
void switchMode(mode_e mode) {
33
  #ifdef SPI_MODE
34
    // Exit SPI mode
35
    CBI(driver_pSEL, driver_SDI + driver_CLK);
36
    SBI(driver_pDIR, driver_SDI + driver_CLK);
37
  #endif  
38
  
39
  hi(driver_nOE);
40
  lo(driver_LE);
41
  hilo(driver_CLK);            // CLK-1
42
  
43
  lo(driver_nOE);
44
  hilo(driver_CLK);            // CLK-2
45
  
46
  hi(driver_nOE);
47
  hilo(driver_CLK);            // CLK-3
48
  
49
  if (mode == MODE_SPECIAL) {
50
    hi(driver_LE);
51
    hilo(driver_CLK);          // CLK-4
52
    lo(driver_LE);
53
    hilo(driver_CLK);          // CLK-5
54
  }
55
  else {
56
    hilo(driver_CLK);          // CLK-4
57
    hilo(driver_CLK);          // CLK-5
58
  }
59
  
60
  #ifdef SPI_MODE
61
    // Switch back to SPI Mode
62
    SBI(driver_pSEL, driver_SDI + driver_CLK);
63
  #endif  
64
}

Edit:
Die Makros sehen so aus:
1
#define hi(pin)         SBI(driver_pOUT, (pin))  // pin: _|^
2
#define lo(pin)         CBI(driver_pOUT, (pin))  // pin: ^|_
3
#define hilo(pin)       hi((pin)); lo((pin))

von Janos K. (noshky)


Lesenswert?

Jetzt habe ich doch nochmal in deinen Code reingeschaut.
Das Betreten des Special-Modes ist zumindest gleich. Beim Verlassen 
ziehst du nach dem 5. SCK-Puls noch OE runter - ich glaube aber nicht, 
dass das das Verlassen des Special-Modes verhindert.

Vielleicht macht deine "current_adjust" Methode nicht was sie soll? 
Sieht mir nach Software-SPI aus, aber wie oben gesagt, spricht nichts 
dagegen, den Konfigurations-Code (8 bit) ebenfalls per SPI zu 
übermitteln.

Hier mal als Vorlage meine Methode:
1
void matrix_driver_config(unsigned char configRed, unsigned char configGreen) {
2
  /**
3
   * TODO: Make sure that the timer/driver has stopped interrupting.
4
   * This method call has to be somehow synchronized with the timer interrupt.
5
   */
6
  bool isDriver_nOE = TBI(driver_pOUT, driver_nOE);    // Remember DRIVER:nOE state
7
  
8
  switchMode(MODE_SPECIAL);
9
  send16(configRed, configGreen);
10
  switchMode(MODE_NORMAL);
11
  
12
  /**
13
   * Restore DRIVER:nOE state
14
   */
15
  if (isDriver_nOE) {
16
    SBI(driver_pOUT, driver_nOE);
17
  }
18
  else {
19
    CBI(driver_pOUT, driver_nOE);
20
  }
21
}
(Ich habe zwei TLCs in Reihe).

Die Konfigurations-Codes erzeuge ich so:
1
/**
2
 * Value between 0 and 63
3
 */
4
#define CONFIG_CODE(value)     (((value) << 2) + 0x03)
(0 war vermutlich kein oder wenig Strom, 63 maximal)

So, vielleicht hilft dir das durch die Nacht - ich muss jetzt aber ins 
Bette.

von Newbie (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, Janosch,
vielen Dank für die Antwort und den Code! Ich habe meine Funktionen 
jetzt komplett überarbeitet und benutze die SPI/USART Hardware zwischen 
dem Moduswechsel. Aber irgendwie kommt es dazu, dass die reingetakteten 
Daten in die OUTputs übernommen werden und nicht in die 
Stromkonfiguration... also blinken die LEDs vom Backlight abwechselnd... 
:-( verstehe nicht, wo da das Problem steckt... habe nochmal die 
USART-Routinen durchgeschaut, die Wartezeit nach dem Deaktivieren des 
Transmitters/Receivers eingefügt (zusätzlich zur while()-Warteschleife, 
die eigtl ausreichen sollte)...

von Janos K. (noshky)


Lesenswert?

Hallo,
vom Ablauf sieht das vollkommen in Ordnung aus - und war es vorher 
bestimmt auch schon.

Bist du denn sicher, dass du die control-Eingabe als Ausgang siehst?
Mich irritiert Zeile 41 in tlc5961.c:
1
void tlc5916_out (uint8_t data, uint8_t device) {
2
/*41*/  static uint8_t out[TLC5916_QTY] = OUT_ARRAY_INIT;
3
  uint8_t i;
4
  out[device] = data;
5
  for (i = 0; i < TLC5916_QTY; i++) {
6
    usart_mspim_transceive (out[i]);
7
  }
8
  LE_HILO
9
}
Dieses Array muss doch raus aus der Methode, da es sonst bei jeder 
Konfiguration neu (leer) angelegt wird. (?)
Lässt sich so das abwechselnde Blinken erklären?
Gruß Janosch

von Newbie (Gast)


Lesenswert?

Hm... wenn ich die arrays global deklariere ändert sich nichts... 
außerdem sind die ja dann auch "statisch" und statisch heißt dabei, dass 
sie nur 1x deklariert werden... oder irre ich mich?

von Newbie (Gast)


Angehängte Dateien:

Lesenswert?

Mich wundert auch irgendwie, dass das manuelle Reintakten bei mir 
überhaupt nicht funktioniert... ich habe jetzt alles in einer Datei 
zusammengefasst und so klein wie möglich gemacht, um den Fehler zu 
finden... aber auch wenn ich den Teil mit Stromanpassung auskommentiere, 
bleiben die LEDs die ganze Zeit dunkel :-( Das brint mich auf den 
Gedanken, dass irgendwas mit dem Timing nicht stimmt... (Der ATmega 
läuft bei mir mit dem internen Oszi mit 8 MHz...) oder es liegt an 
mangelnden C und AVR-Kenntnissen :-(

von Janos K. (noshky)


Angehängte Dateien:

Lesenswert?

Newbie schrieb:
> Hm... wenn ich die arrays global deklariere ändert sich nichts...
> außerdem sind die ja dann auch "statisch" und statisch heißt dabei, dass
> sie nur 1x deklariert werden... oder irre ich mich?

Nein völlig richtig - Test bestanden :-p, an mangelnden C-Kenntnissen 
liegt's wohl nicht.

Also dein Code sieht absolut in Ordnung aus. Irritieren tun mich 
lediglich noch die Delays - wozu sind die?. Mein MSP läuft mit 8 oder 16 
MHz und vollem SPI speed (keine Ahnung was das ist), und ich brauche 
mich um Timings nicht zu scheren.

Ich kann leider nicht aktiv mit debuggen, weil mein wilder Aufbau mit 
100 Kabeln hier auf dem Schreibtisch unter einer Staubdecke verschwunden 
ist, d.h. ich traue mich zurzeit nicht ihm auch nur ein Kabel zu krümen 
:-(.

Doch wie sieht es denn jetzt aus:
1. Der TLC schaltet den Output im Hardware-SPI Betrieb
   -> Aber der Config-Code wird an den Ausgang gelegt
   -> Auch wenn zur Übertragung des Config-Codes Soft-SPI verwendet 
wird?
2. Der TLC macht gar nichts im Soft-SPI Betrieb?
   -> Richtig?

Wenn 2. korrekt ist, dann ist sollte der Fehler dort gesucht werden. 
Denn um zwischen den Modes zu wechseln, muss "soft" getaktet werden, und 
wenn das nicht funktioniert, kann auch nichts weiter gehen.
Also: Soft-SPI muss gehen, würde ich mal fast sagen. (Deine Soft-SPI 
Routine sieht auch völlig ok aus).

Ansonsten:
Kann es am Schaltplan liegen? Welchen Widerstand hast du an R-Ext? Ich 
hänge mal ein Bild von meiner Schaltung an.

Nicht aufgeben, der TLC5916 ist ein starkes Bauteil! :-)

von Newbie (Gast)


Angehängte Dateien:

Lesenswert?

Also ich habe es jetzt irgendwie hinbekommen :-) Ich habe meine softSPI 
Routine nochmal überarbeitet und nun läuft es! Das mit dem USART Master 
SPI Modus funktioniert aber immer noch nicht, ich will mich auch nicht 
weiter damit auseinandersetzen, weil Software SPI für mich schon schnell 
genug ist. Vielen Dank nochmal, Janosch, für deine Hilfe! Ich hänge mal 
den (endlich) funktionierenden Code an, vielleicht kann es ja jemand 
gebrauchen ;)
MfG Newbie

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.