operacje na liczbach w zapisie z uzupełnieniem do dwóch

Tutaj mozesz poruszać tematy ogólne powiązane z elektroniką, np. dyskusje na temat podzespołów, układów, zasad ich działania. Czyli można pisać o wszystkim czego nie da się przyporządkować do innych działów.
ODPOWIEDZ
slawek55
Użytkownik
Posty: 475
Rejestracja: 16 sie 2005, 11:47
Lokalizacja: Szczecin

operacje na liczbach w zapisie z uzupełnieniem do dwóch

Post autor: slawek55 » 21 lis 2005, 6:39

Cześć.

Chciałem Was prosić o pomoc w rozwiazaniu takiego problemu.
Otóż mam czujnik temperatury, który podaje wynik z uzupełnieniem do dwóch.
Odczytuje ten wynik i potrzebuję podzielić tą wartość przez dwa.
I tu zaczynają sie schody, bo jeśli mam np dziesiętnie -6 (a hex 0xFA) to po podzieleniu przez 2 wcale nie dostaję -3 (0xFD) tylko zupełnie inną liczbę. Jest tak jakby kompilator miał zamiast -6 liczbę dodatnią 250 i dopiero tą liczbę dzieli przez 2.

Jest to kompilator C dla AVR i zmienna jest deklarowana jaku signed char.

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 21 lis 2005, 14:02

Podaj, proszę, więcej informacji:
1. Jeśli możesz, przedstaw odpowiedni fragment kodu źródłowego.
2. Gdzie otrzymujesz niespodziewany wynik? W emulacji? W gotowym układzie? Może winna jest procedura wyświetlająca wyniki? Czy uwzględnia ona możliwość cyfry ze znakiem?

tasza
Użytkownik
Posty: 1391
Rejestracja: 21 lut 2005, 15:02

Re: operacje na liczbach w zapisie z uzupełnieniem do dwóch

Post autor: tasza » 21 lis 2005, 14:20

slawek55 pisze:Jest to kompilator C dla AVR i zmienna jest deklarowana jaku signed char.
a jakiego typu jest wynik? też signed char?
to akurat z VC++

Kod: Zaznacz cały

signed char schValue = -30;	

signed char schResult_Signed = schValue / 3;
printf ("rsig = %d (%02X) \n", schResult_Signed, schResult_Signed );

unsigned char schResult_Unsigned = schValue / 3;
printf ("runs = %d (%02X) \n", schResult_Unsigned, schResult_Unsigned );
i wyjście:

Kod: Zaznacz cały

rsig = -10 (FFFFFFF6)
runs = 246 (F6)
pierwszy wynik ok, dla typów ze znakiem, drugi? tak jak u Ciebie...
problem jest chyba w złych typach danych lub braku rzutownia na signed char

slawek55
Użytkownik
Posty: 475
Rejestracja: 16 sie 2005, 11:47
Lokalizacja: Szczecin

Post autor: slawek55 » 22 lis 2005, 7:04

Czeœć sorry że tak póŸno odpowiadam, pewne kłaopoty z sieciš.

Dowiedziałem sie ze moj kompilator obługuje ze znakiem tylko int , char zawsze unsigne.
Szukałem algorytmow obliczeń na zmiennych jednobajtowych w kodzie U2 ale nie znalazłem nic, jeœli macie cos to podrzucie.

Przedstawiam moj kod jest to Obsługa odczytu DS1820 (nie jest to moj pomysł tylko z sieci).

signed char Tb;
signed int Tm;
unsigned char Tb01,minus,;
char Str[9];


Tb=(signed char)Str[0]; // w tym rejestrze jest wartiosc tem w kodzie U2
Tb=Tb/2;
Tb01=((Str[7]-Str[6])*10)/Str[7];
Tm=(Tb*100)+(Tb01*10)-25;

if((Tm&0x8000)==0x800)
{ //liczba ujena
minus=1;
Tm=~Tm;
Tm=Tm+1;
}
else minus=0;

Str[0]=0;
while(Tm>99){ Tm=Tm-100; Str[0]++; } //wyliczenie czeci calokwitej
Tb01=(char)Tm; //reszta to cyfra po przecinku
Tb01=Tb01/10; //tylko jedno miejsce po przecinku


jeœli macie jakiœ lepszy kod to będę wdzięczny.

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 22 lis 2005, 9:11

Zerknąłem tylko w pośpiechu. Jeśli jednak skopiowałeś kod bezpośrednio, to:

Kod: Zaznacz cały

if((Tm&0x8000)==0x800) <- może sam widzisz już błąd?
Ogólnie aby uniknąć takich problemów polecam:

Kod: Zaznacz cały

if(Tm&0x8000)
Albo jeszcze lepiej... nie pozostawiająć jakichkolwiek wątpliwości:

Kod: Zaznacz cały

if(Tm<0)
Też będzie działać prawidłowo

Jaki to kompilator nie obsługuje signed char? Jeśli to gcc, polecam przyjrzenie się nagłówkowi inttypes.h

slawek55
Użytkownik
Posty: 475
Rejestracja: 16 sie 2005, 11:47
Lokalizacja: Szczecin

Post autor: slawek55 » 22 lis 2005, 9:50

Nie jest to gcc

ODPOWIEDZ