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
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.
Jaj, tényleg! Amikor a B csatornát is bekötöttem teljesen elkerülte a figyelmemet. :bummafejbe:
Köszi!
É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ű...
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.
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.
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.
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...
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ő:
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.
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
Á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.
Ennek a sornak szerintem nincs értelme, amúgy sem ez kapcsolja be az időzítőt:
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
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.
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):
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!
Sajna már nem tudom szerkeszteni, egy "}" lemaradt az ISR rész előtt, ami a main() függvényt lezárja!
Köszönöm a választ, nagyon érthető volt.
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
Bocs hogy közbekotyogok, de egyrészt le is írja szövegesen, másrészt ha bemásolod talán válaszol valaki...
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.
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:
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?
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).
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!
Az a baj hogy nem nagyon tudom darabolni.
itt a kód, ahol a hiba jelentkezik.
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:
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...
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...
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...
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. |
Bejelentkezés
Hirdetés |