Probleme mit Arithmetik in C - WinAVR

#4757408
Lesenswert?

ein RTC-Baustein DS1302 wird ausgelesen. Dabei kommt es zu Fehlern. Die 
bits werden korrekt in ein unsigned char byte eingelesen.

In den oberen 4 bit stehen Sekunden*10 und in den unteren 4 bit die 
Sekunden. Es werden folgende Operationen durchgeführt:
1
unsigned char byte, temp, temp1;
2
((byte &= 0x0f) + ((byte >>=4) * 10));

dies klappt so leider nicht. Jedenfalls scheint das Ergebnis 0 oder 
falsch zu sein, obwohl Sekunden ungleich 0 da sind.

als Beispiel wird in byte abgelegt: 0101 1001 = 0x59
so weit so gut. Daraus müsste nun 5*10=50 + 9 =59 werden.
1
temp = (byte &= 0x0f); liefert als Ausgabe 9. Dies ist ok.
1
temp1 = ((byte >>=4) * 10); liefert jedoch 0, was falsch ist.

Ist das byte beim ersten Rechenvorgang ungewünscht verändert worden?
Legt sich der Compiler keine Kopie davon an?

Das Ergebnis von temp = temp + temp1 wird als unsigned int über USART 
ausgeben. Es erscheint über USART die falsche Ausgabe 90909. Wie ist das 
möglich?

Die Ausgabe von temp macht USART_Tx_int((unsigned int)temp) die ich 
schon länger nutze. Siehe den folgenden Code der Ausgabe:
1
void USART_Tx_int(unsigned int data){
2
   unsigned long temp;
3
   unsigned char tmp;
4
   unsigned char ziff=0; // fuehrende Null da? fuer Unterdrueckung
5
   
6
   signed char i;  // signed, damit for-Schleife beendet wird mit <0 !
7

8
   temp = INT2BCD5(data); 
9
   
10
   for (i=16; i>=0; i-=4)   {
11
     tmp= (((unsigned char) (temp>>i)) &0x0f)+'0'; 
12
     if (tmp=='0') { // eine Ziffer = Null da?
13
        if (ziff==0) { // ist es eine fuehrende 0?
14
           if (i==0) { // ist die letzte Ziffer eine 0?
15
              USART_Tx (tmp); // diese Null ausgeben
16
           }
17
           else { // nein, also unterdruecken
18
              USART_Tx (' '); // fuehrende Null als Space ausgeben
19
           }
20
        }
21
        else {
22
           USART_Tx (tmp); // Nullen in der Zahl als Nullen ausgeben
23
        }
24
     }
25
     else { // eine Ziffer ungleich Null da
26
       ziff=1;
27
       USART_Tx (tmp); // Ziffer 0-9 als ASCII ausgeben
28
     }
29
   }
30
}

Vielleicht hat jemand eine Idee warum und wo es hier klemmt?
#4757422
Lesenswert?

die BCD-Routine sieht so aus:
1
const unsigned int unit[]={10000,1000,100,10};
2
#define UNIT_TEN_THOU 0
3
#define UNIT_THOU     1
4
#define UNIT_HUNDRED  2
5
#define UNIT_TEN      3
6

7
unsigned long INT2BCD5(unsigned int input)
8
{
9
  return (unsigned long) convertBCD(UNIT_TEN_THOU,input);
10
}
11

12

13
unsigned long convertBCD(char digit, unsigned int input){
14
  unsigned long high = 0;
15
  char i;
16

17
  for (i=digit;i<=UNIT_TEN;i++){ 
18
     while (input >= unit[(int)i]){
19
        high++;
20
        input -= unit[(int)i];
21
     }
22
     high <<= 4;
23
  }
24
  return high | input;
25
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren