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
Ha letiltom a globális megszakítást, kajd később engedélyezem, akkor a letiltás ideje alatt történő megszakítások le fognak futni egymás után? (Persze csak ha különböző típusúak voltak).
Szerintem meg igen. A megszakításjelző flag-ek az engedélyezéstől függetlenül magasra állítódnak egy esemény bekövetkeztekor. A tiltás csak annyit tesz, hogy nem veszi ezt figyelembe a proci, és nem szakítja meg az éppen futó programot. Viszont ahogy újra engedélyezzük a megszakításokat, a magas megszakításjelző flag-ek egyből megszakítást generálnak sorjában a prioritási szintnek (vagy a belső logikának) megfelelően.
Próbáld csak ki! Sőt! Amennyiben a megszakításkezelő rutinod nem törli a megszakításjelző flag-et, kilépés után újra megszakítás generálódik.
Köszönöm! De amúgy amikor lefut a megszakításkezelő rutin, az alapból törli a flag-et, nem?
A megszakítás kezelő rutin törli a flag-et a RETI utasítással.
A flag-ek minden esetben beállnak,mint ahogy írtad is,de az adott megszakítás csak akkor fut le,ha az engedélyezve van és a global is 1-es. Flag-et 1-be írással lehet törölni. Tehát a megszakítás így fut le: global 0-ba áll ,majd reti utasításra 1-be és törlődik az adott flag is,mindez hardveresen.
Bocs,annyit korrigálnék,hogy a flag akkor törlődik,amikor, a PC(program counter) az adott vektorra mutat,tehát az elején.Így létrejöhet az a helyzet is amit írtál,ha a lefutás alatt jön még egy megszakítás kérés,feltéve persze,ha nem ugrik be egy nagyobb prioritású is,mert akkor övé az elsőbbség.Elnézést a figyelmetlenségért !
A hozzászólás módosítva: Máj 23, 2014
Köszönöm a segítséget. Letöltöttem az eXtreme Burner programot és azzal sikerül a fuse bit állítás.
Üdv!
Inkább nekem kellene elnézést kérnem, mert nem igazán korrekt amit írtam, így ezt most javítom. Tehát... Kétféle megszakítástípus létezik: Az első típushoz tartozóknak van megszakításjelző flagjük, ami egy esemény bekövetkeztekor magasra állítódik, még ha épp tiltva is van a megszakítás. Mihelyt engedélyezve lesz, az azonnal programmegszakítást generál. (Hacsak nem jött ezalatt egy nála magasabb prioritású, mert akkor azé az elsőbbség, ő pedig várhat tovább.) A megszakításkezelő rutinba való belépéskor a flag automatikusan törlődik és minden megszakítás tiltásra kerül, de ha ezután (a megszakításkezelő rutin végrehajtása közben) mégis bekövetkezik egy esemény, az újra magasba billenti a flaget, ami majd újabb megszakítást generál kilépés után. Akár a jelenleg futó megszakításkezelő rutin is megszakítható, ha közben engedélyezzük a megszakításokat. Egyébként a flagek manuálisan is törölhetők 1-es érték beírásával. Kilépéskor (RETI) újra engedélyeződnek a megszakítások, és az esetleg addig várakozók most sorrakerülnek. A második típusba a flag nélküli megszakítások tartoznak. Ezek csak akkor szakítják meg a programot, ha a megfelelő feltétel ideje alatt a megszakítás engedélyezve van. Útólagosan már nincsenek hatással a program menetére.
Magyarul: amikor a megszakítás LEFUT, a rutin meghívásakor törlődik a flag, azaz nem fut le újra.
Egy kivétel van: az USART "UDRE" flag. Ez mindig "1", ha üres a kimenő adat regiszter. Ezt nem fogja törölni a megszakítás lefutása. Ha a megszakításrutinban nem történik egy újabb bájt átvitele(pl. mert elfogyott) akkor TILTANI KELL:
Természetesen, ha van új elküldendő bájt(sorozat) akkor engedélyezni kell. Ezzel a módszerrel teljesen a "háttérben" lehet elvégezni az adatátvitelt, a főprogram futásakor elegendő az adat feldolgozását végezni, nem kell várni az átvitelre vagy annak befejezésére. A hozzászólás módosítva: Máj 23, 2014
When the Program Counter is vectored to the actual Interrupt Vector in order to execute
the interrupt handling routine, hardware clears the corresponding flag that generated the interrupt. Tehát rögtön a megszakításra ugrással törlődik a flag,ami azt jelenti,hogy a megszakítás lefutása alatt is újra beállhat,újabb megszakítást generálva,amint a global megint 1-es lesz,mint ahogy ezt Zsora is írta. Hozzá kell tenni,hogy két megszakítás között a főprogramból még egy utasítás végrehajtódik,ezt a tulajdonságot lehet debug-ra használni.
Sziasztok!
Ennek mi lehet az oka? Már egyszer újratelepítettem, de nem segített. Az .elf fájl pedig megvan.
Csak egy tipp: lehet hogy a konyvtarnevekben levo ekezetes betuket nem szereti...
Az lesz a probléma. Köszi!
Hello, engem az erdekelne, hogy atmeg328-ast ha olyan bekotesbe rakom bele, amiben van kulso kristaly, de nem allitom at belsore, akkor az gondot okozhat?
Sziasztok!
Egy kis segítségért fordulok hozzátok. C-ben próbálok megoldani egy programozási problémát, de valahogy nem igazán sikerül. Attiny24 a vezérlő, rá van kötve 6db relé. Külöböző portokon, különböző lábakon. Ezeket beraktam tömbbe, nekem tetsző sorrendben. Így sorban tudom őket egymás után egy "for" ciklussal ki-be kapcsolni. És itt jön a számomra megoldhatatlannak tűnő feladat: egy relét addig kellene bekapcsolva tartani, amíg: -az ADC4 lábról érkező A-D eredmény 5 egymást követő alkalommal nem kevesebb, mint 2 (ez az érték fix lesz, csak ki kell még számolnom) AKKOR csak lépjen egyet előre a for ciklus a tömb következő elemére, DE HA -nyomva tartom az "A" vagy "B" gombot kb. 20ms-ig vagy -az ADC4 lábról érkező A-D eredmény 5 egymást követő alkalommal túllépi a referencia értéket (ez az érték adott, az A-D konverzió free-run módban fut a háttérben) AKKOR hagyja abba a for ciklust, és ugorjon a következő parancsra. Hogyan kellene a ciklusokat egymásba ágyazni, illetve ez így egyáltalán kivitelezhető-e? Esetleg megszakításokkal? Most eléggé tanácstalan vagyok.
Én ezt inkább egy while ciklusba szervezném. Azon belül néhány segédváltozóval.
while (aktiv_relé<6) - "aktiv_relé" értéke megadja, hogy melyik relé aktív. - "feltétel_1" számolja az ADC4 alacsony értékeit. Ha elérte a határt, növeli az aktiv_relé értékét és nullázza a feltételeket. - "feltétel_2" számolja, hogy hány ciklus óta nyomod a gombot. Ha elérte a határt, növeli az aktiv_relé értékét és nullázza a feltételeket. Hogy hány ciklust kell kivárnia, az órajeled szabja meg. - "feltétel_3" számolja az ADC4 magas értékeit. Ha elérte a határt, azonnal 6-ra növeli az aktiv_relé értékét és ezzel kilép a ciklusból. A hozzászólás módosítva: Máj 27, 2014
Azóta rájöttem, hogy figyelmetlenül olvastam. A feltétel_2 is 6-ra növeli az aktiv_relé változót.
Köszönöm, ez a megközelítés még nem jutott eszembe. Viszont egy bökkenő még van:
ahhoz, hogy elkezdjek mérni az ADC lábon, ahhoz előbb el kell indítsak egy relét. Mivel a rendszer úgy lenne összerakva, hogy egy 0.05 ohm-os ellenálláson eső feszültséget mér az ADC, így érzékelve az adott relén lévő motor áramfelvételét. A gondom a program felépítésével van. Hogyan tudom számoltatni a ciklusokat (vagy időt) úgy, hogy közben meghúzva maradjon a relém? Tehát addig ne lépjen ki, amíg nem tartom elég ideig nyomva a gombot, vagy (egy ideig) nem túl nagy az áramfelvétel. A hozzászólás módosítva: Máj 27, 2014
A ciklusba lépés előtt 1-re állítod az aktiv_relé értékét.
A ciklust úgy kezdeném, hogy vagy egy switch-case vagy 5 db if vizsgálattal bekapcsolnám a megfelelő relét: magasat_mér=0; aktiv_relé=1; while (aktiv_relé<6) { if (aktiv_relé==1) {relé1=be, minden más relé=ki;} if ... gombot_nyomtak=gombot_nyomtak+1; magasat_mér=magasat_mér+1; if (gombot_nyomtak==ciklus_max) {aktiv_relé=6;} //ciklus max a gombnyomás ideje alatt lefutó ciklusok száma if (magasat_mér==2) {aktiv_relé=6;} }
50 Hz-es frekvenciájú PWM kimenetet hogy lehet beállítani, úgy, hogy a TCNT1 regiszter értékén ne kelljen változtatni? (Használom másra is a Timer1-et, ezért jó lenne, ha nem kellene nullázni).
A hozzászólás módosítva: Máj 27, 2014
Ha meghatározott kimeneti frekvenciát akarsz el érni, akkor vagy az órajelet variálod, vagy a számláló indulási értékét állítod be, minden túlcsordulás után.
Segítség: AVRCalc AVRCalc Az AVRCalc egy igazán hasznos segédprogram a mikrovezérlő fejlesztéséhez. De mire is képes: * megjeleníti a lebegőpontos számoknak megfelelő hexanumerikus értékpárját * Adatátviteli sebesség (Baud-rate) beállítását meghatározó UBR regiszter értékét adja meg a kristályfrekvencia és a tervezett sebesség függvényében. Mellette a névleges és a tényleges érték eltérését is feltűnteti. * Az előosztás mértékét, az előbeállítás adatait, a számláló- (Timer0 és Timer1) regiszterek értékét megadja a deklarált periódusidő (msec, usec), frekvencia alapján. Adatátviteli sebesség kiszámítása A példában a tervezett adatátviteli sebesség 9600 bps legyen és a chip frekvenciája 4.0 MHz. Ehhez az AVR BaudRate mezőbe a lenyíló menüből válasszük ki a 9600-at. A Crystal freq(in MHz) menüből a 4.0-t kell megjelölni. A programablak aló részén az UpDate gombra kattintva meg is történik a meghatározás. Az UBRR regiszter értéke és a %ERR hiba megjelenítésre kerül. Ha Bascom rendszerben programozunk, akkor a UBRR regisztert a fordítóprogram automatikusan kiszámolja nekünk. A hibatűrés - ha PC-vel kommunikálunk - a 2-3%-ot ne haladja meg. A program figyelmeztet, ha nem beéállítható sebesség-frekvencia páros akarunk alkalmazni (pl. 14.7456 MHz és 300 bps). Ekkor kérdőjelekkel jutalmazza ténykedésünket. Adott frekvencia előállítása A Timer0 számlálót szeretnénk felhasználni 100Hz-es jel előállítására. a Timer0 8 bites számláló, így az értéke 0...255 között változhat. A túlcsorduláskor megjelenő megszakításban kell beállítani az újraindulási értékét és itt lehet a kimeneti port állapotváltozását is megadni. vagy használhatjuk a hardveres kimenet is (OC0). A számoláshoz meg kell adni a chip órajelét a Crystal freq(in MHz) menüből, a példánkban ez legyen 4 MHz, így a 4.0-t kell megjelölni. A Prescale TCCRx regiszterben megadjuk a tervezett beállítandó előosztás mértékét, ez legyen pl. 256 (lenyíló menüből kiválasztható). A Needed timer mezőbe beírjuk a 100-as értéket, és a rádiógombok segítségével a Units:Hz-t kiválasztjuk. Ha a hardveres kimenetet használjuk, akkor figyeljünk arra, hogy mit állítunk be. Az OCx toggled kipipálásával a Timerx leketyegéskor állapotváltozást adjuk meg, míg egyébként csak tüske keletkezik a kimeneten. (frekvencia kétszerezés). Az UpDate megnyomásával a beállítandó TCNT0 regiszter újraindulási értékét kapjuk meg. Mellette a ténylegesen elérhető időzítést (ez jelen esetben a feltételek mellett 100,2 Hz). Timer1 használatával, 8-as előosztással elérhető a 100 Hz jel. A hozzászólás módosítva: Máj 28, 2014
Köszönöm, megpróbálom összehozni.
Sziasztok! Lenne egy kérdésem, napok óta bajlódom vele. (Megjegyzném, hogy eléggé kezdő vagyok még ezen a téren)
Van egy HC 06 -os bluetooth modulom, azt akarom, hogy tudjak kommunikálni egy atmega8 kontrollerrel PC-ről, uarton keresztül. Azt szeretném, hogy azt a karaktert amit PC-ről elküldök (putty), azt küldje vissza a kontroller. Ez nem működik..tehát nem ugyanazokat kapom vissza, azonban ha a kontrolleről direkt küldöm a karaktereket akkor azt jól megkapom. A beállítások egyeznek. (9600 baudrate, no parity, 1 stop bit, no flow control). Próbáltam külső kristály oszcsillátorral is de ugyanaz a helyzet. A BT modult kipróbáltam egy arduinoval is, azzal működött..(ugyanazt kaptam vissza amit küldtem) Esetleg tudnátok segíteni? Előre is köszönöm. A hozzászólás módosítva: Máj 28, 2014
A fogadast hogy ellenorzod megszakitassal vagy pollingal? Mekkora orajelet hasznalsz? Estleg csatold a kodot is.
Programkód? HW rajz?
- hibás bekötés, - nembufferelt soros vétel, - hibás kommunikáció megadása - ...
Sziasztok!
Adott egy string-em, ami a következőt tartalmazza: +CSPN: "Telenor HU",0 Szeretném a két idzőjel közti karaktersorozat első 9 karakterét egy string be másolni. Hogyan lehet megcsinálni?
Nem használok megszakításokat, mert egyelőre csak leakarom tesztelni, hogy müködik - e.
8MHZ - es órajelet használok, próbáltam belső oszcillátort és külső kristály oszcillátort is.
Minden esetben megkapom a két zárójelet, de közöttük hibás karaktert kapok. Általában 'k'-ra [B] -t, 'j'-re [@]-t, 'h'-ra [@]-t, 'g'-re [F]-t. (ha ez segít valamit).
Az új kódban ellenőrzöm az errorokat is, minden karakter után frame errort kapok. |
Bejelentkezés
Hirdetés |