Ahoj, po delší pauze jsem se zas vrátil k pokusování s AVR… Koukám do instrukčního souboru, vidim tam samý instrukce MUL, MULS, MULSU, FMUL, FMULS, … všude se násobí, a co dělení?
Na šel jsem jen dělení 2mi (ASR, LSR, ROR). No to nechápu, AVR, a ono to snad nemá ani dělení.
Nebo jsem někde něco přehlédl?
Jak se u AVR řeší např. dělení např. dvou 8b unsigned čísel? To jako kvůli tomu stvořit smyčku, která hodnotu neustále přičítá, a zjistí tak, kolikrát se tam vejde? (zbytek se dopočítá odečtením). Nebo se to dělá jinak, a lépe?
Dík moc
PS: tohle mě teda pěkně zaskočilo…
Pokial viem, nikde nie je uvedene, ze by AVR mal mat matematicky koprocesor.
To sa musite pozriet po inych typoch procesorov (napr. ARM7, tan tusim hw delenie ma)
Sposob delenia, ktory navrhujete sa nepouziva pre jeho zdlhavost, aj ked by urcite fungoval.
Ak s AVR zacinate, vrelo doporucujem prehrabat sa v aplikacnych poznamkach samotneho Atmela. Mozete tam najst vela inspirativneho, ci uz zapojenia, alebo kod. Inak v C to riesit nemusite - jedna z dobrych vlastnosti prekladaca.
Napriklad v aplikacnej poznamke AVR200 najdete postup ako na 8 / 16b signed i unsigned delenia a nasobenie. Vedla pdf by mal byt i kod na stiahnutie.
Ako na float v GCC najdete napr. tu:
winavr.scienceprog.com/avr-gcc-t … r-gcc.html
staci dat do googla spravne slova
ale furt to Cčko… Kdybych dělal v C, tak bych se takle blbě neptal
Dělám v ASM. ARM7 jen kvůli blbýmu dělení…
Instrukci DIV měly i straré 8051… (a to taky nejsou žádné matematické procesory)
Jinak nemáš tušení Martine, jak realizovat “ekonomičtější” variantu toho dělení než to postupně sčítat(nebo odečítat)? Jemi jasné že tohle bude trvat pěkně dlouho…
Od ATMELu mi to příde děsně neseriozní, hlavně že AVR mají 6 instrukci pro násobení
Mám program v ASM na dělení dvou neznamínkový 16.bit čísel u AVR min 126 cyklů a max. 142 cyklů
Ja rad poradim, ale evidente ignorujes co pisem. Uz si si stiahol AVR200.pdf a AVR200.zip (normalne nazvy vlozis do googla a ono Ti vypluje vyskyty), ktore uvadzam hned na zaciatku mojho prispevku?
Vidis tam nejake C-cko? Mas tam pekne rutiny na signed a unsigned delenie a nasobenie i s vypoctom velkosti a casu trvania.
Ale ak by to snad nebolo jasne, kludne to napisem este aj treti krat. Ale potom uz nie
Tu aplikacnu poznamku pre to GCC ber ako doplnok - sa mi nejak vygooglil a presiel sitom Ctrl+C /Ctrl+V. Z otazky mi je jasne, ze ide o ASM.
Ale hned na zaciatku Ta predsa odkazujem na ASM. Ta ne?
Ak by bol google problem, tak so mTi nasiel konkretnu stranku, odkial si AVR200 mozes stiahnut.
atmel.com/dyn/products/app_n … ily_id=607
Je to take jednoduche A doporucoval som Ti, aby si si pozrel i ine dokumenty - malo ktory z nich je o C-cku, - a ak na niektory taky narazis, tak ho preskoc. Je tam velmi vela inspirativneho kodu a popisov riesenia roznych problemov okolo AVR i okolo roznych matematickych rutin, ci okolo navrhu HW, ako pouzivat jednotlive periferie, sw UART, atd atd atd.
Vsjo jasno?
Pozeral som teraz namatkovo instrukcnu sadu 18F87 a tam som tiez ziadne delenie nenasiel, iba nasobenie. Nemyslim, ze by preto bol Microchip neseriozna firma, i ked este naviac robi vsetko 4x pomalsie ako ATmega (ale tam kde sa da pouzit, PLL to zachranuje ), takze aj to delenie bude normalne 4x pomalsie a procesory su to dobre, hojne pouzivane.
Atmega (podla AVR200) vydeli dve znamienkove 16b cisla do 261 taktov, co je pri 16MHz Xtale 16.3us a program zaberie 39 instrukcii. No des co?
este som nasiel toto (aj pre PICkarov)
Ono z toho “v aplikacnej poznamke AVR200” zrovna nejde hnedka pochopit, že to mám vrazit do googlu.
Jinak, zajmalo by mě, dělení zabere starejm 8051 4 strojový cykly, tj 48 hodinovejch taktů. Neexistuje náhodou něco aspoň takhle rychlého pro AVR? Jakým principem 8051 dělí? Vim že to jde realizovat špatně, ale co se dá dělat.
Původně tohle dělení mělo běžet několikset až tisíc krát za sekundu, a koukám, že to bude docela problém… Zkusím ještě zvážit jiná možná řešení (bez tolika dělení)
Nejde mi o již hotové zdrojáky, které si tam “jen tak ctrl c+v”, jde mi o pochopení principu toho dělení, jakým způsobem se to řeší. Trochu se porozhlídnu po netu, jelikož jsem to ještě neudělal, o víkendu se v tom zas zkusím trochu porýpat.
EDIT: “co je pri 16MHz Xtale 16.3us a program zaberie 39 instrukcii. No des co?” - Ja¨k se to veme. Na to na co sem to chtěl je to úděsně pomalý, na kalkulačku by to ale bohatě stačilo.
Zatím díkes, Honza
vždyt jsem psal, dvě 16 bit. neznaménková čísla na 142 taktů což je 8,9us
pokud jsem se překlepl v tom výpočtu tak to prosím omluvte
to dělení mám řešené jako postupné odečítání
Pre pochopenie ako rutiny funguju, je v aplikacnej poznamke AVR200.pdf na strane 11 (8b)a strane 16 (16b) vyvojovy diagram s podrobnym popisom co to robi.
Deli sa opacne ako sa nasobi.
Nasobi sa tak, ze s pripocitanim sa posunie rad (podobne ako na papieri v desiatkovej sustave - tiez sa pri nasobeni N * M nepripocitava M krat cislo N, ale sa postupne spocitavaju jednotlive medzivysledky s posunom o rad)
Deli sa zas presne ako na papieri, s odpocitavanim sa posuva rad. Ani pri vypoctoch s ceruzkou N/M nezistujeme vysledok tak, ze by sme od N neustale odpocitavali M.
Obdobne je tomu pri vypoctoch v binarnej sustave. Skus si pozriet ten dokument AVR200.pdf. Zdrojaky z AVR200.zip si kopirovat nemusis.
ATmega Ti vydeli dve znamienkove 16b cisla 61302x za sekundu (v najhorsom pripade).
No a x51 je holt x51.
Pokial viem, instrukciou DIV sa daju delit iba dve neznamienkove cisla.
Ako uvadzas, cely vypocet treva 48 hodinovych taktov. Da sa tato instrukcia pouzit i pre znamienkove viacbajtove delenia? Neviem, mozno nejako ano.
AVR spravi to iste za 97 taktov (podla AVR200, ale to neznamena, ze sa to neda spravit i inak, napriklad nie tak uspone na kod ale rychlejsie - caven pise nieco podobne ale rychlejsie) a zaberie to v pamati 14 instrukcii. Takze zhruba 164900x za sekundu. Okrem toho bezne AVR slape do 16MHz a bezna x51 do 24MHz. Takze v tomto pripade AVR vychadza
97/48*24/16 = 3x pomalsie.
A to este neuvazujem o rychlejsich jadrach x51 na 6/4/2/1 clk. Ako som pisal, niektore veci ostanu jednoducho neprekonane
No malokedy staci delit len unsigned 8bit (napr. pri kalibracii AD hodnot a tak podobne )na NETe
som ale napriklad nasiel (vytrhavam kusok z celej kniznice):
;====================================================================
; subroutine UDIV16
; 16-Bit / 16-Bit to 16-Bit Quotient & Remainder Unsigned Divide
;
; input: r1, r0 = Dividend X
; r3, r2 = Divisor Y
;
; output: r1, r0 = quotient Q of division Q = X / Y
; r3, r2 = remainder
;
; alters: acc, B, dpl, dph, r4, r5, r6, r7, flags
;====================================================================
UDIV16: mov r7, #0 ; clear partial remainder
mov r6, #0
mov B, #16 ; set loop count
div_loop: clr C ; clear carry flag
mov a, r0 ; shift the highest bit of
rlc a ; the dividend into…
mov r0, a
mov a, r1
rlc a
mov r1, a
mov a, r6 ; … the lowest bit of the
rlc a ; partial remainder
mov r6, a
mov a, r7
rlc a
mov r7, a
mov a, r6 ; trial subtract divisor
clr C ; from partial remainder
subb a, r2
mov dpl, a
mov a, r7
subb a, r3
mov dph, a
cpl C ; complement external borrow
jnc div_1 ; update partial remainder if
; borrow
mov r7, dph ; update partial remainder
mov r6, dpl
div_1: mov a, r4 ; shift result bit into partial
rlc a ; quotient
mov r4, a
mov a, r5
rlc a
mov r5, a
djnz B, div_loop
mov a, r5 ; put quotient in r0, and r1
mov r1, a
mov a, r4
mov r0, a
mov a, r7 ; get remainder, saved before the
mov r3, a ; last subtraction
mov a, r6
mov r2, a
ret
ak ani nepocitam slucky, len jednoduchym spocitanim instrukcii (co je velmi v prospech x51) vychadza cislo 43 * 12 = 516 taktov clk. Uz asi v tomto pripade asi bude mat to AVRko ci PICko (PLL 4x ) navrch.
Ale to sa divim spolu s Tebou, ze do tychto 8bitov nedavaju mat. koprocesor aspon an to delenie a nasobenie, ale aj odmocnina a goniometria by sa obcas hodili.
V tomto smere su omnoho lepsie vybavene ARM7, Cortex a im podobne, to je ale uz uplne ina kategoria.
Ku podivu instrukcie delenia, alebo nejaku hw delicku neimplementoval Atmel ani do Atxmegoveho radu.
Mě šlo jen o podíl dvou unsigned 8 bitových čísel, to “caven” si tu myslím začal s 2x signed 16bitů
Běžné 8051, jako 89S51, 89S52,… běží do 33MHz. Do 24MHz jsou ty jejich zastaralé “C” verze s horšími parametry 89C51, C52,… - tyhle ani neummějí sériové programování.
To jako fakt ani atxmegy nemaj dělení? Zajímalo by mě proč… se atmelu dělení nějak nezamlouvá
Jinak dík, o víkendu si udělám čas, a podrobně to prozkoumám.
ano, já jsem s tím začal, ale jenom proto aby si viděl jak ten kod pro 16. bitové dělení trvá dlouho. Nic víc nic míň
Taky ti nic nevyčítám… Jen odhadem, jak dlouho trvá dělení dvou Uint8 mezi sebou?
Preco odhadom?
Casy uvadzam to v mojom prispevku z 21 leden 2009, 23:29
Rutiny sa daju napisat s prihliadnutim na velkost kodu, alebo na rychlost aplikacie. A konkretne v pripade delenia dvoch unsigned 8b je na tom x51 minimalne 3x lepsie, ako AVR.
to je docela krutej paradox… z 89S51 vymáčknu sotva 3MIPS, z AVR 16MIPS, a když se trochu přetaktuje, tak i těch 20MIPS dá. A přecejenom ten pomalejší procesor je rychlejší (v dělení). omg…
Ale len pre ten jedne pripad unsigned 8b.
V ostatnych pripadoch je garde obratene.
Inak ATmega88/168/328/164/324/644P idu regulerne do 20MHz, takze ak by sa pretaktoval (co rozhodne nedoporucujem) mohol by ist na 22-24MHz. Atxmega do 32MHz, ale tie by som sem neplietol.
Prajem uspesne prekonavania rozcarovani, ktore vzniknu z nenaplnenia ocakani a mylnych predpokladov zaciatocnika na nejakom jadre.
Preto tie naucene a zvladnute jadra tak neradi opustame.
Tiez by som nepredpokladal, ze k STR71x sa neda priamo pripojit Xtal, ale treba kupit a zapojit cely generator, cim okrem ineho stupne spotreba dvojice procesor - oscilator skoro na dvojnasobok.
Myslím ,že ani AVR32 nemají dělení, určitě je nemají ani signálové procesory, tedy alespoň ty menší. Ve skutečnosti ani není potřeba. Pro zpracování signálu vždy stačí součet a součin, zrovna tak pro grafiku. Ve svých aplikacích jsem je ani moc nepotřeboval a téměř vždy to jde obejít. Dělení konstantou je totéž co násobení převrácenou hodnotou a tu spočte překladač. Dělení je vždy zdlouhavé a má jeden problém, dělení nulou. Co s tím? Takže raději se ho vyhýbat, jako čert kříže.
Technik… ted si mi trošku rozjasnil… Styl jak si napsal příspěvěk mě tak trochu natrknul. Dělení přece jednoduše lze převést na násobení s číslem převráceným:
Y = A / B
to samé co
Y = A * (1/B)
Otázkou je, jestli to násobení a dělení 1 / B je rychlejší než když se použije rovnou jen jedno dělení, A/B. Toť otázka… Zvlášť jkeště když se budou používat desetinná čísla, ale to by nemělo být zas tak htrozné ne?
Potrebujem urobit delenie na MEGA328, mam cislo v premenej long pocitadlo
potrebujem urobit toto:
pocitadlo=553;
konstatnta=100/pocitadlo;// stym ze konstanta je double. Akosi mi to nefunguje vysledok v konstanta je 0
potom potrebujem pre zobrzenie
displey (pocitadlo*konstanta); displey pouziva long
Tak ze ako to urobit aby mi to pouzivalo desatiny.
Dakuejm
konstanta=100.0/pocitadlo;
nebo
konstanta=(double)100/pocitadlo;
Jde o to, ze 100 je int.