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
Tudom, sajnos a program vagy 40 oldal és rengeteg részre van bontva.
(Ezért sem raktam be elsöre). Amire segitséget keresek azonban talán igy is érthetö. A Motorrun Kapcsolja az EN bemenetet - nem fontos a probléma szempontjából Utánna következik az Xpulseon Ami kapcsolja a kimenetet magas szintre. ( teszi is ha teljesülnek a feltételek) Utánna van egy makro ami talán a kivülállonak a legérthetetlenebb: Az elsö sor az imént kapcsolt kimenet komplemensét rakja a T regiszterbe Majd a következö sor a T regiszter tartalmát küldi vissza ugyanarra a kimenetre , azaz megváltoztatja a kimenet szintjét és igy befejezödik a periodus. (Legalábbus a fejemben ) Az xpulseoff elméletileg ugyanezt teszi ( ez volt az eredeti ötlet), de ezt a programbol hivtam, de valamiért nem lett jo. Még egyszer talán elölröl. Van két regiszeterem y és x Az y-ba beirok egy számot (word) Az IRQ lehiv egy rutint ami összehasonlitja az y az x-l és ha nem egyformák, akkor kiad egy impulzust a portra, majd eggyel növeli az x értékét, majd vissza kellene billentenie a portot az alaphelyzetbe. Mindezt ismételnie kell minden IRQ ciklusban addig, amig az x=y, ekkor leáll. A feladat elsö része müködik azaz az IRQ-ban szépen összehasonlittodnak a regiszterek, kimennek a parancsok a portra, az x is növekszik minden ciklusban, de port bekapcsolt állapotban marad addig, amig el nem érem az y=x állapotot, ( vagy olyan rövid az impulzus, hogy az analizátorom nem látja). Ha a léptetés közben kézzel nullázom a portot, azt ujra bekapcsolja. Na mindegy, megint nekiülök, lehet, hogy megtalálom a bajt. Kösz a segitökészséget. A hozzászólás módosítva: Jún 25, 2014
Idézet: „Az elsö sor az imént kapcsolt kimenet komplemensét rakja a T regiszterbe” Pár megjegyzés: A T nem regiszter,hanem egy bit a status regiszterben,de gondolom csak elírás. Bit esetén nem használjuk a komplemens kifejezést,mert 1 komplemense nem 0,hanem negáltja,inverze van. Ha bitet akarsz billegtetni egy byte-ban,akkor maszkot kell használni és EOR utasítást,ahol 1-es van a maszkban ott a bit inverzére vált.
Bocs igy van, de már közben sikerült összerakni a kodot. Most már billeg a kimenet minden IRQ ciklusban ( nem a T bitet használom).
A kikapcsolás volt rossz helyen.......
Sziasztok. Nem rég kezdtem ismerkedni az AVR programozással C++ban. Az első programok futtatása után egy kérdés tevődött fel bennem, amire nem találtam választ... ezért megkérdezem.
Lehetséges-e az AVR mikrónál, hogy két kimeneti lábon egymástól függetlenül kapcsoljak ki-be (Timer használata nélkül), vagy egyébb müveleteket hajtson végre párhúzamosan? Pl. (remélem érthető lesz a példa) Első rész: if (adc_1 > x) { delay 10s; újbóli ellenőrzés; PB1 ON delay 10s; PB1 OFF; PB2 ON } else { csináljon valami mást) Második rész: if (adc_2 > y) { PB3 ON, delay 2s; PB3 OFF; delay 2s; } // ez fusson folyamatosan Meg lehet oldani hogy az "első rész" amig fut (várakozik, kapcsol, stb), addig a "második rész" szünet nélkül fusson folyamatosan? Vagy hogy lehet az ilyesmit megoldani?
Igen lehetséges!
Mondjuk felbontod a várakozást 1s-re. És felveszel 2 változót számlálónak s2, s10 Cikluseleje: delay 1s; ++s2; ++s10; if(s2 == 2) {Második rész; s2=0;} if (s10 == 10) {első rész; s10=0} goto cikluseleje; (A példa csak ötlet adó, a részleteket rád bízom!)
Valódi paralell nem. Preemptív multitask a kulcs. Illetve gyors timer alapú interrupt. Így 1...10 msec reakcióidővel/várakozásokkal/válaszokkal tudsz számolni. Mint pl. a korai Windowsok.
A korai vindozok (3.1, 95, 98) kooperativ multitaskot hasznaltak, es a fenti feladatra is bosegesen elegendo lenne. A mostani vindozok (kezdve az NT-vel) mar preemptivek.
Direkt ki hangsújozta, hogy Ő kezdő és, "(Timer használata nélkül)"!
Kissé komolytalan Preemptív multitaskot ajánlani!
Egy ujabb kérdés: már ugy müködnek az impulzusok ahogy szeretném, de most valami más alapvetö bajba akadtam meg.
Szoval ha az AVR Studiobna F5-l léptetem a kodot, akkor minden rendben van, ha Autostepben, akkor sajnos nem jön ki az nyomogombot kezelö rutinbol. És valoszinü, higy ugyanezt teszi, ha betöltöm a programot, mert a nyomogomb parancsát elfogadja és az állapotot kiirja az LCD-re, de nem jelennek meg az impulzusok a kimeneten. Esetleg tul lassan megy, és nem tudom kivárni az eredményt? Mit kéne megnéznem még. Ilyen bajjal must futottam elöször össze, amikor már régen mennek az LCD, az EEPROM meg a nyomogomb rutinok, söt már az impulzus ado is megy F5-tel.
Sziasztok. Nem tudom találkozott-e valaki hasonló problémával:
Adott egy atmega8, amelynek a ADC0 lábára egy feszültég osztón keresztül 400mV adok. Az AREF-re és az ADCC-re is egy-egy 100nF kondenzátor került, ezen túl az VCC és AVCC között egy 10uH induktivitás is van. Az atmega órajele 12MHz. Az ADC 2,56V-os referencia feszültségre van állítva, az előosztó 128 (~93.74kHz). 100ms időközzel 2 ADC mérés történik, amelyből az első értéke el van dobva. A hibajelenség a következő: - indulás után 146-152 lesz az ADC regiszter értéke (arányosítva 380-400mV). - ha megváltozik a mért feszültség (pl.: 1,2V egy-két másodpercre), akkor a mért érték (miután a bement vissza áll 400mV-ra) 178-182 (470-480mV) - reset hatására újra jól méri az értéket (146-152) - indítás után az ADC0 lábat GND-re kötve 0 (0mV) értéket mér - bemenet változása után ugyan ez az érték 32 (80mV) Ha mérés után letiltom az ADC, akkor 400mV-on megjavul a mérés. Ettől függetlenül 330mV és 370mV közötti tartományban durván felülmér 160-163 (420-430mV), viszont 370mV felett helyre áll: bement => ADC regiszter => arányosított érték 320mV => 120-122 => 320mV 330mV => 120-122 => 320mV 340mV => 160-161 => 420mV 350mV => 160-161 => 420mV 360mV => 169-170 => 440mV 370mV => 136-137 => 360mV 380mV => 144-145 => 380mV 390mV => 146-147 => 380mV 400mV => 149-152 => 400mV Releváns kódrészlet:
A méréshez használt tesz áramkör képe mellékletben. Van bárkinek ötlete, mi okozza vagy hogyan lehet javítani rajta? Segítségeteket előre is köszönöm.
(Nem szólt hozzá senki? Mert ilyenkor szoktak a Modik törölni!)
Csak az első sorod elemzése: ADMUX = (ADMUX&0xE0)|0x00; // ADC0 Induláskór az ADMUX = 0x00; Tehát ADMUX és 0xE0 = 0x00; Tovább 0x00 vagy 0x00 = 0x00; Vagyis nem csináltál semmit az ADMUX regiszterrel! (Szerintem keressél valami Cpp Alapok tankönyvet a Neten!)
Lehet hogy az általad kívánt feladatsor megvalósítható egyetlen, beágyazott ciklusos programmal is amiben a két vagy több "taszk" egymás után kapja meg a processzort.
Ha várakozást szeretnél megvalósítani akkor kelleni fog egy időzítő is, de nem kell interruptot használni. Az időzítésre várakozó "taszk" - ha odaér a program - az időzítő állapotát figyeli, és ha még van hátra belőle akkor továbbugrik a következő programrészre(taszkra). Erre a célra nagyon jól használható a "goto" parancs is a taszk többi részének átugrására. Multitaszk helyett még szokás az állapotgép-modellt használni, az még egyszerűbb is, de a program megírása előtt érdemes a modellt megrajzolni. Papíron... Az interrupt használata a preemptív multitaszk rendszerekhez kell, ami jóval bonyolultabb és nagyobb hardverigényű(flash, RAM, órajel - bár ez utóbbi nem feltétlenül). Lásd: uC/OS. Cserébe a rendszer skálázható lesz, tehát a válaszidő a taszkok számának növekedésével egyenletesen romlik. A hozzászólás módosítva: Jún 29, 2014
A delay 10-s-t ugy kell itt megoldani, hogy mondjuk egy számlálót csökkentesz.
Csak ugye ekkor a 10s nem lesz pontosan annyi. A kérdés, hogy fontos-e pontosan 10s, vagy 8-12-ig minden mehet. A hozzászólás módosítva: Jún 29, 2014
Sziasztok!
Lehet hogy tönkrement a mikrovezérlőm? Már évek óta kísérletezgetek egy ATmega8-as mikrovezérlővel, de most teljesen használhatatlan. A programot tökéletesen befogadja, de nem tudok még egy egyszerű led villogtatót sem csinálni vele. Írtam egy olyan programot ami az összes portot ki és be kapcsolgatja és végigpróbálgattam az ic összes lábát egy leddel és egyiknél sem villog, csak a PB0-s lábnál 10mp-ként(én 500ms-re programoztam). Lehet hogy már elérte a felprogramozási lehetőségek számának a határát?
Szia!
Próbáltad kiolvasni a programot beprogramozás után? Programozáskor az ellenőrzés megvan és rendben is van? Nem lehet, hogy valami bitet (pl 8as órajel osztó) és a LED olyan gyorsan villog, hogy nem is látod?
Sziasztok!
Köszönöm a segítségeket. A probléma már megoldódott. Sajnálom én voltam a figyelmetlen. AVR Studio 4-el írom a programokat és még a régi program hex file volt betallózva a programégető ablakba.
Sziasztok!
A következő a gondom: UART-on kap a mikrokontroller adatot egy GSM modultól, majd egy számot szeretnék integerré konvertálni, de az istennek sem akar működni.
At AT+CSQ elküldése esetén visszaküldi azt hogy "+CSQ: 19,0<cr><lf>". Az RxBuff változót LCD-re kiírattam és benne van a"+CSQ: 19,0<cr><lf>". Mi lehet a gond?
Lényegében ki kell hámoznod a sztringből a két számot. Csak a környezet segít, tehát az első
szám előtt szóköz van és vesszőig tart, a másik a vessző után van és a záró karakterek határolják. Ennél van kicsit egyszerűbb megoldás is, mert "nem-szám" karakterek határolják a számokat:
A hozzászólás módosítva: Júl 5, 2014
Helló!
AVR (Attiny24) lába használható-e úgy, hogy ráteszek egy 150-200ohm körüli ellenállást, ezzel sorba kötök egy led-et, majd a led katódját rákötöm egy npn tranzisztor bázisára? A tranzisztor emittere földre lenne kötve, kollektora pedig egy relé behúzótekercsével lenne sorba kötve. A célom az lenne, hogy az adott reléről vizuális visszajelzésem is legyen. Valami ilyesmi
Egy "sima" npn tranzisztor (nem Darlington) nyitófeszültsége kb. 0.6V, ehhez hozzáadódik a LED nyitófeszültsége ami színtől függően 1.8-3.3V, ha ezt valamivel meghaladja az áramkör tápfeszültsége, akkor működni fog.
Nem hülyeség, de ilyet nem szokás csinálni. A tranzisztor bázisárama töredéke a LED-nek,
ezért egy soros kapcsolás nem túl egészséges még akkor sem ha a tranzisztor egyébként bírja. A másik ellenérv, hogy a LED - ha fényt kap - kapcsain feszültség jelenik meg. Habár ez ellentétes polaritású az "üzemi" polaritáshoz képest, egy zárt kapcsolásban működésbe hozhatja a tranzisztort. Ráadásul a LED nyitófeszültsége jócskán függ a hőmérséklettől. Én a párhuzamos kapcsolást javaslom, egyetlen ellenállással több, illetve kettővel mert a bázis-emitter közé is szokás egy, a bázisellenállással azonos ellenállást rakni. A védődiódát se felejtsd le a relé lábairól...
Az atoi strstr-nek is jónak kell lennie, a programom másik felèben hibátlanul működik. Van rá ötletetek?
Mi a konkret problema az atoi-s megoldassal? Az istennek nem akar mukodni, az nem tul egyertelmu...
Szerintem azért nem működik mert a bemenet nem egy sima szám, hanem egy kevert valami.
Előbb ki kell bányászni belőle a két szám sztringet, utána mehet az atoi. A bányászáshoz az elválasztó karakterek(separators), a sztring környezet jelentenek segítséget. Ehhez a klasszikus sztring műveleteket kell használni: - strncpy - strcasestr Tudom hogy elsőre megoldhatatlan feladatnak látszik egy algoritmus összerakása, de csak így lehet megtanulni. Azt javaslom hogy a GSM modultól független cuccon, saját magad által kreált sztring bemenetekkel játssz, és egyszer csak összejön...
Az atoi-s megoldasod mukodik, elvileg nincs vele semmi baj. Az atoi a megadott cimtol kezdve eldobal minden space-t, majd konvertalja a szamot, amig nem talal barmi nem szamjegy karaktert.
Viszont az strstr() gondot okozhat, ha nincs a string-ben a keresett substring. Mivel addig keres, amig meg nem talalja, tul fog menni az RxBuff-n, es az nem jo. Megoldaskent javaslom az strchr() hasznalatat, ami igaz, csak egy karaktert keres a stringben, de jelzi, ha nem talalja, nem pedig vegigolvassa a teljes memoriateruletet. Ha garantalt, hogy lesz a string-ben "Q:", akkor ez nem erdekes. De garancia nincs semmire, inkabb keszulj fel a nem vart modem valaszra, mintsem elszalljon a programod, es hetekig keresd az okat.
Arra lennek kivancsi, hogy mi zarja le a modem felol erkezo string-et. Az USART ISR nem tesz 0-t a vegere, a GSMWait viszont strcpy()-vel masol. Vagy az a memset() szolgalna erre? Nem tul szerencses, bar mukodik. Egyszerubb lenne a 12. sorban az i = 0 ele beszurni egy RxBuffer[i] = '\0'; es utana az i = 0;
De ami a legfontodsabb, hogy egy globalis valtozo soha ne legyen 'i' vagy egyeb hasonlo rovid nevu. Ilyen neveket lokalis valtozoknak szokas adni. Ha a fuggvenyedben van egy lokalis i valtozo, akkor az i = 0; a lokalist fogja atirni, nem a globalist. Egyebkent miert nem a '\n' karaktert keresed, miert timeout-tal keresed a modem valasz veget? A hozzászólás módosítva: Júl 6, 2014
Köszönöm neked és zombee-nak is a válaszokat.
A helyzet az, hogy a nyák már majdnem kész van, és most jött ez az ötletem, hogy led-es visszajelzést is tennék rá. De úgy tűnik, hogy hanyagolni fogom, eléggé át kellene tervezzem, hogy jó helyre be tudjam pakolni a ledeket. zombee: köszönöm, nem felejtettem el az ellenpárhuzamos diódát sem. SMD 1206 lesz, szépen közéfér a relé lábainak. |
Bejelentkezés
Hirdetés |