Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 19 kwi 2024, o 04:56


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 4 ] 
Autor Wiadomość
PostNapisane: 17 sty 2021, o 11:22 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 28 gru 2014
Posty: 21
Pomógł: 0

Witajcie!

Napisałem sobie funkcję służącą do obliczania mocy wyjściowej pewnego urządzenia i wyświetlania go na LCD (HD44780 4 x 20):
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Na potrzeby testu wywołuję go z funkcji głównej programu stałymi wartościami:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Pomijam też przeliczanie surowej wartości z adc na fizyczne jednostki (są "zakomentowane").

Zgodnie z oczekiwaniami gdy wartości przekazywane do funkcji wynoszą odpowiednio 1680 i 200, wynikiem mnożenia jest liczba 336000. Ta powinna znajdować się w zmiennej p zapisana binarnie tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


następnie w wyniku dzielenia do zmiennej power trafić powinna liczba 336 zapisana tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


po czym zostać wyświetlona na lcd.

Niestety jak bym nie próbował - na wyświetlaczu mam cyfrę 8...

Spróbowałem wyświetlić zawartość zmiennej power bez dzielenia na 1000:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


i otrzymuję wynik 8320, binarnie to będzie:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Okazuje się, że jest to wynik mnożenia (336000) z którego znikają cztery najstarsze bity. Wszystko się zgadza. Czemu natomiast dzielenie przez tysiąc wykonywane jest już na obciętej wartości? Tzn dzielone jest 8320 a nie 336000? Próbowałem też zrobić tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Niestety również wynikiem jest liczba 8.

Dajcie proszę jakąś wskazówkę - nie mam już za bardzo pomysłu. Myślałem że ostatni przykład załatwi sprawę i do zmiennej uint32_t zostanie zapisany wynik 336000 i podzielony przez 1000, jednak tam również ucięte są cztery najstarsze bity.

Mógłbym teoretycznie dzielić liczby przed mnożeniem ale:
- to jest ominięcie problemu a nie rozwiązanie + zerowa wartość edukacyjna
- nie uzyskam zakładanej dokładności

Procesor to Atmega8 taktowana fcpu = 16MHZ.

Proszę o wyrozumiałość - jestem amatorem hobbystą i dopiero się uczę :)

Łukasz



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sty 2021, o 12:47 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 mar 2014
Posty: 330
Lokalizacja: Rybnik
Pomógł: 54

https://atnel.pl/domyslna-promocja-do-typu-int.html


Autor postu otrzymał pochwałę

_________________
Amatorska stacje meteorologiczna



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sty 2021, o 12:52 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 sie 2015
Posty: 205
Lokalizacja: UK
Pomógł: 10

Policzyłem to korzystając z windowsowego kalkulatora i mi również wyszło 8 :) Dlaczego? Zobacz na linię 10. kodu twojej funkcji i zastanów się jak wykona się operacja dzielenia.

Wykonujesz rzutowanie na typ 16 bitowy. Wcześniej, wynik (jak mówiłeś) wynosi 0100 0010 0000 1000 0000.

Po wyrzuceniu 4 najbardziej znaczących bitów podziel 0b0010 0000 1000 0000 (0x2080) / 0b0011 1110 1000(0x3E8) i kalkulator pokaże 8 jak na zdjęciu poniżej.

Obrazek

Mam nadzieję, że się nie pomyliłem, ale proszę mnie poprawić jeżeli jednak to nie to ;)


Autor postu otrzymał pochwałę

_________________
MMT Technologies



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sty 2021, o 13:58 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 28 gru 2014
Posty: 21
Pomógł: 0

anonimowy napisał(a):
https://atnel.pl/domyslna-promocja-do-typu-int.html


Bingo! Przejrzałem właśnie całego BB i nie znalazłem niczego na ten temat. Bardzo ci dziękuję.

Makowka napisał(a):
Policzyłem to korzystając z windowsowego kalkulatora i mi również wyszło 8 :) Dlaczego? Zobacz na linię 10. kodu twojej funkcji i zastanów się jak wykona się operacja dzielenia.

Wykonujesz rzutowanie na typ 16 bitowy. Wcześniej, wynik (jak mówiłeś) wynosi 0100 0010 0000 1000 0000.

Po wyrzuceniu 4 najbardziej znaczących bitów podziel 0b0010 0000 1000 0000 (0x2080) / 0b0011 1110 1000(0x3E8) i kalkulator pokaże 8 jak na zdjęciu poniżej.

Obrazek

Mam nadzieję, że się nie pomyliłem, ale proszę mnie poprawić jeżeli jednak to nie to ;)


No właśnie według mojego rozumowania do zmiennej uint16_t powinien zostać zapisany wynik dzielenia zmiennej uint32_t przez 1000 a nie najpierw sama zmienna a później operacja dzielenia na niej. Z resztą w następnych wersjach funkcji wyeliminowałem ten problem jednak bez skutku.

Ostatecznie działająca funkcja wygląda tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Problem leżał w tym że kompilator zapisywał wynik mnożenia a * b do jakiejśc zmiennej tymczasowej dwubajtowej pomimo iż wynik miał być zapisany do uint32_t. Wystarczyło potraktować zmienne a i b jako zmienne czterobajtowe i wynik jest już prawidłowy.

Makowka w tej funkcji też zapisałem na próbę wszystko w jednej linii i problem nie występuje :)

Miłego dnia wszystkim!



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 4 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 7 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO