[AVR]AtMega8 i ADC, dlaczego tak?

Mar 06, 2006 22 Replies

Witam Jakis czas temu zaczalem zabawe z AVR. Napisalem prosty programik w asemblerze i pojawil sie dziwny problem, ktorego nie potrafie sobie wytlumaczyc. Jest tak: ADC dziala sobie, wynik przesuwany do lewej, czyli w w mlodszej czesci rejestru wynikowego dostaje wynik pomiaru. Napiecie referencyjne to 5V. Wszystko dziala Ok, na wyswietlacz segmentowy wypisuje wynik, dla 5V mam



255. Teraz chcialem zamienic to na napiecie w V.
5V/255 daje ~0.019 V/jednostke. Mnozac wynik pomiaru przez 0.019 powinienem miec wynik w V jest tak: w r16 mam wynik pomiaru dalej mam tak: ldi r17,q7(0.019) fmul r16,r17

w r0 bede mial czesc po przecinku w r1 czesc calkowita



Problem w tym, ze dla 5V napiecia mierzonego po mnozeniu dostaje w wynikach r1 = 3 r0 = 32 (czy cos kolo tego) Dlaczego?



Mozna to obejsc, wpisujac mnoznik 0.029 (podaje z pamieci) i wtedy dla



5V dostane 5V na wyswietlaczu. Dzieki za jakies sugestie Pozdrawiam TomaszB

:-)

Od kiedy AVR operuj± na floatach??

Mister

TomaszB napisał(a):

Tak z ciekawości zapytam ;-) jak Ci się udaje wpisać 0.019 do 1-go bajtu pomijając kwestię, że jest to liczba zmiennoprzecinkowa ? ;-))))

Pozdrawiam

Krzysztof Piecuch napisał(a):

Z tego co wyczytalem z ksiazki, to funkcja q7() mowi dla kompilatora, ze jest to liczba zmiennoprzecinowa i odpowienio ja zamienia i miesci na jednym bajcie.

Skoro w asm dla AVR sa przewidziane funkcje do operacji na liczbach zmiennoprzecinkowych (np fmul - mnozenie bez znaku liczb zmiennprzecinkowych) to chyba jest to mozliwe jak tez mozliwe jest wpisanie do jednego bajtu liczby zmiennoprzecinkowej z pewnego zakresu. Pozdrawiam TomaszB

Skad ty wziales ta informacje? FMUL to mnozenie dwoch 8 bitowych liczb bez znaku. AVR NIE POSIADA operacji na liczbach zmiennoprzecinkowych. Prostym trickiem jest wykorzystanie liczb stalopozycyjnych. Mozesz je normalnie mnozyc za pomoca MUL, pamietajac o odpowiednim przesunieciu pozycji dziesietnej.

T.M.F. napisał(a):

Jak tylko wroce do domu, to przeczytam jeszcze raz i zweryfikuje swoj poglad na ta sprawe. Pozdrawiam TomaszB

T.M.F. napisał(a):

informacja pobrana ze strony

formatting link
w dziale mikrokontrolery -> jezyk asembler AVR -> Lista rozkazów mikrokontrolerów AVR

w tabelce z rozkazami mamy: MUL Rd,Rs Mnożenie bez znaku zawartości rejestrów R1:R0 ¬ Rd · Rs Z,C 2 MULS Rhd,Rhs Mnożenie ze znakiem zawartości rejestrów R1:R0 ¬ Rhd · Rhs Z,C 2 MULSU Rhd,Rhs Mnożenie zawartości rejestrów (jeden ze znakiem, drugi bez znaku) R1:R0 ¬ Rhd · Rhs Z,C 2 FMUL Rd,Rs Mnożenie liczb ułamkowych bez znaku R1:R0 ¬ (Rd · Rs) << 1 Z,C 2 FMULS Rd,Rs Mnożenie liczb ułamkowych ze znakiem R1:R0 ¬ (Rd · Rs) << 1 Z,C 2 FMULSU Rd,Rs Mnożenie liczby ułamkowej ze znakiem z liczbą ułamkową bez znaku R1:R0 ¬ (Rd · Rs) << 1 Z,C 2

T.M.F. napisał(a): > Skad ty wziales ta informacje? FMUL to mnozenie dwoch 8 bitowych liczb

Pomylilem pojecie, zamiast zmiennoprzecinkowa mialo byc stalopozycyjna (zmiennoprzecinkowe to mam w C++ :/)

Tak czy inaczej, moj problem z pierwszego posta dalej jest nierozwiazany. Pozdrawiam TomaszB

Zawsze sprawdzaj u ¼róde³:

formatting link
Liczby zmienno-przecinkowe zazwyczaj s± kodowane na czterech bajtach, do sprzêtowego dzia³ania na nich wymagany jest koprocesor, którego w 8 bitowych procesorach raczej siê nie stosuje.

