Forum: Compiler & IDEs 8 Bit zu 16 Bit Fehler in der Zusammenführung


von ShishaLiVe (Gast)


Lesenswert?

Hallo,

Ich versuche aus zwei 8 Bit einen 16 Bit Wert zu einem PCA9685 zu 
Senden.


Leider bin ich nicht der C Profi und hoffe daher auf etwas Unterstützung 
oder Ratschläge.



Hier einmal mein versuch
1
while(1) {  
2
 if(dmx_rx_complete) {
3
      uint8_t led = 0;
4
      for(led = 0; led < 16; led++) {
5
        pca9685_led_pwm(PCA9685_CHIP_1, led_map[led], (dmx_buf_back[led + 1] << 8 ) | dmx_buf_back[led + 2]);
6
        
7
            }
8
         }
LG
Sven

von Werner (Gast)


Lesenswert?

Wenn dmx_buf_back 8 bit breit ist, dann wird das Geschiebe dazu führen, 
dass leuter nullen drin stehen.

Mach dir vorher einen Helper

unsigned int uihelper; //(16 Bit)

uihelper = (dmx_buf_back[led + 1] << 8 ) | (dmx_buf_back[led + 2]);

Bin mir nicht sicher, aber vielleicht musst du auf der rechten Seite 
auch noch ein Cast machen, damit dort überhaupt mit 16 bit gerechnet 
wird:

uihelper = (unsigned int)(dmx_buf_back[led + 1] << 8 ) | 
(dmx_buf_back[led + 2]);

Werner

von Peter II (Gast)


Lesenswert?

Werner schrieb:
> Wenn dmx_buf_back 8 bit breit ist, dann wird das Geschiebe dazu führen,
> dass leuter nullen drin stehen.

nein, C legt fest das alles mindestens in int (16 bit) rechnet wird.


@ShishaLiVe
was geht dann nicht? Was kommt raus und was erwartest du?

von A. S. (Gast)


Lesenswert?

Dein Code ist mit Sicherheit falsch, da Du led+1 und led+2 verpackst und 
dann in der Schleife led++ machst.

Beschreibe erstmal, was im letzten Parameter drinstehen soll, dann 
können wir sagen, wie es geht. Und beschreibe, ob das höchstwertige byte 
zu Anfang oder am Ende steht (in einem Array bei 0 oder bei 1?)

Vielleicht wolltest Du sowas:
1
if(dmx_rx_complete) 
2
{
3
uint8_t led = 0;
4
5
   for(led = 0; led < 16; led++) 
6
   {
7
   uint16_t v = dmx_buf_back[led*2 + 1] << 8 ) | dmx_buf_back[led*2 + 2])
8
9
        pca9685_led_pwm(PCA9685_CHIP_1, led_map[led], v);
10
   }
11
}

von ShishaLiVe (Gast)


Lesenswert?

Hey,


Danke das hilft mir schon mal weiter, werd es heute Abend ausprobieren.


Du hast natürlich recht led*2+1 ist natürlich richtig, wollte da nur 
erstmal alle fehlerquellen ausschließen ?




Lg
Sven

von ShishaLiVe (Gast)


Lesenswert?

Nabend,



Soweit so gut, das Funktioniert schon mal danke euch schon mal dafür.


Aber ein Problem habe ich noch.
Ich hätte gerne einen Master Dimmer für diese 4 Kanäle, eigentlich 
Rechnet man 16 Bit * 16 Bit / 16 Bit aber da kommt nur müll bei raus 
evtl hat hier noch jemand einen guten rat.



1
            for(led = 0; led < 4; led++) {
2
        uihelper1 = (dmx_buf_back[led*10 + 1] << 8 ) | dmx_buf_back[led*10 + 2];
3
        uihelper2 = (dmx_buf_back[led*10 + 3] << 8 ) | dmx_buf_back[led*10 + 4];
4
        uihelper3 = (dmx_buf_back[led*10 + 5] << 8 ) | dmx_buf_back[led*10 + 6];
5
        uihelper4 = (dmx_buf_back[led*10 + 7] << 8 ) | dmx_buf_back[led*10 + 8];
6
        dimmer =    (dmx_buf_back[led*10 + 9] << 8 ) | dmx_buf_back[led*10 + 10];
7
          pca9685_led_pwm(PCA9685_CHIP_1, (led*10+0), ((uihelper1 * dimmer)/65535));

LG
Sven

von Peter II (Gast)


Lesenswert?

ShishaLiVe schrieb:
> eigentlich
> Rechnet man 16 Bit * 16 Bit / 16 Bit aber da kommt nur müll bei raus
> evtl hat hier noch jemand einen guten rat.

weil 16bit mal 16bit sehr oft mehr als 16bit sind, da muss man schon mal 
mit 32bit rechnen.
1
pca9685_led_pwm(PCA9685_CHIP_1, (led*10+0), (( (uint32_t)uihelper1 * dimmer)/65535));

von ShishaLiVe (Gast)


Lesenswert?

Manchmal hat man einfach ein Brett vorm Kopf, macht natürlich sinn ;-)



Ich bedanke mich für eure Unterstützung.


Und Schönes Wochenende noch ;-)



Lg
Sven

von W.S. (Gast)


Lesenswert?

ShishaLiVe schrieb:
> Leider bin ich nicht der C Profi und hoffe daher auf etwas Unterstützung
> oder Ratschläge.
>
> Hier einmal mein versuch
> while(1) {
>  if(dmx_rx_complete) {
>       uint8_t led = 0;
>       for(led = 0; led < 16; led++) {
>         pca9685_led_pwm(PCA9685_CHIP_1, led_map[led], (dmx_buf_back[led
> + 1] << 8 ) | dmx_buf_back[led + 2]);

Warum muß es denn eigentlich immer maximal unleserlich sein?
Ich formuliere das mal um (ohne deine eher seltsam anmutenden Indices 
wirklich verstanden zu haben):
1
 long L;
2
 int  i;
3
 int  amap;
4
5
if(dmx_rx_complete) 
6
{ i = 0;
7
  while (i<16)
8
  { amap = led_map[i];
9
    L = dmx_buf_back[i+1];
10
    L = (L << 8) | dmx_buf_back[i+2];
11
    pca08154711(PCA_Chip, amap, L);
12
    ++i;
13
  }
14
}
Den Rest, also die ganze Optimiererei, kannst du getrost dem Compiler 
überlassen.

W.S.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

W.S. schrieb:
> ShishaLiVe schrieb:
>> Leider bin ich nicht der C Profi und hoffe daher auf etwas Unterstützung
>> oder Ratschläge.
>>
>> Hier einmal mein versuch
>> while(1) {
>>  if(dmx_rx_complete) {
>>       uint8_t led = 0;
>>       for(led = 0; led < 16; led++) {
>>         pca9685_led_pwm(PCA9685_CHIP_1, led_map[led], (dmx_buf_back[led
>> + 1] << 8 ) | dmx_buf_back[led + 2]);
>
> Warum muß es denn eigentlich immer maximal unleserlich sein?

Weil eine for-Schleife besser lesbar ist als das da:

> Ich formuliere das mal um (ohne deine eher seltsam anmutenden Indices
> wirklich verstanden zu haben):
>
> { i = 0;
>   while (i<16)
>   { ...
>     ++i;

Mal abgesehen davon, dass es keiner Coding-Rule folgt :-)

Wenn man das Zusammenbauen von 2 Bytes in einen 16-Bit Wert öfter 
braucht oder leserlicher haben will, dann geht nix über eine 
inline-Funktion.

>  long L;

hä?

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.