Morgen,
ich habe ein IC von TI TLC5941 (16xLED Dimmen per PWM 12Bit)
Controller AtMega48-20PU ... der LED Treiber will 196 Bit Daten für die
PWM (12 Bit pro LED).
nach dem man dem IC alle 196 Bit geschickt hat brauch man ein PWM Ref
CLK...das IC Zählt die Clocks und sobald der Wert für den jeweiligen
Kanal erreicht ist schaltet er sie ein.
nach 4096 clocks jedoch brauche ich ein blank Signal um den Zähler
zurück zusetzen... logisch und eigentlich auch kein Problem...oder?
...also aus meinem Standpunkt schon....
am liebsten würde ich denn Ref. CLK über ein PWM out erzeugen da ich den
nur einmal setzen muss und mich das keine Prozessorzeit kostet.... nur
brauch ich im Endeffekt ein Interrupt nach 4096 Clocks um dann die PWM
abzuschalten den Black zuschicken und wieder anzufangen.
meine Überlegung war:
wenn ich ne 100Hz PWM will muss ich 100 mal neu Anfangen d.h. 4069
Clocks mal 100 => 4096 KHZ die ich als Ref CLK brauche eigentlich etwas
mehr da ich zwischendrin immer noch den blank brauche ... sagen wir
0,5MHz ist eine runde Sache ....
kann ich irgendwie auswerten wann 4096 Clocks aus einem PWM Ausgang
rausgekommen sind?
ohne gleich 50% Cpu time zu verlieren?
oder hat da einer eine bessere Idee (das ist meine Hoffnung^^)
mfg Nova
@ Nova (Gast)
>CLK...das IC Zählt die Clocks und sobald der Wert für den jeweiligen>Kanal erreicht ist schaltet er sie ein.
Eher aus.
>am liebsten würde ich denn Ref. CLK über ein PWM out erzeugen da ich den>nur einmal setzen muss und mich das keine Prozessorzeit kostet.... nur
Genau.
>brauch ich im Endeffekt ein Interrupt nach 4096 Clocks um dann die PWM>abzuschalten den Black zuschicken und wieder anzufangen.>wenn ich ne 100Hz PWM will muss ich 100 mal neu Anfangen d.h. 4069>Clocks mal 100 => 4096 KHZ die ich als Ref CLK brauche eigentlich etwas
nein, eher 100 Hz * 4096, macht 409,6 kHz.
>kann ich irgendwie auswerten wann 4096 Clocks aus einem PWM Ausgang>rausgekommen sind?>ohne gleich 50% Cpu time zu verlieren?
Man braucht hier zwei Timer. Einer macht den Takt von 400 kHz, der
andere die 100 Hz.
MFG
Falk
du meinst also ich lasse die einfach immer laufen .... naja die idee ist
nicht dumm... das SPI interface ist getrennt d.h. auch wenn die pwm
gerade läuft kann ich daten nachschieben.
der Blank muss aber ein kurzer strob sein ... das würde ich über ein
compare machen ... den pin kurz toggeln (12ns reichen) joar... is ne
gute idee ...
kostet mich 1 8-bit timmer + OCA pin und 1 16-bit timmer naja nicht
schön aber was besseres ist mir auch nicht eingefallen^^
danke aufjedenfall erstmal
@ Nova (Gast)
>der Blank muss aber ein kurzer strob sein ... das würde ich über ein>compare machen ... den pin kurz toggeln (12ns reichen) joar... is ne>gute idee ...
Nöö, vollkommen unsinnig. Den Strobe machst du schlicht per Software,
nachdem du neue Daten geladen hast.
>kostet mich 1 8-bit timmer + OCA pin und 1 16-bit timmer naja nicht>schön aber was besseres ist mir auch nicht eingefallen^^
Wird hier auch nicht besser.
MFG
Falk
ich meine nicht den Strob sondern den blank... den Strob braucht man
natürlich für das SPI Interface aber nicht für den PWM Cycle
soweit ich das im Datenblatt richtig verstanden habe wird mit dem gclk,
der mit dem PWM Pin erzeugt wird, der interne Counter hochgezählt mit
dem an verglichen wird, um den Counter wieder auf 0 zusetzen brauche
ich ein blank da er das nicht von alleine macht.
d.h. für jeden PWM Durchgang brauche ich 4096 GCLK’Ss dann ein Blank und
dann wieder 4096 GCLK’s und dann ein Blank ... und so weiter ...
bei 100 Hz PWM brauch ich auch 100 Blanks egal ob ich was an den Dimm
werten der einzelnen Kanäle änder oder nicht ... wenn ich das richtig
verstanden habe ist das SPI Interface unabhängig von der eigentlichen
PWM Erzeugung ...
So also die Timmer sind am laufen...420KHz und 100,2Hz passt ganz gut
aber
hat einer ne Idee wie ich 16 x 5bit in 8 bit Packete verpacke?
meine Idee ist:
1
uint8_t byte_count = 0;
2
uint8_t dot_count = 0;
3
int8_t frei = 8;
4
uint8_t send_byte = 0;
5
6
while ( dot_count <= 15)
7
{
8
send_byte |= dot_array[dot_count]>>frei;
9
10
byte_count++;
11
dot_count++;
12
frei = byte_count*8 - dot_count*5;
13
14
while (frei > 0)
15
{
16
send_byte |= dot_array[dot_count] << (8 - frei);
17
frei = byte_count*8 - (dot_count+1)*5;
18
if (frei >= 0) dot_count++;
19
else frei = frei * -1;
20
}
21
22
SPI_SEND(send_byte);
23
send_byte = 0;
24
}
kann das so gehen? oder hat da mal wieder wer ne bessere idee^^
gruß Sascha
@ Nova (Gast)
>hat einer ne Idee wie ich 16 x 5bit in 8 bit Packete verpacke?
Wieso 16x5? Das Ding hat 6 Bit/Punkt. Ist aber auch etwas doof, weil
eben nicht 8 :-0
>kann das so gehen? oder hat da mal wieder wer ne bessere idee^^
Ohne das Programm jetzt im Detail geprüft zu haben würde ich sagen dass
es zwar prinzipiell läuft, auf dem AVR aber relativ viel Zeit braucht.
Keine Ahung wieviel, aber Bitschieben mit variabler Stellenzahl kostet
viel Zeit.
Besser ist es, feste Bitmasken zu verwenden. etwa so.
Das sollte recht flott laufen, weil nur eine feste Maske geschoben wird,
das dauert jeweils 1 Takt ;-)
>Nova (Gast)>gruß Sascha
Soviel zum Thema Geschlechterzuordnung von Nicknames im Internet . . .
;-)
Mfg
Falk
Ich habe das mal so gelöst, indem ich GSCLK und die Daten-Clock beide an
die SPI-Clock gehängt habe. Dann einen Zustandsautomaten in den
SPI-Interrupt, der sich um den Datenversand (erst Dummydaten, am Ende
richtige Daten + Blank/Strobe) kümmert. Damit läuft die ganze
Ansteuerung eines TLC5940 nebenher ab und man braucht sich nicht weiter
drum kümmern.
Geht allerdings nur, wenn man die SPI-Schnittstelle nicht noch für was
anderes braucht.
joar äää^^
naja and der spi hängt noch ein FRAM ein FLASH eine SD karte ein RFM12
eine RTC und porterwieterung + Front Board ^^
den SPI ist im dauer Stress ;-)
meine lösung sieht jetzt mal so aus:
1
while ( dot_count <= 15)
2
{
3
send_byte |= dot_array[dot_count]>>frei;
4
PORTA = send_byte;
5
byte_count++;
6
dot_count++;
7
frei = byte_count*8 - dot_count*5;
8
9
while (frei > 0)
10
{
11
send_byte |= dot_array[dot_count] << (8 - frei);
12
PORTA = send_byte;
13
frei = byte_count*8 - (dot_count+1)*5;
14
if (frei >= 0) dot_count++;
15
}
16
17
if (frei < 0) frei = 5 - (frei * -1);
18
SPI_Transfer(send_byte);
19
send_byte = 0;
20
}
die Variante von Falk habe ich wenn ich erlichbin bei ersten
drübergucken nicht verstanden ... muss mir das mal im Simulator angucken
...
aber nur vom einwürf im endeffect brach ich ein bitstrom von 96bit nur
für die Stromeinstellung.
aber danke schon mal^^
das besste ist amanfang hatte ich keine Idde und bei ab tippen von dem
code vom Schmirpapier ins Forum habe ich schon 3 Fehler gefunden...
edit:
also laut AVR Studio kommt da kein einziges Bit in der SPI rutine an ...
hattes du das schon mal getestet oder frei schnautze mal runter getippt?
War nur so mal fix hingeschrieben, ist aber korrekt, bis auf zwei
vergessene ">" Zeichen bei den Schiebeoperationen. Hier nochmal etwas
aufgeräumt und simulationsfreundlich.
ja fettes DANKE!!!!
du schiebst dir das einafch zurecht... sag ich jetzt mal so ... du
maskirst immer nur ein Bit und schiebst das dann in das Ausgangsbyte
rein ... saubere Idee ... und ja du ahst recht das ist schneller^^
mfg Sascha
@ Nova (Gast)
>richitg?
Leider nein. Deine Ausgangsdaten sind immer noch nur 8 Bit, dort also
keine Änderung. LEdiglich die EIngangsdaten wachsen von 6 auf 12 Bit, es
ändert sich nur byte_in und die Maske für byte_in. Einfacher als du
denkst ;-)
Siehe unten.
1
voidsend_tlc5941_pwm(uint16_tpwm_array[]){
2
3
TLC5941_PORT&=~(1<<TLC5941_MODE);
4
5
uint8_tbit_count_in;// Zähler für Bits in den Eingangsdaten 6Bit/Segment
6
uint8_tbit_count_out=0;// Zähler für Bits in den Ausgangsdaten 8Bit/SPI Byte
7
uint8_tdot_count;// Zähler für Arrayindex der Eingangsdaten
8
uint16_tbyte_in;// Eingangsdaten
9
uint8_tbyte_out=0;// Ausgangsdaten
10
uint8_tmask_out=0x80;// Bitmaske für Ausgangsdaten
11
12
for(dot_count=0;dot_count<16;dot_count++){// Schleife über Eingangsarray
13
byte_in=pwm_array[dot_count];// nächstes Element laden
jo sehr cool ... das ding geht ja^^
wenn ich fertig bin soll das mal ein rgb folienleier werden mit den ic's
auf dem folien leiter und mir ist aufgefallen man sollte das spi schon
voll aufdrehen (8MHz) bei 100 KHz SPI Clk Flacken die LED's
@ Nova (Gast)
>auf dem folien leiter und mir ist aufgefallen man sollte das spi schon>voll aufdrehen (8MHz) bei 100 KHz SPI Clk Flacken die LED's
Dann machst du was falsch. Die LED-Ansteuerung ist unabhängig von der
SPI-Geschwindigkeit.
MFG
Falk
ja ok^^
in zwichen bin ich da auch durchgestiegen^^
Ps.: geile Variante total einfach, multifunktional einsetz bar, SAU
schnell, und ich bin nicht draufgekommen -_- ....
ps kennsich wer mit controllerlosen displays aus?
Beitrag "GLCD Interface"
kann mir da wer weiter helfen?
Guten Tag!
Ich weiss, der Beitrag ist etwas älter aber der Beste den ich zum Thema
TLC4951 gefunden habe!
Ich bin an einem Projekt in dem zwei TLC4951's die Hauptrolle haben.
Die LED Reihe bestehet aus 2x16 LED. Die 2 TLC's sollen die Daten für
die LED's innerhalb einer 1/100s erhalten und danach auch genau so lange
anzeigen.
Bin kein Experte im Programmieren und werde mich mit dem Code weiter
oben noch ein wenig auseinander setzen.
Da ich die Daten schneller senden müsste, könnte ich auch den Timer 1 im
CTC-Modus verwenden und eine Taktrate von z.B. 10MHz...?
Da ich später 32 RGB LED verwenden möchte bräuchte ich 6xTLC4951 somit
32 x 12 Bit x 3 Farben = 1152 Bit und bei 10MHz eine Übertragungszeit
von 0.0001152 plus BLANK und XLAT Zeit.
Kommt das hin?
Könnte man den oben genannten Code so anpassen?
@ Michael Ammann (ammannm)
>Die LED Reihe bestehet aus 2x16 LED. Die 2 TLC's sollen die Daten für>die LED's innerhalb einer 1/100s erhalten und danach auch genau so lange>anzeigen.
Kein Problem.
>Da ich die Daten schneller senden müsste, könnte ich auch den Timer 1 im>CTC-Modus verwenden und eine Taktrate von z.B. 10MHz...?
Nimm das SPI Modul des Mikrocontrollers.
>Da ich später 32 RGB LED verwenden möchte bräuchte ich 6xTLC4951 somit>32 x 12 Bit x 3 Farben = 1152 Bit und bei 10MHz eine Übertragungszeit>von 0.0001152 plus BLANK und XLAT Zeit.
Der Fachmann nennt das 115,2us, weil kein Mensch soviele Nullen
schreiben und abzählen will.
>Kommt das hin?
Ja.
>Könnte man den oben genannten Code so anpassen?
Sicher. Wo ist das Problem? Statt 16 nimmst du halt 32 oder mehr für
dot_count.
Danke Falk Brunner!
Habe Testprogramm geschrieben mit dem Code aus den Beiträgen weiter
oben.
Weiter habe ich mich über den SPI schlau gemacht. Die Taktrate kann
nicht voll ausgenutzt werden, da SPR0 und SPR1 wenn nicht high,
Systemtakt/4 ergeben was leider schade ist. Kann sein dass ich noch zu
wenig darüber gelesen habe (SPI ist neu für mich!) und es einen anderen
Weg gibt um das ganze schneller laufen zu lassen?!
Der Code ist im Anhang. Was noch fehlt sind die XLAT und BLANK Impulse
um die Daten zu übernehmen.
Werde den Code heute nicht mehr testen können. Hoffe habe keine Fehler
gemacht?!
Gruss Michael