Fórum témák

» Több friss téma
Fórum » AVR - Miértek hogyanok
 
Témaindító: pakibec, idő: Márc 11, 2006
Témakörök:
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
Lapozás: OK   167 / 840
(#) toto válasza toto hozzászólására (») Nov 27, 2009 /
 
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.
(#) trudnai válasza toto hozzászólására (») Nov 27, 2009 /
 
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')...
(#) gtk válasza trudnai hozzászólására (») Nov 27, 2009 /
 
Nem ismerem a fuggvenyt,..Nem lehet benne valami float dolog, ami sokat foglal?
(#) gtk válasza toto hozzászólására (») Nov 27, 2009 /
 
z mikori avrlibc ? Rakd fel a legujabbat.
(#) gtk válasza toto hozzászólására (») Nov 27, 2009 /
 
+ az elozohoz: es linkeld hozza a libm libraryt. (persze hogy lebegopontos...)
(#) toto válasza gtk hozzászólására (») Nov 27, 2009 /
 
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)
(#) gtk válasza toto hozzászólására (») Nov 27, 2009 /
 
A lebegopontos kell, leirtam mit kell tenni.
Egeszre:

  1. int a;
  2. char str[16];
  3. a = 123;
  4. itoa(a, str, 10);
(#) trudnai válasza gtk hozzászólására (») Nov 27, 2009 /
 
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...
(#) toto válasza gtk hozzászólására (») Nov 27, 2009 /
 
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.
(#) toto válasza gtk hozzászólására (») Nov 27, 2009 /
 
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.
(#) toto válasza trudnai hozzászólására (») Nov 27, 2009 /
 
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?
(#) toto válasza gtk hozzászólására (») Nov 27, 2009 /
 
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?
(#) trudnai válasza toto hozzászólására (») Nov 27, 2009 /
 
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.
(#) ATtiny válasza toto hozzászólására (») Nov 27, 2009 /
 
Pozitív egész -> String konverzió. Remélem jó Most írtam 5 perc alatt.

  1. void uint_to_str(unsigned int szam, char* szoveg)
  2. {
  3.  unsigned int tmp = szam;
  4.  
  5.  while(tmp)
  6.  {
  7.   szoveg++;
  8.   tmp = tmp/10;
  9.  }
  10.  
  11.  *szoveg-- ='\0';
  12.  
  13.  while(szam)
  14.  {
  15.   switch(szam%10)
  16.   {
  17.    case 0: *szoveg-- ='0'; break;
  18.    case 1: *szoveg-- ='1'; break;
  19.    case 2: *szoveg-- ='2'; break;
  20.    case 3: *szoveg-- ='3'; break;
  21.    case 4: *szoveg-- ='4'; break;
  22.    case 5: *szoveg-- ='5'; break;
  23.    case 6: *szoveg-- ='6'; break;
  24.    case 7: *szoveg-- ='7'; break;
  25.    case 8: *szoveg-- ='8'; break;
  26.    case 9: *szoveg-- ='9'; break;
  27.   }
  28.   szam = szam/10;
  29.  }
  30. }



Így kell használni pl:

  1. unsigned int probaszam = 45487;
  2.   char probastr[20];
  3.  
  4.   uint_to_str(probaszam,&probastr[0]);
  5.   printf("%s\n",probastr);
(#) toto válasza trudnai hozzászólására (») Nov 27, 2009 /
 
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.
(#) gtk válasza toto hozzászólására (») Nov 27, 2009 /
 
Nem ertem mi bajod ezzel a "nem szabványos C" allapottal, nem akarsz leszallni rola
(#) toto válasza ATtiny hozzászólására (») Nov 27, 2009 /
 
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.
(#) toto válasza gtk hozzászólására (») Nov 27, 2009 /
 
Most már én sem értem, hogy mit nem értettem. Remélem, érted?
(#) trudnai válasza ATtiny hozzászólására (») Nov 27, 2009 /
 
Mondjuk akkor mar valahogy igy csinalnam, de persze izles kerdese:
  1. unsigned int probaszam = 12345;
  2. char probastr[20];
  3.  
  4. void uint_to_str(unsigned int szam, char* szoveg)
  5. {
  6.     char  tmp;
  7.     char* ptr = szoveg;
  8.    
  9.     // alakitsuk at a szamot
  10.     do {
  11.         *szoveg++ = '0' + szam % 10;
  12.     } while (( szam /= 10 ));
  13.     *szoveg = '\0';
  14.    
  15.     // forditsuk meg a stringet
  16.     for ( szoveg-- ; ptr < szoveg; ptr++, szoveg-- ) {
  17.         tmp = *ptr;
  18.         *ptr = *szoveg;
  19.         *szoveg = tmp;
  20.     }
  21. }

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)...
(#) niches hozzászólása Nov 27, 2009 /
 
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:
  1. PORTD|=0x01; // 0-ás bitet 1-re állítom
  2. PORTD&=~0x01; //0-ás bitet 0-ra állítom


Azt is láttam, hogy így is lehet:
  1. PORTD|=(1<<PIND0);

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?
(#) gtk válasza niches hozzászólására (») Nov 27, 2009 /
 
Van, bitmezo. Volt szo rola korabban.

  1. 1: PORTD|=(1<<PIND0);
  2. 0: PORTD&= ~(1<<PIND0);
(#) trudnai válasza niches hozzászólására (») Nov 27, 2009 /
 
Idézet:
„De ilyenkor csak 1-re sikerül állítanom, nullára hogy a viharba kell?”

  1. PORTD & = ~(1<<PIND0);

Vagy:
  1. PORTD |= _BV(PD0); // set bit 3
  2. PORTD &= ~_BV(PD0); // clear bit 3

(#) ATtiny válasza trudnai hozzászólására (») Nov 27, 2009 /
 
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.
(#) TyeDa hozzászólása Nov 27, 2009 /
 
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?
(#) vzoole válasza TyeDa hozzászólására (») Nov 27, 2009 /
 
Tegyél az ADC bemenetre egy feszültségosztót (2db ellenállás).
(#) trudnai válasza ATtiny hozzászólására (») Nov 27, 2009 /
 
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:
  1. struct str_t {
  2.     unsigned char len;
  3.     char str[1];
  4. };

...stilusban, bar felesleges erre strukturat definialni.
Ilyenkor az elobbi pelda ilyesmire modosulna:
  1. void uint_to_str(unsigned int szam, char* szoveg)
  2. {
  3.     char* ptr = szoveg;
  4.  
  5.     // alakitsuk at a szamot
  6.     do {
  7.         *(++ptr) = '0' + szam % 10;
  8.     } while (( szam /= 10 ));
  9.     szoveg[0] = (char)(ptr - szoveg);
  10. }
  11.  
  12. int main() {
  13.  
  14.     unsigned char i;
  15.  
  16.     uint_to_str(probaszam, probastr);
  17.  
  18.     // forditva, mondta a szamar orditva
  19.     for ( i = (unsigned char)probastr[0]; i; --i ) {
  20.         putchar( probastr[i] );
  21.     }
  22.  
  23.     return 0;
  24. }

(persze nem tudom mennyi teteje van ennek, ez csak az elmelet, hogy osszessegeben talan ki lehet alakitani kisebb kodot is ilyen trukkokkel)
(#) vzoole válasza TyeDa hozzászólására (») Nov 27, 2009 /
 
Itt van a program ahogy én használtam LCD kijelzőn.

És 2 példa 5 voltnál nagyobb fesz mérésére.
(#) TyeDa válasza vzoole hozzászólására (») Nov 27, 2009 /
 
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?
(#) trudnai válasza TyeDa hozzászólására (») Nov 27, 2009 /
 
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
(#) TyeDa válasza trudnai hozzászólására (») Nov 29, 2009 /
 
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.

12V_adc.c
    
Következő: »»   167 / 840
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem