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
Szia!
Találtam Neked két példát, egy Ulli Sommer könyvből (Ő, német nyelvterületen ismert a különböző AVR, ARDUINO, BASCOM, stb. szakkönyveiről). Viszont ezek tényleg csak példák, "csontvázak", a végtelenségig leegyszerűsítve. A portokat természetesen át kell írnod. A nyomógombok lekérdezése is egyéni, hogy High vagy Low, amire kíváncsi vagy. Viszont használható. A hozzátartozó kapcsolásokat nem scannel-tem be. Az első egy impulzus számláló a 8-bit Timer segítségével. Az eredményt minden 5 másodpercben adja ki, a nyomógomb nulláz. A második egy frekvencia számláló. Játssz a kóddal és megérted. Aztán bővítsd. Sok sikert!
Úgy döntöttem megírom a programot. Olyan kérdésem lenne hogy a timert miután elindítom milyen sebességgel számol(ha jól értem a működését indulás után elkezd 0tól felfelé számolni)? Ez megegyezik a processzor sebességével? Vagy esetleg én adom meg? Most épp ezzel ismerkedek.
Alapesetben valóban a processzor sebességével fut, mint az első példa programban. A másodikban minden 256-ik órajelnél számol egyet. Ott aktiválva van az előosztás.
Azaz a "Prescale". Egész logikus ez a programozás
![]() ![]()
Akkor a programom nagy vonalakban: egy külső megszakítás= zárt a reed > indul a TIMER > újabb megszakítás =megint zárt a reed > TIMER leáll egy értéknél > ha TIMER kisebb X-nél akkor OUT egyenlő HIGH > TIMER nullázás(kérdésem még: hogyan kell nullázni?) > LOOP
Egyenlőre ennyi, számolgatnom kell még de ez az alap elgondolás már megvan és véleményt kérnék. 2 dolog hiányzik a tudástáramból ehhez az egyszerű feladathoz: timer nullázása és a megszakítás. Remélem nem túl nagy hülyeség amit kitaláltam, illetve remélem a processzor végre tudja-e hajtani ezen műveleteket mire jön a következő megszakítás. Ne haragudjatok a bénázásomért, sosem voltam közel a programozáshoz.
Szerintem!
Ide érdemes regisztrálnod: Bascom-AVR nyelvű programozás Utána olvashatod a régi oldalon. A Bascom könyvet! Ott minden kérdésedre megtalálod a választ.
Van egy nixie órám. Ha mp-ként futtatom az interrupt-ot akkor szépen dolgozik.
Szeretném 0,5 mp-ként meghívni az IT-t és csak minden 2. alkalommal elvégezni az óra kiszámítását. Ha így teszek egyszerűen, véletlenszerűen megbolondul és csak 9-ig számol. Utána sem állítani nem lehet, sem a normál lépését sem végzi el. Néha csak az óra néha csak a perc, néha mindkettő. Néha elmegy 19-ig és ott áll meg. A különbség csak a kommentel tiltott (//) if utasítás és a vált növelése. Ha van if akkor bolond, ha nincs működik. A kód:
Létezik, hogy több if egymásban vagy több if az IT rutinban bizonytalanságot okoz? Veremhiba? A hozzászólás módosítva: Aug 13, 2014
Hali,
Csak ránéztem a kódra, de szemet szúrt, hogy van egy delay az ISR-ben. Az ilyen megoldás kerülendő, mert kevés idő marad a főprogramra, vagy más megszakításokra. Esetedben valószínűleg éppen ez okozza a hibát, mert 450ms-ig áll a program, és ha 500ms-enként akarod meghívni az ISR-t a többi műveletre nem elég az 50msec, és mivel a függvény végén nullázod a flag-et, a következő megszakítás kimarad. Ha én írnám a kódot, a timer-t 100msec-re állítanám be, és minden 10. futásra állítanék egy flag-et, amit a főprogram vizsgálna, és ott lenne az óra beállítása, flag törlése, kettőspont (ez szintén flag, csak 5-ös osztással) és a többi.
Elnézést, de a kódban benne maradt a workaround. Az eredeti kódban nincs 450ms delay csak a 20ms prellmentesítő. Ezt kéretik nem figyelembe venni:
Azért hívtam meg 500ms-re mert így villogtatnám a kettőspontot. Mellesleg az működik, úgyhogy az IT meghívása rendben zajlik. Workaround: kínomban 1mp-enként hívom a rutint és 480ms-t várok majd frissítem a kijelzést. Ettől villog a jel. De így 480ms-t elbukom mert nem megy le idle állapotba. Pontosan erről kérdeztem a program megírása előtt itt a fórumon és ha visszanézed nem volt határozott álláspont. Nem sokból tart átírni. A hétvégén megcsinálom. Így még a beállítás sebességét is pontosítani tudom 10 lépésben. Köszönöm.
Hogy csinálsz veremhibát a fenti kódban?
1) az interruptban szöszmötölsz delay_ms-sel, meg minden mással 2) az interrupt végén meghívod a sei-t Ez a kettő garantált veremhibát eredményez. Interruptban se a cli-t, se a sei-t nem kell meghívni. Meghívódik a timer interrupt, elkezdesz benne időthúzni, mégegyszer lejár a timer, de ez még nem lenne baj, mert amint kilép az interrupt, azonnal újrameghívódna, nem lenne veremhiba. De te elengeded az interruptot sei()-vel az interrupt befejezése előtt, ami azt eredményezi, hogy ahelyett, hogy kitakarítaná a vermet, azonnal újra meghívódik az interrupt és néhány ciklus után túlcsordul. Ha nem lenne sei, az MCU másodpercenként 2-3 utasítást végrehajtana. ![]() Két hiba összege, amit látsz. Interruptban a delay_ms(1) is brutális késleltetés, mondjuk 16 MHz alatt 16000 ciklust zabál el értelmetlenül. Delay-t nem raksz interruptba, se kicsit, se nagyot. A hozzászólás módosítva: Aug 14, 2014
Köszönöm. Értettem.
![]() Akkor megy ki a cucc a main-be. Ahogy Lpi írta szaporán It-zek, flag-ezek aztán számolgatok mikor ki fusson le a szükséges rutinok közül. Akkor az valószínű, hogy nem az egymásba ágyazott if-ek okoznak gondot, ugye? Azt továbbra is használhatom a főprogramban? A főprogram végén maradhat az idle, hogy a fölös időben ne egyen olyan sokat?
Sziasztok, lehet hogy ez nem ebbe a témába tartozik, de az lenne a kérdésem, hogy az ATTINY13-20PU többször felprogramozható? (kezdő vagyok)
![]()
10000-szer, adatlapjában benne van.
Hát nem megy. Valami más a baj és nem tudok rájönni. Most az alábbi kód is megállt 19:49-nél és sehova tovább:
Most nincs több ötletem. Valami mégiscsak az if-ekkel lesz. A következő indulás után a 09:19-nél akadt ki amikor be akartam állítani. Ez nem a kód logikájában lesz
A fejlesztes folyaman erdemes bizonyos program reszeket kulon kulon tesztelni es utanna osszerakni egy nagyobb programot belole es igy tovabb. Az extrak maradnak a vegere (esetedben sleep, stb) A konstansokat nevezd el (C-ben #define nev ertek), ugyanigy a gombokat es maszkjait is. Nincs az a pihent ember aki bitenkent vegignezi a kodot manapsag a forumon, mert sok ido es energia. Ha mar IT-zel, ne hasznalj delayt. A delay csak anyit csinal hogy megeszi adott ideig a proci idot, semmi szukseg ra, kezdo, tudatlan programozo hasznalja csak. (Inicializalasoknal hasznalhato, mert az csak egyszer fut le)
Mindenkinek köszi. Megvan a hiba. Akkor akadt ki amikor felgyorsítottam a beállításkor a számlálást olyan állapotba került, amit a számláló programrészlet nem tudott kezelni (9-ről 11-re ugrott egy mp alatt). Ettől szétesett. Nem az if vagy az IT tette hanem ha 1mp-cel futott a beállítás akkor jó volt ha pörgettem nem.
Kicseréltem a feltételeket = helyett > -ra és láss csodát megy. Úgy jártam mint a tudós és a bolha. Rossz következtetést vontam le a kísérletekből.
Majd szétnézek a Neten más prellmentesítő algoritmus után. Minden más delay-t töröltem.
zombee féle hiszterézises prellmentesítés - az algoritmus:
- csinálj egy időzítő interruptot, abban vizsgáld a nyomógombokat(akár többet is) - minden nyomógombhoz tartozzék egy számláló (elég 8 bites) - ha egy gomb le van nyomva, a hozzá tartozó számlálót növeled 1-el ha nem érte el a "maximumot" - ha egy gomb nincs lenyomva, csökkented a számlálóját (kivéve akkor ha nulla) - ha egy gomb számlálója ÉPPEN elérte a "maximumot", egy jelzőbitet 1-esre állítasz(LENYOMVA) - ha egy gomb számlálója ÉPPEN kisebb lesz mint a "minimum", 0-ra állítod (FELENGEDVE) A jelzőbitek lehetőleg "volatile" változókban legyenek, a számlálók lehetnek "sima" globális változók mivel csak az interruptból lesznek használva. Pár paraméter: - az interruptot 1-2 ms közé érdemes beállítani - MAXIMUM = 25 - MINIMUM = 19
Itt találsz párat, a Dannegger féle hasonló,mint amit zombee javasolt.
Nem kell bonyolult dolgokra gondolni. Ha mar van egy megszakitas beallitva, ami eleg gyorsan fut be ahhoz hogy egy gombot be tudj olvasni mar meg is van oldva a problema egy resze. Nehan 10ms-onkent kell megnezni hogy az adott gomb milyen allapotban van. Ha az IT-d gyorsabb, akkor novelsz a megszakitasban egy szamlalot. A main()-ben pedig vizsgalod, hogy a szamlalod elert-e egy bizonyos erteket (ez az ertek elore kiszamolhato az IT idobol), ha elerte kinullazod azt es beolvasod a gomb(ok) allapotat.
Üdv ! A Studio4-ben használható a legfrissebb Toolchain ,vagy csak nálam fagy a szimulációban ?
Csak a 3.3.1-ig megy,telepíthetem újra a 6-ost. Miért pont visual studio ?
![]()
üdv. Mindenkinek!
Nem készülő projekttel kapcsolatban, csak gondolati síkon érdekel a válasz. Ha nem tudom beállítani a megszakítások prioritását, akkor hogy kezelem le azt az esetet, amikor egy megszakítást kiszolgáló rutin éppen fut, de számomra éppen beérkező más típusú megszakítás fontosabb? üdv. VFR72.
A "nem fontosabb" megszakításrutin elejére teszel egy "sei();"-t.
A sei(); nem a globális megszakítás engedélyezése?
Figyeled a megszakításban a számodra fontosabb megszakítás jelzőbitjét. És
- átugrasz és végrehajtod és nullázod, - a futó megszakításodat lezárod, az alacsonyabb prioritású végrehajtódik és a végén az abbahagyott jelzőbitjét újra bebillented. Melyik INTekről van szó? Hátha van más megoldás... A hozzászólás módosítva: Aug 21, 2014
Szervusz!
Általánosságban érdekel a dolog, de nézzünk egy konkrét esetet: RS232 porton megszakítással fogadom a karaktereket, ez a megszakítás fontos, mert nem dobhatok el egy karaktert sem, de mindeközben fut egy időzítő is, ami alárendelt szerepet játszik a történetben. A kérdés az, hogy megszakításon belül tudok-e tiltani egy másikat? Azaz: - jön a karakter - megszakítási rutinra ugrok - tiltom a timert - elvégzem a megszakításban a feladatot (karakter ment, számláló inkrementál) - engedélyezem a timert
A soros buffer 3 byte + a vételi buffer. Mindez HW-ből.
Nem. Megszakítas jon, timerre ugrasz. Végrehajtod. A rutin max ideje 1-2 karakter vétele. A timer lefutott, akkor kilépés után azonnal a soros INT-re ugrik.
Sziasztok,
Egy projektben, egyszerre több nMOSFET-et kell vezérelnem, PWM jellel. Ehhez egy arduino és 74HC126-típusú IC-k vannak, mindegyik Mosfethez ugyan az a PWM jel kell, a probléma a kapcsolgatással van. Az IC elég egyszerű, minden 'A' bemenethez megy ugyan az a PWM jel az Arduinoból, és mindegyik PWM jelet egy digitális jellel engedélyezek, hogy mehet e ez a jel a Mosfetre, a baj az, hogy amikor a PWM jelet nem engedélyezem, az IC nem tökéletessége miatt a kimenetén ilyenkor is megjelenik egy kb 0,5 V feszültség ami a Mosfetet már nyitja, holott éppen ilyenkor zárt állásban kellene lennie. Ebben szeretnék segítséget kérni, hogyan lehetne, hogy nem engedélyezett jel mellett a Mosfet Gatjére ne kerüljön feszültség, 0V-on legyen, egyébként pedig 0-5 V-ig vezérelhető a gate a PWM jelnek megfelelően.
Nem mindig tudod megcsinálni.
I2C alatt használtam ilyet, ott hellyel-közzel be lehet rakni a sei()-t, mert amíg le nem kezeled, addig a a TWINT 1-ben van és fogja a buszt (a STOP jelet külön kellett kezelni, ott nem jó a sei). Baromi veszélyes, mert könnyen stack túlcsorduláshoz vezet. Timer esetén sei szintén megy, de előtte tiltsd a timer interruptot. Egy cli után meg interruptból visszakapcsolhatod a timer interruptot. A hozzászólás módosítva: Aug 21, 2014
|
Bejelentkezés
Hirdetés |