Fórum témák

» Több friss téma
Fórum » AVR - Miértek hogyanok
 
Témaindító: pakibec, idő: Márc 11, 2006
Témakörök:
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
Lapozás: OK   610 / 837
(#) Massawa válasza rolandgw hozzászólására (») Jún 25, 2014 /
 
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
(#) rolandgw válasza Massawa hozzászólására (») 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.
(#) Massawa válasza rolandgw hozzászólására (») Jún 25, 2014 /
 
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.......
(#) srac321 hozzászólása Jún 26, 2014 /
 
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?
(#) kapu48 válasza srac321 hozzászólására (») Jún 26, 2014 / 1
 
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!)
(#) TavIR-AVR válasza srac321 hozzászólására (») Jún 26, 2014 / 1
 
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.
(#) killbill válasza TavIR-AVR hozzászólására (») Jún 26, 2014 /
 
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.
(#) kapu48 válasza TavIR-AVR hozzászólására (») Jún 26, 2014 /
 
Direkt ki hangsújozta, hogy Ő kezdő és, "(Timer használata nélkül)"!

Kissé komolytalan Preemptív multitaskot ajánlani!
(#) Massawa hozzászólása Jún 26, 2014 /
 
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.
(#) dc001 hozzászólása Jún 28, 2014 /
 
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:
  1. int main(void) {
  2.     unsigned int adcval;
  3.     ...
  4.     ADMUX = (ADMUX&0xE0)|0x00;                  // ADC0
  5.     ADMUX | =(1<<REFS1)|(1<<REFS0);             // Uref: 2,56V
  6.     ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // prescale: 128, 12MHz -> 93.75 kHz
  7.     ...
  8.     while(1) {
  9.         ADCSRA |= (1<<ADEN);                    // ADC on
  10.         ADMUX = (ADMUX & 0b11110000) | 0x00;    // ADC0
  11.         ADCSRA |= (1<<ADSC);
  12.         while (ADCSRA & (1<<ADSC));
  13.         ADCSRA |= (1<<ADSC);
  14.         while (ADCSRA & (1<<ADSC));
  15.         adcval = ADC;
  16.         ADCSRA &= ~(1<<ADEN);                   // ADC off
  17.         ...     // adcval kiiras LCD-re
  18.         _delay_ms(100);
  19.     }
  20. }


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.

adc.jpg
    
(#) kapu48 válasza dc001 hozzászólására (») Jún 29, 2014 /
 
(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!)
(#) zombee válasza srac321 hozzászólására (») Jún 29, 2014 / 1
 
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
(#) csabeszq válasza srac321 hozzászólására (») Jún 29, 2014 / 1
 
A delay 10-s-t ugy kell itt megoldani, hogy mondjuk egy számlálót csökkentesz.

  1. if( !szamlalo )
  2. {
  3.   if (adc_1 > x) {
  4.     szamlalo = valamennyi;
  5.   }
  6. }
  7. else if ( ! --szamlalo )
  8. {
  9.    újbóli ellenőrzés; PB1 ON delay 10s; PB1 OFF; PB2 ON
  10. }
  11.  
  12. if (adc_2 > y) { PB3 ON, delay 2s; PB3 OFF; delay 2s; } // ez fusson folyamatosan


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
(#) kissto hozzászólása Jún 29, 2014 /
 
Sziasztok!

Egy Atmega128-as mikrokontrollerre SPI porton csatoltam egy ENC28J60-as chipet.
Van mód arra, hogy emellé egy TLC5940-es LED vezérlőt is csatolhassak?
Csinált már valaki hasonlót?

A válaszokat előre is köszönöm!
(#) Robi98 hozzászólása Júl 1, 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?
(#) kiborg válasza Robi98 hozzászólására (») Júl 2, 2014 /
 
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?
(#) csabeszq válasza Robi98 hozzászólására (») Júl 2, 2014 /
 
A távjavítás elég nehezen működik. Vennék a helyedben egy másik Atmega8-at (inkább Atmega88-at). Próbáld ki és ha az újjal megy akkor a régi elromlott.

A kérdésre a válasz kb. 1000 Ft-ba kerül.
A hozzászólás módosítva: Júl 2, 2014
(#) kissto válasza Robi98 hozzászólására (») Júl 2, 2014 /
 
Szia!
Égetőt ha lehúzod róla?
(#) Robi98 válasza kiborg hozzászólására (») Júl 5, 2014 /
 
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.
(#) Droot hozzászólása Júl 5, 2014 /
 
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.

  1. ISR (USART_RXC_vect)
  2. {
  3.         RxBuffer[i]=UDR; //berakjuk a bufferbe az adatokat
  4.         i++;
  5.         TCNT0 = 0x00; //Timer Counter 0-zása
  6. }
  7.  
  8. void GSMWaitFor(char * rpy)
  9. {
  10.         while( USARTTimeOut < UARTRCT-1 );// && RxEnd == 1);
  11.         USARTTimeOut = 0; //usart timeout counter nullázása
  12.         i = 0; //szting counter 0-zása
  13.  
  14.         strcpy((char *)rpy, (char *)RxBuffer);
  15.         memset((char *)RxBuffer, '\0', sizeof RxBuffer);
  16. }
  17.  
  18. main-ben:
  19.  
  20. UARTsendTEXT("AT+CSQ\r");
  21. GSMWaitFor(RxBuff);
  22.  
  23. quality=atoi(strstr(RxBuff, "Q:")+3);


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?
(#) zombee válasza Droot hozzászólására (») Júl 5, 2014 /
 
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:
  1. char* TEXT;  //<-- ebbe van a kérdéses sztring
  2. int x = -1; //első kimenet
  3. int y = -1; //második kimenet
  4. uint8_t   s = 0; //állapotváltozó;
  5. uint16_t cnt = 0; //számláló
  6. for(;;)
  7. {
  8.   if(!ch) break;
  9.   char ch = TEXT[cnt];
  10.   if(ch>='0' && ch<='9') switch(s)
  11.   {
  12.     case 0: //várakozik a legelső számra
  13.       s++;
  14.       x=ch-'0';
  15.       break;
  16.     case 1: //első szám feldolgozása
  17.       x=x*10+(ch-'0');
  18.       break;
  19.     case 2: //várakozás a második számra
  20.       s++;
  21.       y=ch-'0';
  22.       break;
  23.     case 3: //második szám feldolgozása
  24.       y=y*10+(ch-'0');
  25.       break;
  26.   }
  27. else
  28.   {
  29.     if(s==1) s++;   //ha az első szám feldolgozása befejeződik, jöhet a következő
  30.     if(s==3) break;  //a második szám után már nem kell konvertálni
  31.   }
  32. cnt++;
  33. }
A hozzászólás módosítva: Júl 5, 2014
(#) yohnsee hozzászólása 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
(#) varttina válasza yohnsee hozzászólására (») Júl 5, 2014 /
 
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.
(#) zombee válasza yohnsee hozzászólására (») Júl 6, 2014 /
 
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...
(#) Droot válasza zombee hozzászólására (») Júl 6, 2014 /
 
Az atoi strstr-nek is jónak kell lennie, a programom másik felèben hibátlanul működik. Van rá ötletetek?
(#) killbill válasza Droot hozzászólására (») Júl 6, 2014 /
 
Mi a konkret problema az atoi-s megoldassal? Az istennek nem akar mukodni, az nem tul egyertelmu...
(#) zombee válasza Droot hozzászólására (») Júl 6, 2014 1 /
 
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...
(#) killbill válasza Droot hozzászólására (») Júl 6, 2014 /
 
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.

  1. const char *x;
  2.  
  3.  x = strchr(RxBuff, ':');
  4.  if(x == NULL)
  5.     NincsBenneKettospont();
  6.  else
  7.     qual = atoi(x+1);
(#) killbill válasza Droot hozzászólására (») Júl 6, 2014 /
 
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
(#) yohnsee válasza varttina hozzászólására (») 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.
Következő: »»   610 / 837
Bejelentkezés

Belépés

Hirdetés
Lapoda.hu     XDT.hu     HEStore.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem