Počítání v long – Mikrokontroléry – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Počítání v long – Mikrokontroléry – Fórum – Programujte.comPočítání v long – Mikrokontroléry – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
Boblig0
Newbie
2. 1. 2014   #1
-
0
-

Čau, potřebuju na osmibitovém up počítat poměrně velká čísla, ale bohužel výsledkem je nula i přesto, že po přetypování do long by se vejít měl, protože nejvyšší hodnota, která může při výpočtu nastat je 32768E4 což je 29 bitů, ale zdá se, že se přes ty hausnumera v mezivýpočtech nedokáže překlenout.  Na vstupu mám 16-bit číslo, to vynásobit konstantou 5000 a vydělit 65536. Je to externí A/D převodník. Nevěděl by někdo nějaký algoritmus jak na to? díky 

ADH=179; // hornich 8 bitu
ADL=87; // spodnich 8 bitu

vysledek = (long) ((256*ADH+ADL)*5000)/65536;

Nahlásit jako SPAM
IP: 89.102.186.–
KIIV
~ Moderátor
+43
God of flame
3. 1. 2014   #2
-
0
-

no mozna bych doporucil zkusit konstanty s L suffixem a pretypovat kazdou promennou zvlast

a overit si, jestli neni long jen 16b... pak by se tezko posunem o 16b dostalo neco vic nez nula

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
3. 1. 2014   #3
-
0
-

Kvůli rychlosti bych udělal ADH<<8 | ADL. Překladač pravděpodobně zoptimalizuje tak, že ADH přímo načte do horního byte a ADL do dolního byte, tedy proběhnou jen přesuny v paměti (EW8051 od IAR Systems nebo Keil u-vision to tak dělají). S algebrou bys asi tuto úrověň optimalizace nedosáhl. Je dobré se občas podívat, co s tím překladač udělá a znát dobře jádro procesoru na kterém děláš. Více o psaní optimalizovaného kódu pro jednočip najdeš v Application Notes např. u Atmelu. Není od věci se podívat i na stránky výrobce překladače, najdeš tam často tipy a triky a rady jejich expertů. Navíc algebra bývá na jednočipech pomalejší (třeba u 8051). Dále si myslím, že celočíselná algebra zde nebude to pravé. Výsledek by měl být z rozsahu 0 až 5000. Asi bych spíš volil float, jinak ztrácíš rozlišení.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Boblig0
Newbie
3. 1. 2014   #4
-
0
-

Mám Atmegu16, takže ta by 32bit na long umět měla. Nicméně sem narazil na jeden zajímavý problém a tím bude zřejmně to dělení, protože, když zadám výpočet

ADH=3;
ADL=251; //AD=1019
vysledek = (long) ((ADH<<8|ADL)*50);

tak vysledek je 50950 proti čemuž se nedá nic namítnout, ale..
pokud to na závěr vydělím, třeba desítkou tj. vysledek = (long) ((ADH<<8|ADL)*50)/10;

vysledek je již 64078 což je naprosto zcesné a to nepřekročím ani 16 bitů.

Nahlásit jako SPAM
IP: 89.102.186.–
Řešení
3. 1. 2014   #5
-
0
-
Vyřešeno Nejlepší odpověď

Pozor na signed a unsigned... ono signed má poloviční rozlišení, takže 16 bitů umí -32 768 až +32 767. Navíc výstup z ADC bývá často jinak kódován než signed hodnota v C. Dále pokud používáš ADC na čipu a Atmel Studio, měl by jít přečíst přímo jako 16-bitový (když to šlo s časovačem s AD převodníkem by to mělo fungovat taky).

Zkus pracovat s unsigned long:

vysledek = ((unsigned long) ADH <<8 | (unsigned long) ADL) * 50 / 10;

hu

Nahlásit jako SPAM
IP: 195.178.67.–
3. 1. 2014   #6
-
0
-

U Atmel Studia (asi ho v tomto případě používáš) se uvádí int 16 bitů a long 32 bitů.

int a long bývají defaultně signed. Představ si, že máš int a v něm -1. Ta bude reprezentována jako 0xFFFF. Tuto hodnotu nacpeš do long. Po takovém přetypování pak bude reprezentována jako 0xFFFFFFFF.  Je dobré se podívat na hexadecimální i dekadický (= jak je interpretován) obsah proměnných. Dále je důležité, jestli převodník pracuje v bipolárním (napětí na vstupu +/-) nebo unipolárním (jen kladné napětí) módu. Způsob, jakým s hodnotou pracuješ, odpovídá unipolárnímu módu. Pak musíš použít vhodné datové typy aby nedocházelo k dezinterpretaci např jako záporné číslo.

Pro bipolární mód k tomu musíš přistoupit trochu jinak. Převodník 16 bitů bude se znaménkem dávat toto:
plné záporné napětí   0x0000
0V 0x8000
plné kladné napětí  0xFFFF

Od hodnoty z ADC přetypované na long (rozuměj signed long) odečíst 0x8000. Teprve nyní máš signed hodnotu odpovídající napětí na vstupu.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Boblig0
Newbie
5. 1. 2014   #7
-
0
-

#6 hlucheucho
Díky za vyčerpávající odpověď, už to jede, ten problém byl v tom, že sem neměl obojí přetypovaný zvlášť jak to uvádíš, to unsigned mě pak taky napadlo, ale to už tu ten příspěvek byl. Každopádně díky za řešení. Jinak je to externí 16bit ADC čtené po SPI.

Nahlásit jako SPAM
IP: 89.102.186.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 3 hosté

Podobná vlákna

Tisk long long int — založil Tereza

Long double — založil akoze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý