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
Nézd meg pl. a DCC szabványt, ott 16-24V-t kapcsolnak, méghozzá ugy, hogy a kod energiája minden pillanatban elegendö a fogyaszto áramellátására is.
De sok ilyen van pl. a telefontechnikában is. Az informáciot a 0 átmenet hordozza maga kod meg az áramellátást végzi.
Szivesen! Timer 0-át is használhatod, csak akkor kicsit más lesz a dolog, mert a megszakítást kisebb intervallumokban tudod megoldani. Pl minden 10ms-ben generálódik csak megszakítás és egy változót minden ciklusban növelsz és mikor eléri a 100-at akkor változik a 'sec' változó egyet...
Kicsit utána kell számolni a dolgoknak és akkor meglátod, hogy neked melyik a legmegfelelőbb ![]()
Pl. azért kell protokoll, mert a -legtöbb- rendszer nem "csak úgy" kapja meg a digitális jelsorozatot. Ha mégis "csak" egy sorozatot adnál ki, tudom ajánlani az SPI egységet. Látom szkópod is van, így hamar meg fogod látni hogy miért nem jó, és miért is kell a protokollt ismerni.
Szia!
Most próbálom átlátni azt, hogyha timer0-val csinálom meg, akkor mivan. 16bit-es timer-el okés a dolog. 16Mhz/1024-1=15624. Mivel a timer1 65535-ig számol, a 15624 simán belefér. Ha ezt az értéket eléri, jön a megszakítás. Ha timer0-át akarom használni akkor, hogy kell osztanom a cpu frekijét, hogy 254-nél legyen a megszakítás? Köszi! A hozzászólás módosítva: Okt 21, 2013
Mint már korábban is írtam, Timer 0-ával is meg lehet oldani, de ott csak overflow (tulcsordulás) megszakítást generál (azaz mikor eléri a 255-öt és vált 0-ra), nem tudsz te megadni egy értéket, hogy addig számoljon majd generáljon megszakítást. Ennek az a hátránya, hogy nem tudsz pontos időzítéseket létrehozni, vagyis 16000000/1024/256 = 61.035... ez azt jelenti, hogy egy másodperc alatt 61-szer fog túlcsordulni, minden túlcsordulásnál növelsz egy változót és mikor eléri a 61-et akkor növeled a másodperc változódat!
Mivel az osztás eredménye nem egész szám lett ezért minden 28.44-ik másodpercben lesz egy 62-ik túlcsordulás is, de mivel te 61-nél már növeled a másodperceket és nullázod ezt a változót, ezzel gyakorlatilag hamarabb váltasz mint ahogy kellene, ezért ezek a kis hibák lassan mind összegyűlnek és kb minden 29-ik percben sietni fog 1 másodpercet ![]() Ezért azt javaslom, hogy inkább használd a Timer1-et ha van rá lehetőséged, mert ott nagyon pontos megszakításokat tudsz beállítani. Egy másik megoldás a Timer2 Aszinkrón üzemmódban, de ehhez kell egy 32768Hz-es óra kvarc de mivel a mega8 csak egyetlen külső kvarcot tud kezelni, ezért a 16MHz-es helyett kell betedd, így akkor a proci órajelét a belső RC oszcillátorról kell meghajtani, ami szintén nem pontos, viszon a timer2 nagyon pontos 1 másodperces megszakításokat tud ezzel generálni overflow üzemmódban, 128-as előosztóval ![]() Remélem, hogy ezek közül egyikkel csak meg tudod oldani ![]()
Timer0-val is megoldhato a pontos idozites, csak trukkozni kell.
Pl: (16MHz-es kvarcot feltetelezve) a) 1-es timer eloosztas eseten masodpercenkent 16.000.000/256=62500-szor csordul tul. A megszakitason belul novelsz egy szamlalot, ha eleri a 62500-at, akkor nullazod a szamlalot es noveled a masodperc erteket 1-el. (nem tudom hogy mit kell meg csinalnia az AVR-nek, de ebben az esetben ele sokat foglalkozik a megszakitassal) b) 8-as timer eloosztas eseten masodpercenkent 16.000.000/(8*256)=7812.5-szer csordul tul, ezert kell trukkozni. A megszakitas kiszolgalo rutinba kell azt megoldani hogy a szamlalo eloszor ha eleri a 7812-et akkor novelje a masodperc erteket 1-el, ezutan a nullazas utan masodjara meg csak akkor novelje a masodpercet, ha a szamlalo eleri a 7813-at. Igy az elso masodperc 1/15625-od masodperccel rovidebb, a masodik pedig ugyanennyivel hosszabb lesz, ezaltal a hibak kiegyenlitik egymast... A hozzászólás módosítva: Okt 22, 2013
Ezek alapjan mar meg tudod erteni a lenyeget es at tudod irni a kodot...
Arduino + PCF8563 Hack A Day
Timer0 - val, komparátor nélkül is lehet pontos időt létrehozni. Az alábbi példa pont 1Hz-el villogtat két ledet:
Bocs, de valamit nem értek a kódodban. Miért birizgálod a TCNT0 regisztert abban az
interruptban, amit pont a TCNT0 állapotváltozása(túlcsordulás) váltott ki? A CTC módot szoftveresen csinálod? Miért? A CTC a legtöbb AVR-ben hardveresen elérhető. Ehhez csak ennyit kell csinálni: - komparátor: OCR0(A) regiszter beállítása, mint nálad a "TCOMP" - TCCR0(A/B) regiszterekben CTC módot adsz meg - TIMSK regiszterben a TCIE0(A) flaget állítod be - ISR hívásnál "TIMER0 capture (A)" nevet használsz
Oké, de ezt próbáld meg Atmega8-on is megcsinálni. Annak elég buta a timer0-ja (nincs benne komparátor), és pont ez volt a kérdés. Komparátorral könnyű.
Ok, értem, akkor csak demonstráció volt. Amire azért nagyon ügyelni kell(ene), nehogy meglepetések érjenek: ha az interruptban állítod a TCNT0-t, akkor nem szabad hogy közben lépjen a számláló. Gondolom érzed hogy az 1-es és 8-as előosztó esetéről beszélek. Utóbbi ráadásul bosszantóbb hibákat generál, mert kiszámíthatatlan, mikor lesz jó és mikor nem.
Ha az 1-es timer foglalt, ott a 2-es, igaz hogy ez is 8 bites, de tud CTC módot és ez jó. ![]() A hozzászólás módosítva: Okt 23, 2013
Sziasztok! Valaki megnézné hogy jól csináltam-e? Itt a c fájl, nekem a hex 3kb.
MaSTeRFoXX Hanglejátszós ajtócsengő szeretném meg építeni. A hozzászólás módosítva: Okt 23, 2013
Az AVR Studio4 -en nem jelenik meg a programozó kiválasztó menüsor, a Jumbo is telepítve van, de nem tudom miért.
Ha pedig így se jelenik meg (pl. jobbegérnél az "STK500" nincs a listában), akkor Tools menü,
és majdnem legalul Program AVR. Újratelepítés végleg megoldja ezt is. Volt már ilyenem...
Sziasztok!
Újabb problémám lenne. Van 4 db 7 szegmenses kijelzőm. Órát szeretnék majd belőlük. Korábban beszéltük, hogy a timer1 megszakításában növelgetem a változók értékét stbstb. Van egy sn7447-es IC-m amivel vezérlem a kijelzőket. Itt a bibi, hogy csinálom meg azt hogy a perc két helyiértékét, majd az óra két helyiértékét küldjem külön külön BCD-ben a 7447-nek? (kapcsoló tranzisztorok kapcsolgatják a kijelzőket)
Köszi szépen!
Ezt multiplexeléssel tudod megoldani, ami azt jelenti, hogy egy időpillanatban csak egyetlen kijelző aktív (egyszerre csak egy szám látszik a 4-ből), tiltod az összes kijelzőt, kiküldöd az első számjegy adatait a BCD sínre (mivel minden kijelző a,b,...g és dp kivezetéseit párhuzamosan kell kötni) majd engedélyezed az elsőt, vársz, majd megint tiltod az őket, kiküldöd a második számjegyet, aktíválod a második számjegyet és így tovább...
Hogy ez a folyamatos kapcsolgatás ne zavarja az emberi szemet, legalább 24-szer kellene ezt végig játszodd egy másodperc alatt, de biztos ami biztos alapon a legjobb ha 1kHz-en kapcsolgatod őket, így mindegyik csak 1ms-ot aktív és 3ms-ot inaktív, ami 250Hz-es villogást eredményez de ezt már az emberi szem nem képes észlelni és egy folyamatos számsornak látja az órádat ![]() Elsőre kicsit bonyolultnak tűnhet, de ezzel a módszerrel nagyon sok kivezetést meg lehet spórolni egynél több kijelző esetén ![]() Az hogy egy számot hogy osztol vel számjegyeire az egyszerű, mert az első számjegyre az szám/10-el tudsz hivatkozni míg a másodikra szám%10-el (hour/10, hour%10, min/10 és min%10 -et kell felváltva kiküldözgeteni a megfelelő pillanatban). A legjobb megoldás ha a multiplexeléshez szükséges időintervallumokat is megszakítással hozod létre, ha nem szeretnéd azzal akkor egyszerű 1ms-os delay-eket teszel be egy végtelen ciklusba, csak ekkor nem nagyon tudsz az idő alatt egyébbel foglalkozni, mert a proci mindig a várakozással lesz elfoglalva ![]()
Tanulásnak bőven elég ez is..
![]() Köszi szépen!
Megcsináltam.
Műkszik a dolog, de valami nem okés.
Az a baj vele, hogy az utolsó szám, azaz a hour 1 értéke átcsúszik a min1-re..
A programod alapján a PB0, PD7, PD6, és PD5 a négy kijelző közös anódja, és a PC5, PC4, PC3 és PC2 a 7447-es D,C,B és A bemenetei. Ha igen akkor a gond az, hogy neked csak minden ciklus után nullázza az összes kijelzőt, és mivel az egyik kijelző (a min2) a B porton van és a többi a D-n és nem kapcsolod ki MINDEGYIKET akkor ha jobban megnézed láthatod, hogy a PB0 mindvégig 1 marad, azaz minden utána következő számot ábrázolni fog az is.
A delay-t is csökkentheted 1ms-re (gyorsabb a multiplexelés és nem zavarja a szemet, a mostani programod 50Hz-en villog. A másik észrevétel az a min1,min2... változók használata, szerintem fölösleges, elég lehhe ott helyben behelyettesíteni. Tudom, van még hely bőven a memóriában, csak jó hogy ha úgy szokod meg már az elejétől, hogy a lehető legkevesebb memóriát próbálod felhasználni, ennek akkor veszed majd hasznát ha nagyobb programokat kell majd írj, mert lehet, hogy ott minden byte-ra szükséged lesz majd ![]() Jobban átláthatóbb lenne a program ha használnál makrókat is, ez jelen esetben majdnem lényegtelen, de később (hónapok múlva) megint előveszed, hogy egy másik programnál felhasználd akkor majd pillanatok alatt látni fogod, hogy hogyan is működik, mi van abban a programban és könnyebben tudod majd felhasználni abban a projektben ![]() pl így:
AVR-es C-s exception implementációt keresnék, ha valaki tud ilyet. Technikailag nem nehéz, mert lementjük a registereket, exception-nél meg átállítjuk a stack-et és visszatöltjük a regisztereket.
Nagyon gyors méréshez kellene, ahol nem szeretném megvárni az interrupt >20 órajeles késleltetését (interrupt meghívása, regiszterek mentése, reti,...). A program végtelen ciklusban várakozna az analóg komparátor interrupt jelzővezetékén. Amikor timeout van, akkor interruptból dobnék egy exception-t, ami kiugrana a végtelen ciklusos mérésből. A kérdés, hogy valaki írt-e már C-s exception-handlert? A hozzászólás módosítva: Okt 24, 2013
Hát a hozzászólásodban több helyen is ellentmondás van:
exception: Idézet: „...lementjük a registereket, exception-nél meg átállítjuk a stack-et és visszatöltjük a regisztereket.” interrupt: Idézet: „interrupt meghívása, regiszterek mentése, reti,...” ez a kettő egy és ugyanaz de te nem szeretnéd Idézet: .„megvárni az interrupt >20 órajeles késleltetését” A másik Idézet: és itt is az interruptot használod fel az exceptionhoz, akkor hogy is van pontosan? Nem tetszik a megszakítás mert sokat kell várni, viszont az exceptionnal pont azt használod!„Amikor timeout van, akkor interruptból dobnék egy exception-t, ami kiugrana a végtelen ciklusos mérésből” Szerintem kicsit gondold át a dolgot, mert itt valami nincs rendben, amúgy meg nem tudom mi lehet olyan gyors hogy egy 16MHz-es órajelen járó proci ne tudná lekezelni ezt megszaktításból...
Szerintem félreérted azt, hogy mit szeretne. Mivel voltam már hasonló helyzetben, nagyjából
sejtem mit szeretne. Szeretne egy pontos időmérést a komparátorral, gondolom 1us vagy még pontosabb felbontásban. Ha ezalatt figyeli a timert is, az a pontosság rovására megy. Ezért kell egy "kiugrás", ha a dolog túl sokáig várakozik. Legegyszerűbb megoldás: Nem kell semmilyen try/catch szerkezet, az analóg komparátor és a Timer1 között lóg egy "input capture" nevű szerkezet. Csak be kell állítani a timert, és ha vált a komparátor, csak ki kell olvasni az ICR1 regiszterből az értéket. Hardveres megoldás: Az AVR 0-s vagy 2-es timerének segítségével előállítasz egy F_CPU/2 órajelet. Az órajel egy külső logikai áramkörre megy(néhány kapuból megépíthető), ami csak egyszer engedi a komparátort váltani. Ja igen: a komparátor is külső kell hogy legyen, pl. LM393. Ha vált a komparátor, a logikai rész tiltja az órajelet(ami a T1 lábra megy be az AVR-en). És csak a TCNT1-et kell kiolvasni. A TCNT1-re beállíthatsz egy felső határt, és akkor interrupt is megszakíthatja a számlálást(ha akarod). Amikor indítod a számlálást, csak egy regisztert kell beállítani a timer0 vagy 2-n (fast PWM mód vagy hasonló) és a TCNT1-t lenullázni. Bonyolultnak hangzik, de ez adja a lehető legpontosabb mérést. Amit te szeretnél (try/catch blokk) arra nem tudok pontos választ adni. Mindenesetre próbáld a lehető legegyszerűbben megoldani, ez nem JAVA meg C#, itt mindent neked kell lekódolni. A hozzászólás módosítva: Okt 24, 2013
Végülis sikerült összebarkácsolnom az exception-kezelést és a kód is tök egyszerű lett, a lefordított méret sem tragikus. Ez kiugrik mindenhonnan és az interrupt flag-et is helyrerakja (csatolva).
Szépen végigugrált az exception-ökön a következő teszt kódon:
A hozzászólás módosítva: Okt 24, 2013
Sziasztok,
SoftPWM-et próbálok megvalósítani. A jel meg is jelenik rendben. A kitöltési tényezőt egy változóval szeretném vezérelni (threshold). A változtatást pedig egy külső interrupt (INT0) kezdeményezi. Az interrupt rutin lefut de a threshold nem változik meg. Betettem az ISR rutinba ellenőrzésként egy LEDet felkapcsoló utasítást. Az is csak egy pillanatra változik meg majd kikapcsolt állapotba visszakerül. MIÉRT? gacserus
Sziasztok!
Most programoztam egy ATMEGA 8 at de sajnos az LCD re nem ír ki semmit, ha a kontrasztot állítom akkor az első sor sárga lesz azután a második is.
Köszönöm a linkeket, azonban az alapvető problémám az I2C (vagyis TWI) interface használata az Atmega128 chipen. Gondolom van már készen erre a feladatra függvénykészlet (feltételezem az első példában a Wire.h header tartalmazza ezeket), amelyeket tanulmányozhatnék, de eddig sajnos nem találtam megfelelő változatot.
A hozzászólás módosítva: Okt 26, 2013
Az lcd_init és az lcd_clrscr hívását tedd a while(1) elé. Ha állandóan inicializálod és törlöd a kijelzőt nem csoda ha nem megy.
|
Bejelentkezés
Hirdetés |