Mister

Mister napisał(a):

TAk, pomylilem formaty, do czego przyznalem sie w poscie nizej. Chodzilo o liczby ulamkowe, stalopozycyjne. Pozdrawiam TomaszB

Dnia Mon, 06 Mar 2006 14:18:10 +0100, TomaszB napisał(a): <ciach>

Strona 71 dokumentu "Instruction set". FMUL operuje na nietypowym formacie (1.7), a wynik jest w formacie (1.15), przy czym numery oznaczają liczbę _bitów_ na część całkowitą i ułamkową.

Dokładną interpretację wyniku doczytaj, ja za bardzo nie zrozumiałem ;)

Pozdrawiam Marcin Stanisz

Marcin Stanisz napisał(a):

W ksiazce o AtMegach jest troszke jasniej. Wychodzi na to, ze jak sie mnozy liczbe calkowita (8n.0q) przez liczbe ulamkowa w formacie 1.7 (1n.7q) to w wyniku operacji fmul otrzymamy liczbe w formacie 8n.8q czyli w dwoch rejestrach r0 i r1 beda odpowiednio: r1-czesc calkowita, r0-czesc ulamkowa. Dla liczb 8 bitowych jest dosc prosto, gozej z liczbami 16 bitowymi:( ale to chyba tez da sie jakos zrozumiec;) Pozdrawiam TomaszB

A co zwraca funcja q7(0.019)?

Wynik dzia³ania funkcji FMUL to R1:R0 <- (Rd x Rr) << 1

Mo¿e jaki¶ przyk³ad jest w tej ksi±¿ce?

Piotr Chmiel napisał(a):

Jest, mnozenie bez znaku liczby calkowitej, 8 bit przez liczbe ulamkowa <1. ldi r16,100 ldi r17,q7(0.25) fmul r16,r17

Wwyniku dostaniemy wartosc 0x1900 (r1:r0) czyli r1=25 (czesc calkowita) r0=0 (czesc ulamkowa)

dla mnozenia prze liczbe wieksza od 1 trzeba zrobic tak: ldi r17, (1<<7)+q7(0.25) co da mnozenie przez 1.25

Pozdrawiam TomaszB

Zwraca 0x02 co daje 0,015625

Juz widze, gdzie jest blad:( Trzeba bedzie dowiedziec sie, jak mnozyc liczbe 16 bitowa przez liczbe

1N.Q15. Pozdrawiam TomaszB

Czyli wychodzi na to, ¿e obliczenie jest poprawne:

0.015625 * 255 = 3.984375 czyli to co koledze wysz³o (3 ca³kowie FC u³amek)

Funkcja q7(0.019) zwraca 0.015625 (0x02)

Zgadzam siê, aby obliczenie by³o dok³adniejsze trzeba siê przesi±¶æ na liczby 16 bitowe.

Piotr Chmiel napisał(a):

A moze kolega juz to przerabial i moglby podpowiedziec jak przeprowadzic mnozenie liczby 16 bitowej przez liczbe 1n.q15? Dziekuje Pozdrawiam TomaszB

A nie prosciej zamiast tak kombinowac wykorzystac normalny zapis stalopozycyjny. Mnozysz wartosc ADC*19 i dla 255 masz 4845, przyjmujesz, ze trzy ostatnie cyfry to cyfry po przecinku i juz. Potrzebujesz wieksza precyzje to mnozysz nie *19 a razy 196 i wtedy przyjmujesz 4 ostatnie cyfry, ze sa po przecinku. Co wazne ciagle miescisz sie na 16 bitach.

Przerabiam to razem z Wami. Nie bawi³em siê rozkazami mno¿enia w AVR. Zato mam chyba to czego ci potrzeba:)

;****************************************************************************** ;* DESCRIPTION ;* Signed fractional multiply of two 16-bit numbers with 32-bit result. ;* USAGE ;* r19:r18:r17:r16 = ( r23:r22 * r21:r20 ) << 1 ;****************************************************************************** fmuls16x16_32: clrr2 fmulsr23, r21;((signed)ah * (signed)bh) << 1 movwr19:r18, r1:r0 fmulr22, r20;(al * bl) << 1 adcr18, r2 movwr17:r16, r1:r0 fmulsur23, r20;((signed)ah * bl) << 1 sbcr19, r2 addr17, r0 adcr18, r1 adcr19, r2 fmulsur21, r22;((signed)bh * al) << 1 sbcr19, r2 addr17, r0 adcr18, r1 adcr19, r2

ps. kod trzeba doprowadziæ do ³adu - w sensie wywaliæ komentarze i powstawiaæ gdzieniegdzie spacje :)

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required