2010-02-27 9 views
8

Próbuję uporządkować moją bibliotekę UART i nieco ją upiększyć, dodając kilka # definicji, dzięki czemu mogę ją później dostosować bez konieczności głębokiego zagłębiania się w kod, ale nie mogę uzyskać następującego fragmentu kodu pracy:C: Lekarstwo na ostrzeżenie: przekroczenie liczby całkowitej w wyrażeniu?

#define FOSC  8000000 
#define BAUDRATE 9600 
#define BRGVAL  (FOSC/2)/(16*BAUDRATE)-1 

void uart_init(){ 
    U1BRG = BRGVAL; 
} 

Po BRGVAL kalkulacja staje 25.0416667, a ponieważ nie jest liczbą całkowitą otrzymuję następujące ostrzeżenie za to, że kiedy przypisać do U1BRG:

UART.c: W funkcji ' uart_init ':

UART.c: 24: ostrzeżenie: liczba całkowita przepełnienie w wyrażeniu

... a kod po prostu nie działa na docelowym sprzęcie. (Jeśli ręcznie wstawiam U1BRG = 25 działa to jak zaklęcie)

Czy istnieje sposób na wpisanie tej stałej do liczby całkowitej, aby kompilator był szczęśliwy?

Wielkie dzięki, Hamza.

+1

Jaki jest typ U1BRG (i rozmiar tego typu)? –

+4

Dlaczego uważasz, że BRGVAL staje się 25.0416667? Wszystkie komponenty wyrażenia w makrze są liczbami całkowitymi, więc gdy makro zostanie zastąpione, wyrażenie użyje do obliczenia arytmetyki liczb całkowitych. Problem, o którym ostrzega kompilator, to przepełnienie, a nie obcinanie zmiennoprzecinkowe. –

+0

U! 1BRG jest unsigned int (16bits) i jest to kompilator MPLAB C30 – Hamza

Odpowiedz

22

Integer przelewowy oznacza, że ​​przekroczył górną granicę wartości int, który jest prawdopodobnie 32767 jeśli otrzymujesz ten błąd. Nie ma nic wspólnego z zmiennoprzecinkową; Operacje, które określiłeś, są w rzeczywistości operacjami matematycznymi całkowitymi, więc część ułamkowa podziału jest i tak odrzucana.

spróbować czegoś takiego:

#define FOSC  8000000L 
#define BAUDRATE 9600L 
#define BRGVAL  ((unsigned int)((FOSC/2)/(16*BAUDRATE)-1)) 

void uart_init(){ 
    U1BRG = BRGVAL; 
} 

L przyrostek okazuje te stałe do long typu zamiast int typu. Przesłona (unsigned int) konwertuje na typ U1BRG i informuje kompilator, że rozumiesz, że wartość long zmieści się w unsigned int i ukryje w ten sposób ostrzeżenia, które może rzucić na ciebie.

Normalnie, to jest złe praktyki, aby wyciszyć ostrzeżenia kompilatora, ale w tym przypadku, to jasne, że choć trzeba long do przechowywania wartości pośrednich w obliczeniach, wynik końcowy będzie pasował do z unsigned int.

+0

Cześć Phillip, Dzięki za sugestię, następujący fragment kodu wydaje się dla mnie teraz #define \t Fosc \t \t 8000000L #define \t BAUDRATE \t 9600L #define \t BRGVAL \t \t (FOSC/2)/(16 * BAUDRATE) -1 z jakiegoś dziwnego powodu Jeśli dodam, że (int) rzutowane na BRGVAL, otrzymuję wartość 65536 (limit int?), nie wiem, dlaczego tak się dzieje. Bez obsady wygląda na to, że działa ... – Hamza

+0

@Adam Albo BAUDRATE musi być długi, albo magiczna liczba 16 musi być długa, bo inaczej 16 * BAUDRATE się przepełni. –

+0

@Hamza jakiego kodu używasz do dodawania obsady? Wszystkie nawiasy są niezbędne dla obsady. Jeśli robisz (int) (FOSC/2)/(16 * BAUDRATE) -1 lub (int) BRGVAL, to nie rzutujesz całego wyrażenia, ale raczej tylko rzutujesz (FOSC/2) na int, co spowoduje przepełnienie i stać się małą liczbą. Następnie podzielisz tę małą liczbę przez (16 * BAUDRATE), dużą liczbę, która daje wynik 0. Następnie odejmiesz 1, czyniąc -1. Przypisz -1 do niepodpisanego int, a otoczysz i uzyskasz 65535. Krótko mówiąc, jeśli wykonujesz rzutowanie, dodaj nawias wokół całego wyrażanego wyrażenia. –

0

I prawdopodobnie to wykorzystać:

#define BRGVAL  ((int)(FOSC/2)/(16*BAUDRATE)-1) 
+0

Witaj Segfault, niestety to nie działa. – Hamza

0

Mogłeś nie zwrócić na to uwagę, jaki jest typ danych dla U1BRG? Jeśli jest to int, rzucić go jak jak pokazano

 
#define FOSC  8000000 
#define BAUDRATE 9600 
#define BRGVAL  ((long)(FOSC/2)/(16*BAUDRATE)-1) 

void uart_init(){ 
    U1BRG = BRGVAL; 
} 

Edit: Zmieniony to wziąć pod uwagę z Adam Liss „s komentarz unsigned int jest zbyt mały, aby pomieścić wynikiem makro, zmieniłem to, aby to long ... Dzięki Adam za HeadsUp ...

Nadzieja to pomaga, poważaniem Toma.

+0

Witaj Tomie, jest to typ 'unsigned int', próbowałem wykonywać odlewania (int), ale ten sam błąd nadal wyskakuje ... – Hamza

+0

FOSC/2 jest nadal zbyt duży, aby zmieścić się w int. –

+0

nadal otrzymujesz przepełnienie z 16 * BAUDRATE, które nie pasuje do int. –

0

Z twojego przykładu nie wynika jasno, czy U1BRG jest zmienną globalną czy stałą zdefiniowaną przez #. W każdym razie, po prostu rzucając na liczbę całkowitą powinno działać:

U1BRG = (int)BRGVAL; 
+0

Witaj Js, U1BRG jest zdefiniowany w innym pliku hesera jako unsigned int, próbowałem robić (int), ale ten sam błąd nadal pojawia się – Hamza

8

Lubię odpowiedź Filipa, ale myślę, że lepszym rozwiązaniem jest zmniejszenie formułę i zmienić swoje makra:

#define BRGVAL (FOSC/32/BAUDRATE-1) 

W ten sposób można wyeliminować obsadę więc kompilator może nadal ostrzec jeśli wybierasz niską szybkość transmisji, która spowoduje, że wartość dzielnika będzie zbyt duża dla 16-bitowej wartości int.

+0

Hej Tom, dzięki za twoją sugestię. To działa jak urok! – Hamza

Powiązane problemy