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
Tehát be kellene vezetni egy segédváltozót, amit vizsgálsz és léptetsz, majd az OCR1A regisztert ezzel teszed egyenlővé.
Vagy kiszámolod, mennyit kell várni, mert ugye a timernek a frekvenciája adott .
Egy kis pontosítás.
Nem tudom melyik AVR-t használod, így feltételezem, hogy a méltán kedvelt atmega8-at. Az adatlapból kiolvasható, hogy az általad használt fast pwm módban az OCR1x regisztert, akkor növeli, amikor a TCNT1 0-nál van. Ezt tehát érdemes bekalkulálni az egész elképzelésbe. És ismétlem, hogy rajzolj idődiagrammokat. Ilyen kis fűrészfog alakú valamik lesznek. Ha egymás alá rajzolod, akkor valami olyasmit látsz, amit a mellékelt móricka ábrámon láthatsz. Hadd hangsúlyozzam ki, hogy direkt ilyen paint gányt rajzoltam. Ha felrajzolod az eredeti programod, akkor kapásból látod, hogy a fényerőváltoztatásod eredetileg olyan gyors volt, hogy a szem nem láthatta. A 3mp-es delayeddel pedig tényleg várhatsz rá órákat. A programozás mindig egy kis tervezéssel kezdődik. Rajzolgatsz, számolgatsz excelben, majd miután tudod merre hány méter, megvalósítod. A számolgatás végeredményben itt pl arra kell, hogy a pwm 50 Hz felett legyen, a fényerőváltoztatás pedig pár Hz körül.
Sziasztok!
Van egy Thunderbird fejlesztőpanelem és kiegészítő boardja. A probléma a következő: Assemblyben akarok beolvasni a billentyűzetről, de valamiért az 'stennek se akarja beolvasni... Se interruptban, se végtelen ciklusban nem lehet kezelhetően beolvasni vele: az 1 2 3 gombot még beolvassa, de ha a következő sorra akarok ugrani ott már hibázik. Ha JTAG-gel végig lépkedem a sorokat, rendesen beírja... Most ami ide be van másolva, az azt csinálja hogy ha nyomkodom az 1 2 3 gombot akkor a másik digiten is egy időben ugrál a 4 5 6...Eddig sehogy se tudtam mindegyik sort ezzel az algoritmussal beolvasni. Ötlet?
Sziasztok!
Összeraktam egy RFID olvasót ID-12-vel, ami ABA Track 2 interfészen küldi az adatot az AVR-nek. Az órajel az AVR D2-es lábára érkezik, amivel az INT0 megszakítást váltja ki (egy olvasás alkalmával 106-szor). Az interfészen 5 bites csomagok érkeznek, ezért úgy gondoltam, hogy a 106. megszakítást felesleges lekezelni és így ki is jön a szabványos adatcsomag(pl.: a konzol első sora): 00;kártyakód?ellenőrzőkód00 . Ha elkezdem feldolgozni a kapott adatot a 106. megszakítás előtt, akkor az első olvasáskor kapott adat jó, de az utánna lévők nem(viszont egyformák). Szerintem a 106. megszakítás is lefut a tiltás és a 63ms-os várakozás ellenére is(a 330us-os periódusidő sokszorosa), ez debuggolás közben be is bizonyosodott. Ha kivárom a 106. megszakítást és egyszerűen nem foglalkozom az ehez tartozó bittel, akkor mindin jól működik. A kérdésem az, hogyan lehet, hogy lefut egy megszakítás, amikor az összes megszakítás le van tiltva?
Őszintén szólva én nem vagyok az assembly nagy ismerője, így nem tudom mi történik és mi nem.
De a kérdésem azért a következő: A gombok beolvasásánál gondoltál arra a jelenségre, amit pergésnek hívnak? Nem lehet, hogy ez okozza a gondod? A Jtag léptetésnél nyílvánvalóan nem lenne pergés, mivel egy-egy lépés között eltelhet pár tized másodperc.
Gondoltam a pergésre igen. ezt pl úgy küszöböltem ki, hogy csak minden 300ms-ban olvastatom be a lábakat(addig meg csak elmúlik a tranziens). És így is...
Most olvasom, hogy a portc-vel gondok vannak, ennek kell utána néznem. Jut eszembe: amikor a jtag-et léptetem, akkor is magát a gombot használom, tehát megnyomom. És Azért sem lehet a pergés jelenségének tulajdonítani, mivel ha nagyon sokszor frissítem az állapotot, kvázi 10ms-onként, akkor is ugyanazt az értéket kellene beolvasnia...
No, de a JTAG interfész viszoont PortF-re kapcsolódik, tehát ez már nem lehet hiba...
Na, azt hiszem megértettem a kódod.
Nos, az észrevételek: Mindent interruptban csinálsz, ez ne váljon rossz megszokássá. A ClearBuffert nyugodtan deklarálhatod static inline függvénynek is. "Szerintem a 106. megszakítás is lefut a tiltás és a 63ms-os várakozás ellenére" Ezt, hogyan kell érteni? A delay-t végzi éppen, és beugrik megint az INT0 interruptvektorra?
Én csak a végeredményt láttam: ib=6, it=1, iB=0, tehát a ClearBuffer() után lefutott még egyszer az INT0. Ebből arra következtettem(feltéve, hogy az órajel után egyből indul az újabb megszakítás), hogy az adatküldésnek le kellett futnia 330us alatt, ami 9600 b/s sebességgel lehetetlen. Ezért szerintem a 106. megszakítás akkor hívódik meg, amikor újból engedélyezem a megszakításokat, addig mintha várakozott volna.
Megtaláltam a megoldást, az EIFR regiszterben kellett törölni az INT0-hoz tartozó bitet. Nem gondoltam volna, hogy nem csak a globális, de az INT0 interrupt kikapcsolásával is felhúzza a zászlót.
Köszönöm a pontosítást.
Kijavítottam a programot, de a LED még mindig csak világít. Most már tényleg nem tudom, hogy mi lehet a hiba.A kódban csak akkor változtatom az OCR1A értékét ha a timer counter regiszter(TCNT1)értéke 0. Amúgy tényleg az ATmega8-at használom.
Egy dolog az, hogy mit akarsz az 1-es timerrel, amikor a 2-es timer a pwm. Másrészt a timer folyamatosan fut, tehát annak az esélye, hogy pont akkor lép a programod az if-es részhez, amikor pont nulla, elég kevés az esély. Az az if-es rész nem kell, hagyd meg a 100ms-os várakozást és lehet, hogy működni is fog.
De hát ezt nem értem.Ha az OCR1A regisztert csak akkor lehet módosítani amikor a timer értéke 0, akkor csak kell legaláb annyi, hogy TCNT2=0 a módosítás előtt.
Bár kipróbáltam, de így se működött.
Kevered a két timert... OCR1A a Timer1-é, míg a TCNT2 a Timer2-é.
Ez így fullosan működik, de ATmega16A-ra készült, nem ATmega8-ra.
Sziasztok!
Egy olyan kérdésem volna, hogy PWM szabályozást valósítok meg, és ebben az esetben az Interrupt Registerrel mire való? Üdv.:Gergő
Köszönöm!
Ez a kód már tényleg működik, csak annyit módosítottam rajta, hogy 100ms késleltetést 8ms késleltetésre állítottam és az OCR2 regiszter kezdőérték 0 legyen.Így már a szemnek is előnyösebb. Csak azt szeretném megkérdezni, hogy timer1-el miért nem lehet PWM-ezni, ugyanis EBBEN a cikkben a timer1 A és B csatornájával vezérlik a motorokat.
Attól függ.
Van un. hardveres PWM, meg szoftveres PWM. Előbbinél beállítasz mindent, majd "hátradőlsz" és elintézi magától a dolgokat. Az inicializáláson kívül tehát a füled botját sem kell mozdítani. A szoftveres tehát mire való? Ha pl. nem elég neked egy AVR által nyújtott 2-3 hardveres PWM. Ekkor szoftverből kell elintézni a dolgokat. Monjduk, ha szeretnél egy 70%os kitöltöttségű jelet, akkor így jársz el: A compare interruptot beállítod a számláló 70%-ra. Amikor belép ebbe az interruptba, akkor kikapcsolod a LED-et. A timer túlcsordulás interruptban pedig visszakapcsolod.
Hogy ne lehetne!
Meg is írtam secc-pecc Atmega8-ra. Biztos, hogy működik, mivel itt villog mellettem. Mindkét csatornát használja, míg az egyiket lefele, a másikat felfele lépteti. Ugyanez a a hatás lenne elérhető, hogyha az egik invertáló, míg a másik nem invertáló lenne. Ugyanakkor remekül látszik működése közben, hogy a LED jó gyorsan megközelíti fényereje csúcsát.
Igazából nem tudom miért írták ezt.
Sajnos készülj fel, hogy lesznek még ilyen hülyeségek, más perfiériáknál is , és ez mikrokontroller független. Mindenféle fajta mikrokontrollernek a perifériájának meg vannak a saját hülyeségei, ami ilyen piti példákban jönnek elő. Majd idővel, amikor többet gyakorolsz, akkor rögtön fognak jönni az ilyenek. Szval fel a fejjel, és csak ügyesen .
Idézet: „Igazából nem tudom miért írták ezt.” Most mire gondolsz, amit írtak? Azt, hogy a Timer1 A,B csatornájával vezérelnek motorokat?
Értem.
Amúgy egy AVR32 UC3B1256-ot programozok. Egyenlőre egy spi kommunikációt valósítottam meg rajta spi.h header file-al. Most néztem egy pwm.h-t de nincs külön leírás a channel_t beállításaihoz és nem tudom hogyan kéne beállítani pl a channel alignment stb. Tudsz esetleg mutatni egy mintaprogramot vagy valamit amiből elindulok? Üdv.:Gergő
AVR Studioban: File->New->AVR Example Project
Itt az AT32UC3B0256 listajat bontsd ki es lesz egy ilyen lehetoseg: EVK1101 - DRIVERS - Pulse Width Modulation (PWM) example. A 32 bites avr-ek headerjei altal mashogy lehet elerni a periferiakat, mint ahogy a 8 bitesnel megszoktad. Itt minden strukturakba(a sorszamozott periferiak/regiszterek, tehat ami egyforma de tobb van, azok tombokbe) van rendezve. A strukturan beluli kis betus elemek az adatlapban megtalalhato regiszterekre mutatnak es mindegyik uint32_t tipusu. Peldaul az avr32_pwm_channel_t tipus ccnt eleme az adatlapban 547. oldalon talalhato CCNTx regisztert kepzi le. A cupd az 548. oldalon talalhato CUPDx regisztert kepzi le, es igy tovabb. A nagy betus elemek szinten regiszterekre mutatnak, de ezek nem uint32_t tipusuak, hanem strukturak. Ezekben a strukturakban a regiszter bitjei vagy bitmezoi vannak lekepezve az elnevezesuk szerint. Peldaul az avr32_pwm_channel_t tipuson belul talalhato CMR elnevezesu struktura (melynek tipusa avr32_pwm_cmr_t) az adatlap 543. oldalan talalhato regisztert kepzi le es a strukturan beluli peldaul cpol az adatlapban is lathato CPOL bitet jelenti. Tehat ha a gyari fuggvenykeszletet hasznalva szeretned a csatornat konfiguralni, akkor deklaralnod kell egy valtozot es azt feltolteni:
Termeszetesen, ha az init utan irod at a pwm_ch valamelyik elemet, akkor annak nem lesz hatasa. Ha a uC valamelyik regiszteret vagy regiszterenek a bitjet el szeretned erni, azt is megteheted. Peldaul a cpol bitet a 0-as csatornan kozvetlenul igy lehet allitani:
Tovabba: a strukturak konnyu felterkepezesehez: Irjad be peldaul, hogy AVR32_PWM. es a pont leutese utan tartsd lenyomva a shift billentyut. Ekkor felugrik egy legordulo menu, amiben a struktura elemei vannak felsorolva. A Timer/Counter modulhoz az AVR32_TC tartozik, az SPI-hez az AVR32_SPI, es igy tovabb.
Szia!
Teljesen még mindig nem értem sajnos. Mellékelek egy képet a programom részletéről. Elsőnek a pwm_options_t struktúrát beállítom, azzal elvileg nincs baj. Aztán beállítom a pwm_channel_t és pwm_cmr_t -t. A két bekeretezett rész arra utalna, hogy teljesen mindegy melyik módon írom igaz, ugyanazt jelenti? A problémám azzal van, hogy a pwm_channel_init() parancs behozása fogja konfigurálni a pwm-et jól gondolom? És ide a pmw_channel_t struktúrát írom be, de azzal önmagában a CMRx regiszter nem konfigurálom. Viszont ha például .CMR.cpol=1 -et vagy bármi mást írok a channel-hez azt nem fordítja le (pl a képen is látható). /remélem érthető a problémám.../ Üdv.:Gergő
avr32_pwm_cmr_t -t nem kell kulon csinalnod, mert az megvan az avr32_channel_t -ben is.
Igy kene:
Szerintem te felreertetted egy kicsit amit mondtam. Ha csinalsz egy static const -kent egy valtozot a csatornanak, akkor az nem fog a regiszterre mutatni. Csak ugyan olyan lesz a strukturaja. Ha te az ott megadott erteket szeretned beleirni a regiszterekbe, akkor kell csinalni egy
ertekadast. A regiszterekre konkretan az AVR32_PWM strujkura mutat, a channel regiszterekre konkretan az AVR32_PWM.channel[] tomb mutat. de a te pwm_ch valtozod es a static const-kent deklaralt PWM_CHANNEL valtozod sem mutat oda. Csak ugyan az a tipusuk igy ertekadasra hasznalhatoak.
Sziasztok!
Most írtam egy kódot aminek az lenne a feladata, hogy bekéri egy potméter értékét és átadja az OCR1A regiszternek.Tehát amikor tekerem a potmétert a LED fényének is úgy kéne nőni/csökkenni ahogy én azt tekerem.A kódot többször is átellenőriztem, de se a fordító, se én nem találtam benne hibákat.A ved pedig aminek világítani kéne abszolút nem világít. Itt a kód:
Látom nem adod fel . Nagyon helyes. Ezzel én is próbálkoztam még tavaly, de nem sok sikerrel.
Hirtelen végig nézve, van benne egy elvi hiba. Te minden ciklusban változtatod késleltetés nélkül, és úgy hogy mindig kikapcsolod a Timert, és mindezt úgy, hogy be sem kapcsolod.
Nos lassan talán összeáll a kép. Viszont egy olyan problémám van ami a képen is láthatsz, hogy a ".CMR"-t nem fogadja el a fordító, pedig az src könyvtárba betöltöttem a pwm.h és a pwm.c fájlokat. Vagy azt valami más tartalmazná?
Mert egy spi kommunikációt már megvalósítottam az itt leírtak segítségével, viszont pwm-hez nem találtam jót. Aztán eszembe jutott az evk1101 example. Ez nagyjából átlátható számomra is, de úgy veszem ki, hogy a Channel Mode Register-t a pwm.channel-ben állítja egy .CMR előtaggal ami nekem nem fordul le. Szerinted mit kéne tennem? Vagy írjak magamtól ezek a header fájlok nélkül?( Csak azzal az a baj, hogy úgy nem is tudom hogy kéne elkezdenem.) Üdv.:Gergő
Minek mérsz kétszer az ADC modullal?
A TCNT1 értékét minek babrálod hardveres pwm-nél? Ha jól van beállítva a timerben a pwm modul, akkor nincsen dolgod azon kívül, hogy állítasz a komparálási értéken, hogyha úgy kívánod. |
Bejelentkezés
Hirdetés |