Fórum témák
» Több friss téma |
WinAVR / GCC alapszabályok: 1. Ha ISR-ben használsz globális változót, az legyen "volatile" 2. Soha ne érjen véget a main() függvény 3. UART/USART hibák 99,9% a rossz órajel miatt van 4. Kerüld el a -O0 optimalizációs beállítást minden áron 5. Ha nem jó a _delay időzítése, akkor túllépted a 65ms-et, vagy rossz az optimalizációs beállítás 6. Ha a PORTC-n nem működik valami, kapcsold ki a JTAG-et Bővebben: AVR-libc FAQ
levi18:
Most nézem csak a késleltetést. Amire te gondoltál, az nem a delay_ms() véletlenül? Mert amit használok az a util/delay.h-ban lévő _delay_ms() (aláhúzással indul!). Mintha ezzel már másodpercenként is villogtattam volna a ledet.
Vedd ki az egyik dtostrf() -et forditsd le, es mentsd el a .LSS file-t egy masik neven. Tedd vissza a dtostrf()-et, es megint forditsd le, es nezdd meg mi a kulonbseg a ket .LSS kozt! ('diff' parancs, vagy akar 'fc', de hasznalhatsz vizualis diff-et is, mint 'windiff' vagy 'kdiff3')...
Nem ismerem a fuggvenyt,..Nem lehet benne valami float dolog, ami sokat foglal?
+ az elozohoz: es linkeld hozza a libm libraryt. (persze hogy lebegopontos...)
A dtostrf függvény biztos sokat foglal, mert az első használatakor 1,8k-val növekedett a mem. foglaltsága.
Először sprintf()-et akartam használni, de a neten azt olvastam, hogy ez a dtostrf "lightweighted" vagyis rövidebb lehet. Ha valaki tud egyszerű vagyis rövid forrású lehetőséget arra, hogy egy int-et (tulajdonképpen 10 bites pozitív egész) string-gé (unsigned char*) átalakítsak, akkor az megoszthatná a tudását. trudnai: jó gondolat, csak még a különbségek értelmezéséhez nem érzem a kellő tudást. (Kapok egy nagy adag ömlesztett adathalmazt, amivel csak nézünk egymásra)
A lebegopontos kell, leirtam mit kell tenni.
Egeszre:
Van benne float, nade akkor is a floatos fuggvenyeket egyszer rantja be es utana mar csak hivatkozik ra -- elmeletileg. Gyakorlatban azonban optimalizal a fordito, meghozza rendesen -- nezzuk hogyan!
Leforditottam amugy a progit, az LCD cuccokat kiszedtem belole, es a forditas eredmenye, hogy a while-bol kivettem a hivast: Program: 1768 bytes (21.6% Full) Vissza teszem a while-on belulre is: Program: 2842 bytes (34.7% Full) A novekedes jelentos, tehat valami nagyon nem stimmel. Ossze hasonlitva a leforditott kodot latszik, hogy valoban a floatos rutinok a ludasa, de mi is tortenik valojaban? Mindket esetben a dtostrf() ugyanazokkal a parameterekkel vannak meghivva, egy nagy kulonbseg megis adodik. Meghozza az, hogy az elso esetben a fordito elore ki tudja szamolni forditasi idoben az elso floatos parametert, mivel hiaba hasznalunk valtozot, a fordito felismeri, hogy a valtozonak fix erteket adunk es a fuggveny hivasa kozott ez az ertek nem valtozhat. Azaz kioptimalizalja onnan a valtozot, konstansot helyez oda, kovetkezo lepesben meg eszreveszi annak bizony floatosnak kell lennie, tehat meg forditasi idoben azt oda fixen bele teszi. Masodik esetben azonban a cikluson belul valtozik az elso parameterkent atadott valzoto erteke, tehat nem tudja ezt az opptimalizalast tovabbra is fenntartani. Mivel a "value" valtozo int, ezert neki kell hozza egy float atalakito fuggveny is, es ezert rant be jo sok floatos rutint... A kod viszont ezekutan mar nem szabadna, hogy gyarapodjon sokat...
Azt hol tudom megnézni?
Az avrlibc a WinAVR részeként települhetett, mert külön nem raktam fel. A könyvtárakban egy ilyet találtam:C:\Program Files\WinAVR\source\avr-libc\1.6.6\ , amiben van 3 db .patch kiterjesztésű néhány kB méretű file.
Ezt ki fogom próbálni, de először megijedtem a használatától, mert nem szabványos C-s függvény, és a PC-s programozáskor valamelyik compiler (Visual vagy GCC, már nem emlékszem) pampogott, hogy nem tetszik neki.
Először float számot akartam kiírni, aztán közben rájöttem, hogy ki tudom kerülni, elég csak az int-et használnom, de ekkor már maradt a fv, mert működött -úgy ahogy.
Ez logikusan hangzik, és igazad van, a második dtostrf után már nem növekszik a kód.
Ha float-tal akarok számolni ilyen iszonyatosan növekszik a forrás mérete? Kipróbálom az itoa()-t és ha az jól megy, hagyom a fenébe ezt a fv-t. Bár ha később mégiscsak kellene valamit lebegőpontosan számolni, akkor megint ott vagyok, ahol a part szakad?
He-he. Én ezekhez a mélységekhez hülye vagyok.
Hozzálinkeltem a libm.a-t a projecthez, ahogy mondtad, és a 66%-ról 55%ra csökkent a programmemória használtsága, a regiszterek használata 75-ről 50%-ra csökkent! Még abban az avrlibc kérdésben segíthetnél. Mit és hol nézzem, hogy a legújabb van-e fent? Idézet: „Ha float-tal akarok számolni ilyen iszonyatosan növekszik a forrás mérete?” Igen, ezekben nincs floatos co-processzor! Mindent szoftveresen kell ezugyben megcsinalni. Idézet: „Kipróbálom az itoa()-t és ha az jól megy, hagyom a fenébe ezt a fv-t.” Jol teszed, az legalabb szabvanyos C-s megoldas... Idézet: „Bár ha később mégiscsak kellene valamit lebegőpontosan számolni, akkor megint ott vagyok, ahol a part szakad?” Igen, de azon raersz kesobb torpolni Meg hat ha int-es a valtozod miert is akarnal egy float-os atalakito fuggvenyt hasznalni? Tehat meg akkor is jobb az itoa ha amugy mashol meg hasznalsz floatosokat. Tehat megegyszer ami tortenik: Ha int-es valtozoval hivod a dtostrf()-et akkor elobb az intet atalakitja floatossa majd a floatost stringge... itoa() meg egylepcsoben csinalja meg ugyanazt, nem kell neki elobb floatossa alakitani. Magyaran meg akkor is ha a masodik dtostrf() utan nem novekszik a kod jelentosen, akkor is azert ennek a felesleges floatositasnak megvan a maga lenyomata, ami futas idoben is megmutatkozik es kodmeretben is, meg ha nem is olyan latvanyos mint a korabbi felfedezesek.
Pozitív egész -> String konverzió. Remélem jó Most írtam 5 perc alatt.
Így kell használni pl:
Az itoa tényleg szépen működik (bár én tényleg azt olvastam, hogy nem szabványos C, ami elriasztott).
A memóriafoglalás 35%-on van, ami remek, így a probléma megoldódott. Számomra is nyilvánvaló volt, hogy a floatos számítások jelentősen növelik a forráskód méretét, de a mértéke mégis meglepett. Bár valszeg e miatt az egy utasítás miatt be kellett linkelni majd az egész float-os könyvtárat, így további lebegőpontos számítás már nem növelte volna jelentősen a forrás méretét. Köszönet mindenkinek.
Nem ertem mi bajod ezzel a "nem szabványos C" allapottal, nem akarsz leszallni rola
Nem próbáltam ki, de értem az elvet.
Pofás megoldás, én is töprengtem hasonlón azzal a különbséggel, hogy ez nálam legalább egy órát vett volna igénybe. Nálam kb. 5 perc az volt, amíg felfogtam.
Most már én sem értem, hogy mit nem értettem. Remélem, érted?
Mondjuk akkor mar valahogy igy csinalnam, de persze izles kerdese:
Nyilvan ha nem std fuggvenyekkel dolgozzuk fel az atalakitott stringet, akkor akar a vissza forditot is elhagyhatjuk es null terminated helyett hasznalhatnank pascal stringeket is (csak eppen a string lenne avtidrof)...
Sziasztok!
Van valami más mód egyetlen pin értékének változtatására azon kívül, hogy maszkolok? Tehát így pl. működik:
Azt is láttam, hogy így is lehet:
De ilyenkor csak 1-re sikerül állítanom, nullára hogy a viharba kell? Illetve mit is jelent ez pontosan? Tudtommal a két kacsacsőr balra, az balra shiftelést jelent. Viszont ez esetben nem?
Van, bitmezo. Volt szo rola korabban.
Idézet: „De ilyenkor csak 1-re sikerül állítanom, nullára hogy a viharba kell?”
Vagy:
Igen, nekem is eszembe jutott utólag, hogy mivel az ASCII táblában a számok egymás után jönnek, így ezt ki lehetne használni, de már akkor el volt küldve a post. Az meg hogy az elején keressük meg hol lesz a str vége és onnan megyünk vissza felé, vagy utólag fordítjuk meg a sztringet már részlet kérdés A lezáró karaktert én nem spórolnám le egy konverziónál, ahol nem lehet tudni, hogy az eredmény milyen hosszú. Ha van lezáró nulla, akkor meg lehet spórolni a sztring helyének törlését. Ennyit bőven megér az az 1 plusz byte.
Sziasztok!
Nemrég kezdtem AVR-rel ismerkedni, suliban tanultam C-programozást PC-n, meg egy kis PIC-et. A következő projektben kérek segítséget tőletek: Atmega8 4db bemenetén van 0-5V feszültség, ezt kell kis átalakítással kiírnom LCD-re. 12V-os akkuk monitorozása. Szóval kb 0-20V tartomány. 'gtk' LCD driver-es cikke alapján már ki tudok írni a kijelzőre sztringet. EZT a programot implementálva 0-5V-ra kapok egy 0-1023 közötti integert. Ez nem a legjobb. Így kéne kinézni a kijelzőn pl: U1=12,23V... Tudnátok mutatni példaprogramot, ötletet, hogy induljak el? Hogy tudnám megjeleníteni ezt az LCD-n?
Tegyél az ADC bemenetre egy feszültségosztót (2db ellenállás).
A vissza forgatasosdit csak azert gondoltam, hog igy megsporoljak par 10-el torteno osztast -- bar lehet mindegy is -- hogy frappans legyek "nem oszt nem szoroz"
A lezarot amugy nem ugy ertettem, hogy elhagyjuk es semmi nincs helyette, hanem hogy pascal formatumban lennenek tarolva a stringek, tehat a legelso char az egy byte hogy milyen hosszu a string amit maga a string kovet:
...stilusban, bar felesleges erre strukturat definialni. Ilyenkor az elobbi pelda ilyesmire modosulna:
(persze nem tudom mennyi teteje van ennek, ez csak az elmelet, hogy osszessegeben talan ki lehet alakitani kisebb kodot is ilyen trukkokkel)
Itt van a program ahogy én használtam LCD kijelzőn.
És 2 példa 5 voltnál nagyobb fesz mérésére.
Köszönöm a választ! A feszültségosztó sima ügy, 10k:30k osztóval +20V mérhető. A progiba eddig én is eljutottam, kiír az LCD-re 0-1023 számot 0-5V-nak megfelelően. A számot tizedesjegyekkel szeretném kiírni pl. 12,43V. Ehhez 1024 állapot sztem kevés, nem elég pontos. Hogy lehetne nagyobb felbontást elérni, tizedesjegyeket kezelni?
20V/1024 = 0.01953125 ~0.02V - miert kell ennel pontosabb?
Amugy: 1. Hany szazalekos az ellenallasod? Mert ha csak nem valami precizios ellenallasod van akkor a meresed amugy sem lesz pontos 2. Mennyire preciz a referencia feszultseged? Mert ha nem valami extra preciz akkor nem lesz pontos a meresed 3. Milyen szuro aramkort teszel bele, hogy az elektromos es elektromagneses zajok ne befolyasoljak a merest? 4. Sokszor mersz, rateszel egy digit szurest + atlagolsz es kapsz egy eleg jo megkozelitest
Igaz trudnai, ennyi az ADC felbontása nincs mit tenni.
Az, hogy a bejövő feszültség mennyire pontos, az már a hardveres gondja (az is én vagyok, ez egy iskolai projekt, lehet, h a végleges megépítésre nem kerül sor, addigis dugdosós panelon van) Sikerült haladni a programban, a saját függvényem visszadja a mért akku feszültséget mV-ban, ezt osztom 1000-rel, az egész rész és a tört megy egy-egy tömbbe, amiket kiiratok az LCD-re, közéjük ','-t iratva. Azért így, mert csak egész számot sikerült stringgé konvertálni "itoa();". Elég nyakatekert a megoldás, nem vagyok programozó, félek, hogy nem fér bele a memóriába majd, most a négy ADC bemenet közötti lépkedést szeretném megírni. |
Bejelentkezés
Hirdetés |