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   459 / 840
(#) sgt válasza zombee hozzászólására (») Júl 20, 2012 /
 
Gondolkozom egy IDE fejlesztésen, de elég macerásnak tűnik, vagyis inkább hosszú ideig tartana, ahhoz hogy normális környezet legyen , mert tényleg nagyon bugos. Csak akkor van a baj, hogy ha nem csak az AVR Studio hanem az exe-k is bugosak.
(#) Robi98 válasza zombee hozzászólására (») Júl 20, 2012 /
 
Jaj, tényleg! Amikor a B csatornát is bekötöttem teljesen elkerülte a figyelmemet. :bummafejbe:
Köszi!
(#) zombee válasza sgt hozzászólására (») Júl 20, 2012 /
 
Én is gondolkodtam rajta, de elég összetett a dolog(C támogatás, makefile, kompatibilitás, AVR programozók).
Szerintem más is bugos, pl. WinAVR, szimulátor, programozó beépülők, stb. Egy natúr, C és ASM nyelv-el
bíró IDE-t el tudok képzelni, de a programozók támogatása biztos nem lenne olyan egyszerű...
(#) sgt válasza zombee hozzászólására (») Júl 20, 2012 /
 
Process monitorral megnéztem, hogy a C fordítás hogyan történik. A depend-re és a makefile generálásra nincs külön exe, azt a Studio csinálja, de azok nem olyan túl vészesek. A többire pedig vannak exe-k. Igazából ki kellene próbálni. Ha parancssorban az exe után írsz -h vagy --help-et valamelyik szokott működni, akkor egész jól leírja a kapcsolókat illetve, hogy mit is csinál. Ha ezek az exe-k nem nagyon bugosak, akkor is a rendes UI nagyon macera. Mert ha az ember bele kezd egy ilyenbe, akkor csak is jobbat kellene kreálni.
(#) blackdog hozzászólása Júl 21, 2012 /
 
Sziasztok!

Ha az AVR RX,TX lábát már használom RS485 kommunikációra akkor tehetek még hozzá RS232-t párhuzamosan? Természetesen a kommunikáció mindig csak az egyik kimeneten lenne.
(#) sikolymester válasza kiborg hozzászólására (») Júl 21, 2012 /
 
Ez azért van, mert a fordító nem fordítja újra azokat a fileokat, amik nem változtak. Tegyük fel, hogy van egy óriási projekted. No persze nem egy 8 bites AVR-rel, hanem mondjuk egy linux kernel méretű valami. Megjegyzem a GCC fordító ugyanaz mindkét esetben. Ha ott változtatsz egy sort az egyik C fileban, akkor várhatnál megint 30-40 percet egy kevésbé izmos gépen, amig lefordul az egész.

Emiatt nem dobja ugyanazokat a warningokat, mivel nem keletkeztek. Ha az egész projektet újrafordítod, akkor megint láthatod őket (make clean, utána build, vagy valami ilyesmi).

Persze el lehetne várni az IDE-től, hogy megjegyezze a korábbi warningokat, de ehhez már szerintem kellene egy-két patch a gcc-be is, hiszen az IDE nem tudja miért nem jön warning, gondolhat arra, hogy azért nem, mert most jól fordultak.
(#) sikolymester válasza sgt hozzászólására (») Júl 21, 2012 /
 
Most komolyan beszélsz?
Az előbb még nem tudtad, hogy hogyan működik a gcc fordító, és most már magad akarsz egy IDE-t írni?

Ott van az eclipse vagy a netbeans, amik remekül működnek. Szépen alátolod a gcc-t és megy is. Ha valami hiányzik írsz hozzájuk plugint.
(#) zombee válasza sikolymester hozzászólására (») Júl 21, 2012 /
 
Eclipse - lehet hogy alapból vele (is) van baj? Ugyanis nálam a szerkesztőablaknál fagy ki másolás/beillesztés alkalmával. A programozók támogatása sem hiszem hogy pár soros plugin beszúrással menne...
(#) Robi98 hozzászólása Júl 21, 2012 /
 
Sziasztok!
Megpróbáltam összetákolni egy programot, ami azt csinálja, hogy egy ATtiny45-ös ic PB0-ás lábára kötött LED-et másodpercenként villogtat, mégpedig TIMER0-ás számláló segítségével.
A fordító nem talált hibát a programban, de az eredmény mégsem jó: A led egyáltalán nem villog.
A program pedig a következő:
  1. //egy kis magyarázat:
  2. //F_CPU: 1000000 hz/255 előosztás=3921,5686
  3. //másodpercenként a timer 3921,5686/255=15,3787-szor csordul túl
  4. //a számlálás idelye 0-tol 255-ig : 1000/15,3787=65.025ms
  5. #include <avr/io.h>
  6. #include <avr/interrupt.h>
  7. int main(void)
  8. {
  9. DDRB|=(1<<PB0);//PB0 kimenet
  10. TCCR0B|=(1<<CS02);//255-ös előosztás
  11. TCNT0=0xFF;// TIMERT bekapcsoljuk
  12. TIMSK|=(1<<TOIE0);//enable interrupt
  13. sei();//interrupt bekapcs.
  14.  
  15. while(1)
  16. {
  17. volatile float x=0;//létrehozunk egy tört szám változót
  18.  
  19. ISR(TIMER0_OVF_vect);//túlcsorduláskor...
  20. {
  21. x++;//... a változót egyel növeljük
  22. }
  23.  
  24. if(x==15.3787)//65,025*15,3787=~1000ms
  25. {
  26. x=0x00;
  27. PORTB^=(1<<PB0);//a láb értékét felcseréljük
  28. }
  29.  
  30. }
  31. }
(#) sikolymester válasza zombee hozzászólására (») Júl 21, 2012 /
 
A programozókat illetően olyan nagy nehézségek nincsenek. Fel kell hívni az avrdude-t a fordítás után.

Ha minden igaz, akkor a $(TARGETNAME) makróval rögtön át is lehet adni avrdude-nak a használt mikrokontroller típust. De csodálkoznék, hogyha nem létezne már egy avrdude plugin eclipse-re.

A szerkesztőablak fagyás érdekes, főleg ilyen alap műveleténél.

De ha egy programozó beszúrása nem pár soros plugin, akkor végleg nem értem az ötletét sgt kollégának, hogy máris saját IDE-t akart hegeszteni.
(#) sikolymester válasza Robi98 hozzászólására (») Júl 21, 2012 /
 
Pedig ez csak matek. Egész számokat összeadva, mikor kapsz tört számot?

Mellesleg amúgy sem javasolt tört számokra == vizsgálatot tenni, mert a digitális processzorok érdekes módon kezelik a lebegőpontos számokat.

Nekem már volt olyan, hogy excelbe írtam egymás alá 50,49,48 -at, majd kijelöltem a 3 cellát és lehúztam mínusz 50 -ig. Utána csak néztem, hogy a függvénykirajzolásom teljesen elszállt a nulla pontnál. Történt ugyanis, hogy a 0 nem 0 volt, hanem 0,0000000000000000001 vagy valami ilyesmi. Pedig ez intel processzor + marha drága office csomag. Néztem is .

Tehát, használj >= operátort is, és lebegőpontos számoknál amúgy is mindig. Ezután már persze nem lesz igaz ez:
//65,025*15,3787=~1000ms
de ez van, meg kell oldani máshogy
(#) Robi98 válasza sikolymester hozzászólására (») Júl 21, 2012 /
 
Átjavítottam a programot, de így sem működik.
A led még így is teljesen sötét, pedig már működnie kéne.
  1. while(1)
  2. {
  3. volatile int x=0;//létrehozunk egy változót
  4.  
  5. ISR(TIMER0_OVF_vect);//túlcsorduláskor...
  6. {
  7. x++;//... a változót egyel növeljük
  8. }
  9.  
  10. if(x==15)
  11. {
  12. x=0x00;
  13. PORTB^=(1<<PB0);
  14. }
  15. // majdnem 1 másodpercet kapunk  
  16. }
  17. }
(#) zombee válasza Robi98 hozzászólására (») Júl 21, 2012 /
 
Ennek a sornak szerintem nincs értelme, amúgy sem ez kapcsolja be az időzítőt:
  1. TCNT0=0xFF;// TIMERT bekapcsoljuk


A törtszámozás alapból nem jó, interruptban főleg! De a programod is súlyos formai hibával is küzd,
én inkább azt nem értem hogy miért eszi meg a fordító. Hiba: a main függvénybe esik az ISR makró!
Az interrupt egy különálló függvény, azaz minden más függvényen kívül kell lennie. Mindjárt mutatok példát
(#) Ricsi89 válasza Robi98 hozzászólására (») Júl 21, 2012 /
 
Egy apró dolog. Az ISR rész mit keres a main-ben? És ha az x egész szám, akkor miért hexában nullázod? Ha azt írod, hogy x=0; akkor is nulla lesz.
(#) zombee válasza Robi98 hozzászólására (») Júl 21, 2012 / 2
 
Akkor folytatom, előtte még egy apróság: 255-ös előosztó nincsen, csak 256. És még 1,8,64,1024.
Jó tudni hogy az előosztó beállításával indítod el az időzítőt is, a TCNT0-t ne bántsd!

Gondolom az kell neked hogy 1 másodpercenként váltson állapotot a LED, méghozzá pontosan.
Előtte egy kis elmélet hogy megértsd a programot amit most írok neked.
Abból induljunk ki hogy 1MHz-en megy a procid. Fent már felsoroltam az előosztókat, közülük a 64
a legnagyobb, amivel a frekit osztva még egész számot kapunk. Ez 15625 lesz. De ááácsi!
A 15625 Hz az a freki amivel a számláló lép 1-et, és nem az interrupt gyakorisága! Utóbbi 15625/256 lesz.
Talán már látod, hogy ha az előosztónak 1-et választasz, az interrupt 3906.25Hz-es lesz. Ez se jó.

Gondolom a fentiek alapján már látod, hogy még 1-es előosztóval sem lesz az igazi,
ha továbbra is a túlcsordulás interruptot akarod használni az időzítő normál módjában.
Én már kissrác koromban megtanultam a CTC alapjait. Igaz, akkor még nem így hívtuk de ez részletkérdés.
A CTC alapja hogy beállítasz egy számot, amit ha elér az időzítő, lenulláz, és még interruptot is generál!
Induljunk ki az 1000000/64=15625-ből! Ez ugye a számláló frekije(és nem az interruptodé).
Erre kell valami egész osztó. Lehetőleg 1-256 között, hiszen a számlálód 8 bites. Hasraütésre nekem
se megy, de azt Te is láthatod, hogy az 5 hatványaival rendesen osztható, nem is akárhogy: 15625=5^6.
Azaz 125*125=15625. Ebből kell kiindulni. Először is, lesz egy interruptunk ami 125Hz-es gyakorisággal
hívódik meg, és lesz ezen kívül egy 8 bites számlálónk ami ha eléri a 125-öt, megváltoztatja a LED állapotát.

És akkor íme a kód ami ezt az elvet alkalmazza(bocs, nem teszteltem):
  1. //F_CPU: 1000000, 64-es előosztással 15625Hz
  2. //timer CTC módban: 15625Hz/125=125Hz - interrupt gyakorisága
  3. #include <avr/io.h>
  4. #include <avr/interrupt.h>
  5.  
  6. uint8_t x = 0;
  7.  
  8. int main(void)
  9. {
  10.     DDRB  = (1<<PB0);   //PB0 kimenet
  11.     OCR0A = 124;        //125-1
  12.     TCCR0A = 1<<WGM01;  //CTC mód(OCR0A elérésekor lenulláz)
  13.     TCCR0B = (1<<CS01)|(1<<CS00);  //64-es előosztás, időzítő indul!
  14.     TIMSK|=(1<<OCIE0A);            //enable interrupt(OCR0A elérésekor)
  15.     sei();                        //interrupt bekapcs.
  16.    
  17.     //innentől már az interrupt dolgozik!
  18.     //...
  19.  
  20.     while(1)
  21.     {
  22.         //...
  23.     }
  24.  
  25. ISR(TIM0_COMPA_vect);    //interrupt
  26. {
  27.     if(++x == 125)
  28.     {
  29.         x=0;
  30.         PORTB^=(1<<PB0);  //a láb értékét felcseréljük
  31.     }
  32. }


Még egy apró megjegyzés: láthatod hogy az "x" itt nem volatile.
Csak akkor kell volatile ha interruptban ÉS főprogramban egyszerre használod,
illetve ha két vagy több interrupt használja közösen(pl. Rx/Tx ringbufferek).
Ha az x változót a main-ből is birizgálni akarod akkor volatile, egyébként felesleges!
(#) zombee válasza zombee hozzászólására (») Júl 21, 2012 /
 
Sajna már nem tudom szerkeszteni, egy "}" lemaradt az ISR rész előtt, ami a main() függvényt lezárja!
(#) Robi98 válasza zombee hozzászólására (») Júl 21, 2012 /
 
Köszönöm a választ, nagyon érthető volt.
(#) kiborg válasza sikolymester hozzászólására (») Júl 22, 2012 /
 
Köszi az infót.
Annak hol lehetne utánanézni, hogy melyik warning mit is jelent? Amit ott leír, az kezdő C-s tudásomnak magas.
Üdv Kiborg
(#) zombee válasza kiborg hozzászólására (») Júl 22, 2012 /
 
Bocs hogy közbekotyogok, de egyrészt le is írja szövegesen, másrészt ha bemásolod talán válaszol valaki...
(#) ZLED hozzászólása Júl 22, 2012 /
 
Sziasztok!

Miért van az hogyha 64bites vagy olyan változót ami 2^32-nél nagyobb számot tud kezelni akkor a flash memória és a ram majdnem 100%-ra elszáll, még akkor is ha csak 1 ilyen változó van a programba. Atmega8-ra írtam egy progit ami kb 1,6kB-ot foglal de amint belekerül egy ilyen változó már 6-7kB-ot foglal. Valaki tudja miért van ez?
A programot AVR studio-ba írtam C-be.
(#) mzozo95 válasza ZLED hozzászólására (») Júl 22, 2012 /
 
Ilyen gondom nekem is volt, 2^16 feletti számoknál furcsa dolgokat csinál az avr, próbáld "szétdarabolni", vagy máshogy kezelni a dolgokat. PL késleltetés is nagyon sok helyet foglal, ha a késleltetett időt változókkal tárolod(pl delay_ms(a), de ha írsz egy függvényt, ami így nlz ki, akkor kevés helyet foglal:
  1. void delay_100us(uint16_t delay_data) {
  2.          while(delay_data--) _delay_us(100); }
(#) mzozo95 hozzászólása Júl 22, 2012 /
 
Nem tudja valaki, hogy egy uart interrupt lefutása annyi időt vesz igénybe, mint a beérkező bájt fogadási hossza+ az interruptban lévő műveletek, vagy csak az interruptban lévő műveletek lefutási ideje?
Olyan érdekes dolgot már tapasztaltam, ha éppen fut ez az unterrupt, de közben jön egy másik bájt, akkor azt gond nélkül lefuttatja az avr egy következő interruptban, így arra következtettem, hogy csak a számítások idejét kell figyelembe venni ilyenkor.
Helyesen gondolom?
(#) zombee válasza mzozo95 hozzászólására (») Júl 22, 2012 / 1
 
Az Rx interrupt a stopbit közepén-végén hívódik meg, lényeg hogy csak akkor amikor már ki lehet olvasni.
Ezt addig ki tudod olvasni(x=UDR), amíg a következő bájt teljes egészében meg nem érkezik.
Tehát ha már a következő bájt beérkezése alatt olvasod ki akkor nincs baj(a kettőt külön buffereli),
de ha már arra is hívná a következő interruptot akkor beszélünk ráfutásról, ami adatvesztést jelent.

A Tx oldalon is hasonló, az éppen küldött adat és a kimenő buffer külön tároló, ezért,
amíg küldi ki a bájtot a Tx csatornán, már írhatod bele a következőt(ha az UDRE flag aktív).
Azaz az UDR kezelése összesen 4 bájtnyi adatra van hatással(2-2 a küldő és fogadó oldalon).
(#) zombee válasza zombee hozzászólására (») Júl 22, 2012 / 1
 
Ezért az interruptod ne legyen hosszú, ajánlott 1-2 bitidőnél kisebbre méretezni.
Ha nem megy(pl. sztringkonverzió miatt) akkor be kell tenni egy tömbbe, amit a proci később feldolgoz.
Vagy tegyél rá nagyobb kristályt, márcsak azért is mert nagysebességű(28kbps felett)
UART kommunikációhoz elengedhetetlen egy BAUD kristály használata!
(#) ZLED válasza mzozo95 hozzászólására (») Júl 22, 2012 /
 
Az a baj hogy nem nagyon tudom darabolni.
  1. void Henry(uint32_t freq) {
  2.  
  3. char *units[3] = { " uH", " mH", " H " };
  4. float numerator = 1e10;
  5. unsigned char unit_type = 0;
  6.  
  7. numerator = numerator/(628*freq);
  8. numerator = (numerator * numerator) / 3;
  9.  
  10. while(numerator > 99999 && unit_type < 2) {
  11. numerator = numerator / 1000;
  12. unit_type++;
  13. }
  14.  
  15.  
  16. LCDGotoXY(0, 1);
  17. Numtostring(((uint32_t)numerator / 100) % 1000, 3);
  18. LCDsendChar('.');
  19. Numtostring(((uint32_t)numerator) % 100, 2);
  20. LCDstring(units[unit_type]);
  21. }


itt a kód, ahol a hiba jelentkezik.
(#) zombee válasza ZLED hozzászólására (») Júl 22, 2012 /
 
Az a baj hogy ezt mi nem nagyon tudjuk ellenőrizni mivel hiányzik a kód többi része, nélkülük nem fordul le.

Pár tippet azért adnék. Igaz, számolni is kell hogy mi mennyi lehet de azért egy kis optimalizálással
a program kevesebb bitszám mellett is tökéletesen működhet!

Először is, több helyen látom hogy először szorzol aztán le is osztod. Ha először osztanál és utána szorzol, lehet hogy 16 biten is elfér a változód. Szintén szorzás-osztáshoz kapcsolódik, ha egy osztás nevezőjében szorzol az szintén pazarlás (processzoridővel is), ott ossz le egymás után a két értékkel!
Aztán két egymás utáni műveletnél is lehet gondolkodni hogy lehet optimalizálni.


Illusztrálom:
  1. numerator = numerator/(628*freq);
  2. numerator = (numerator * numerator) / 3;
  3. //helyett:
  4. numerator /= freq;
  5. numerator /= 1088;
  6. numerator *= numerator;


Magyarázat: 1088~= 628*gyök(3).
A második műveletnél először négyzetre emeltél és utána 3-al osztottál. Tehát az "eredeti" értékben
már ott volt a gyök(3), de csak úgy nem oszthatsz le gyök(3)-al, mert ez egy nagyon kicsi tört szám.
De ha már ott volt a 628-al való osztás, ez simán kapóra jön ahhoz hogy a gyök(3)-at kivedd belőle.
Eredmény: a végén(négyzetre emelés után) nem kell 3-al osztani, nagyobb eséllyel bennmaradhat
a 16 bites korlátban. Valószínű hogy csak papíron fog látszani, miért lesz ugyanaz az eredmény...
(#) kiborg válasza zombee hozzászólására (») Júl 22, 2012 /
 
Igazad lehet Majd megpróbálom úgy.
(#) sgt válasza sikolymester hozzászólására (») Júl 23, 2012 /
 
IDE != gcc. IDE része a gcc, de az nem csak abból áll.

Azokkal a környezetekkel az a probléma, hogy nem AVR specifikusak. Tudsz benne írni C-ben, és eltudod fordítani. Viszont nem tudod felprogramozni, fuse biteket állítani, asm-ben írni, online debuggolni, nem tudod szimulálni stb...
(#) mario1111 hozzászólása Júl 23, 2012 /
 
Sziasztok!

ATXMEGA192A3-al és ATXMEGA256A3-al szívok.
A gondom az, hogy 192-esről 256-osra váltottam. Ezt a projekt beállításainál is módosítottam. De ha 256-ra van állítva, akkor elszáll a program. A hiba akkor következik be amikor int-é akarok egy double-t kasztolni. Ha visszaállítom 192-re, akkor azt letöltve a 256-osra jó lesz. WINAVR-t használtam. Most felraktam a avrtoolchain-t és azzal próbáltam. Ott mindkettő projektbeállítással elszáll. Azt is megtaláltam, hogy csak akkor halálozik el, amikor egy globális változóba kasztolok. Ha a függvényben hozom létre a változót, akkor abba bele tudja kasztolni, de ha átadnám a globális változómnak ebből az átmeneti változóból, akkor is fagy. Próbáltam már volatile-ként is... Agyvérzés...
(#) sgt válasza mario1111 hozzászólására (») Júl 23, 2012 /
 
Szia!

Implicit vagy explicit?

Volatile-al csak azt mondod meg a compilernek, hogy az ő tudta nélkül is változhat a változó értéke.
Következő: »»   459 / 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