Hallo,
ich versuche PWM Werte für den TLC5940 in ein Array aus uint8_t zu
schreiben (damit ich sie später einfach über die SPI ausgeben kann)
Hier mein Code:
1
voidSetLED(uint8_tled,uint16_tvalue)
2
{
3
if(led|0b11111110==0)
4
{
5
// Blöcke 0, 2, 4, 6, ...
6
pwm_data_raw[led]=(uint8_t)(value>>4);
7
pwm_data_raw[led+1]=???
8
}
9
else
10
{
11
// Blöcke 1, 3, 5, 7, ...
12
pwm_data_raw[led-1]=(uint8_t)(value<<4);
13
pwm_data_raw[led]=(uint8_t)(value>>4);
14
}
15
}
Nur leider funktioniert... nichts :(
In der ersten IF-Abfrage will ich halt einfach teste, ob es gerade oder
nicht gerade ist... das dürfte ja stimmen.
Ist der Block ungerade, kommen die 8 oberen Bits (also die von 12-4) in
das erste Array-Glied und die unteren 4 Bit in die oberen 4 Bit des
zweiten Array-Gliedes.
Bei geraden halt genau umgekehrt ;)
Evtl. könnt ihr mir ja helfen. Hier eine Grafik des Aufbau's des
Array's. Die Zahl gibt den LED Kanal an:
00000000 00001111 11111111 22222222 22223333 33333333 44444444 44445555
Wäre nett, wenn mir einer da helfen könnte :D
Liebe Grüße
Julian
Jap, folgende Warnung:
warning: suggest parentheses around comparison in operand of ||
Aber tut mir Leid, ich bin eigentlich recht fit in C... nur dieses
Bitgeschiebe... das is einfach... ich versteh das einfach nicht und
versuche es auch immer zu vermeinde... nur hier geht es einfach nicht :/
Julian W. schrieb:> Aber tut mir Leid, ich bin eigentlich recht fit in C... nur dieses> Bitgeschiebe... das is einfach... ich versteh das einfach nicht und> versuche es auch immer zu vermeinde... nur hier geht es einfach nicht :
Guck mal nach Bitmanipulation
Hab ich schon... aber wie mach ich z.B. folgendes:
00001111 11112222
Diese 8 "Einsen" auslesen und in ein uint8_t kopieren?
Und die 2er dann in die oberen Bits eines anderen uint8_t kopieren?
also das aus
00001111 11112222
=>
11111111 2222XXXX (X = alte Bits)
und dann noch einmal "verdreht"
00001111 22222222
=>
XXXX1111 22222222 (Y = alte Bits)
Die if-Abfrage könnte ich evtl. noch durch % ersetzen, aber die Routiner
wird halt seeeeehr oft aufgerufen, daher dachte ich, dass das so evtl.
schneller geht.
Aber soweit ich das sehe werden dort doch nur 8 bit genutzt, oder?
Ich würde aber gerne schon die vollen 12 bit nutzen ;)
Beitrag "Re: AtMega 48 Timmer"
Aber ich glaube ich habe mein if-Problem lösen können mit:
Nein, ich muss ja die 12bit-Werte in 8bit-Blöcke (also ein Byte)
einsortieren. Und da unterscheide ich quasi zwei Fälle^^
bei geraden "Block-Nummern", also 0, 2, 4, 6, ...
00001111 11112222 (12 bit PWM-Wert in uint16_t)
=>
11111111 2222XXXX (X = alte Bits)
BLOCK BLOCK+1
bei ungeraden "Block-Nummern", also 1, 3, 5, 7, ...
00001111 22222222 (12 bit PWM-Wert in uint16_t)
=>
XXXX1111 22222222 (X = alte Bits)
BLOCK BLOCK+1
Das ganze ist halt für ein TLC5940, der eine 12bit PWM zur Verfügung
stellt und dem ich die Daten über SPI, also jeweils 8bit weise, zur
Verfügung stelle.
Mist, ich merke gerade dass das ja auch Blödsinn ist... mmhhhh... ich
muss morgen mir nochmal neu den Kopf darüber zerbrechen...
was ich brauche:
16x 12bit Werte, die jeweils in einem uint16_t gespeichert sind, direkt
aneinander in einem Array aus 24 Elementen des Typs uint8_t.
Julian W. schrieb:> Nein, ich muss ja die 12bit-Werte in 8bit-Blöcke (also ein Byte)> einsortieren. Und da unterscheide ich quasi zwei Fälle^^
Das paßt auch. Du kannst immer zwei 12-Bit-Werte in 3 Bytes stecken,
danach wiederholt sich das Schema.
> bei geraden "Block-Nummern", also 0, 2, 4, 6, ...>> 00001111 11112222 (12 bit PWM-Wert in uint16_t)> =>> 11111111 2222XXXX (X = alte Bits)> BLOCK BLOCK+1>>> bei ungeraden "Block-Nummern", also 1, 3, 5, 7, ...>> 00001111 22222222 (12 bit PWM-Wert in uint16_t)> =>> XXXX1111 22222222 (X = alte Bits)> BLOCK BLOCK+1
Sieht erstmal nicht so schlecht aus. Du darfst halt nur deine Xe nicht
überschreiben, sondern, wie du schon erwähnst, die alten Bits
beibehalten. Und du must BLOCK richtig ausrechnen, denn zwei Werte
brauchen ja nicht zwei, sondern drei Blöcke. Du mußt also deine
LED-Nummer * 3 / 2 nehmen, um die richtige Blocknummer zu bekommen:
@ Julian W. (julian-w) Benutzerseite
>Aber soweit ich das sehe werden dort doch nur 8 bit genutzt, oder?>Ich würde aber gerne schon die vollen 12 bit nutzen ;)
Dann bist du kurzsichtig.
Drei Beiträge im Thread tiefer . . .
Beitrag "Re: AtMega 48 Timmer"
Mein Ziel ist es halt, die Werte immer in uint8_t zu haben, da ich die
Werte sehr viel öfters senden wie bearbeiten muss. Daher denke ich ist
es effizenter, einfach immer nur das fertige Array zu senden anstatt die
zu sendenen Daten jedesmal neu zu "berechnen".
Hier mal was in C#, was funktionieren sollte:
Julian W. schrieb:> Mein Ziel ist es halt, die Werte immer in uint8_t zu haben, da ich die> Werte sehr viel öfters senden wie bearbeiten muss. Daher denke ich ist> es effizenter, einfach immer nur das fertige Array zu senden anstatt die> zu sendenen Daten jedesmal neu zu "berechnen".
Das ist ja auch ok
> Hier mal was in C#, was funktionieren sollte:
Nope.
Es gibt einen ganz einfachen Grund warum das nicht funktionieren KANN.
Mit einem Oder (|) kannst du immer nur Bits von 0 auf 1 ziehen. Um ein
1-Bit wieder auf 0 zu ziehen, brauchst du ein Und (&). Ich seh aber
keines in deinem Code, daher kann der schon mal im allgemeinen Fall dort
nicht stimmen, wo sich 2 Werte 1 Byte teilen müssen und du daher nicht
mit einer Zuweisung arbeiten kannst.
Aber abgesehen davon siehts nicht schlecht aus. Jetzt noch daraus eine
Funnktion machen, die aus der LED Nummer den ersten der beiden Array
Indizes bestimmt und welches der beiden Verfahren zur Bitmanipulation
anzuwenden ist und du hast es.
Stimmt... ich bin bei dieser einfachen "Simulation" einfach davon
ausgegangen, das vorher alles 0 ist.... Nur irgendwie klappt es mit &
gar nicht...
Könntest du mir nicht schnell weiterhelfen ;)
Was klappt denn nicht?
Du brauchst doch nur die 4 Bits, die du beschreiben willst vorher alle
miteinander gezielt auf 0 setzen, ehe du dann mit dem Oder einzelne
davon wieder auf 1 ziehst.
Bitmanipulationen
Sorry. Aber da musst du durch. Mit Und und Oder zu arbeiten um Bits in
einem Byte zu manipulieren, ist das kleine EinmalEins der
µC-Programmierung.
In beiden Fällen bearbeitet man ein Byte mit einer 'Maske'.
Bei einem Oder hat man im Ergebnis genau dort auf jeden Fall ein 1 Bit,
wo
in der Maske ebenfalls ein 1 Bit war.
Bei einem Und hat man im Ergebnis genau dort auf jeden Fall ein 0 Bit,
wo in der Maske ebenfalls ein 0 Bit war.
Oft ist die Maske konstant und fix, bei dir ist das ein Bitmuster, das
dir jemand vorgegeben hat.
Achso, quasi als zusätzlicher Schritt... Ich wollte irgendwie das ODER
durch ein UND ersetzten... und das ging schief^^
Hier mein Code... in C# funktioniert er :D
Julian W. schrieb:> Achso, quasi als zusätzlicher Schritt... Ich wollte irgendwie das ODER> durch ein UND ersetzten... und das ging schief^^>> Hier mein Code... in C# funktioniert er :D
OK.
Jetzt willst du noch ein
byte[] dat = new byte[20];
und eine Funktion, die die n-te LED auf einen Wert setzt.
Wie muss die Funktion aussehen?
Zum Test: die 4. Led setzen lassen, die 5. Led setzen lassen