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   636 / 837
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Ezt nem igazán értem!
Honnan tudjuk, hogy mikor jön az impulzus, Mikor mérjük, és milyen hosszú?

Ezt inkább szét kellene osztani 2 I/O pinre!
(#) Massawa válasza kapu48 hozzászólására (») Dec 30, 2014 /
 
Az impulzust én generáom az AVR kimenetén, de csak akkor, ha a meghajtott berendezés ezt igényli.
Annak a bemenete ugyanis minden impulzusra billen, nekem meg csak akkor kell billenteni, ha nem jo állapotban van. ( gondolj el egy lámpát. Minden impulzus be illetve kikapcsolja, nekem viszont csak akkor kell kapcsolnom ha pl. nem világit). Szoval mielött ki kiüldök egy impulzust meg kell vizsgálnom, hogy át kell- e egyáltalán kapcsolni a berendezést.
A hozzászólás módosítva: Dec 30, 2014
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Sajnos még mindég én vagyok az értetlen!

Kimenet vezérel >> Bemenetet! Hogyan jön visszajelzés a Bemenetről >> Kimenet fellé???
(#) Massawa válasza kapu48 hozzászólására (») Dec 30, 2014 /
 
A vezérelt cucc is egy AVR-s berendezés ( sok egyforma porttal). A portokra adott impulzusokkal lehet a kimeneteket átbillenteni ( bonyolult impulzussorozatot ad ki). Amint megszünik a bemenetre adott impulzus, ugyanezen a porton jelzi vissza ( pl. egy opcionális LED-el), hogy a kimenet milyen állapotban van. ( gondolj el egy vezérlöpanelt kivilágitott nyomogombokkal, amik fénye jelzi a kezelönek, hogy az adott funkcio aktiv vagy sem, ha sötét meg kell nyomni, ha világit akkor nem).
Az én berendezésem meg hivatott ezeket a gombokat kezelni, azaz bizonyos algoritmus szerint kapcsolgatni a cucc kimenetét - de csak akkor, ha az már nem a kivánt állapotban van. ( mert akkor az ujabb bemeneti impulzusra kikapcsolna).

Az eredeti AVR egy berendezés vezényel 8 kimenetet 8 gombbal vezérelve). Az én AVR meg egy folyamatot vezérel mikor melyik kimenetnek milyen állapotban kell lennie. ( sok egyéb feltétel teljesitése alapján).
A hozzászólás módosítva: Dec 30, 2014
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Nem a kérdésre válaszoltál!

Honnan tudja a Vezérlő, hogy milyen állapotban van a Vezérelt eszköz?
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Mondjuk 1 impulzus érzékelésre valami ilyesmit gondolok:
  1. unsigned char PortPin = (PORTn & PINxMaszk);    // kezdőéerték?
  2. unsigned char t;
  3.        
  4.         do
  5.         while (PortPin != (PORTn & PINxMasz)); // Változásra várunk
  6.         PortPin = PORTn & PINxMasz;     // az új érték
  7.         t = PortPin;    // Az impulzus = ??
  8.         do
  9.         while (PortPin != (PORTn & PINxMasz)); // Változásra várunk
  10.         PortPin = PORTn & PINxMasz;     // az új érték
(#) Massawa válasza kapu48 hozzászólására (») Dec 30, 2014 /
 
Bocs. Az elsö cucc - ami megvan - kepzelj el, hogy 8 ajtot nyit vagy csuk. Minden ajtohoz van egy bemenet, amire adott 0V impulzus az ajtot az ellenkezö állapotba csukja. Ezt az állapotot a bementi portrol ki lehet olvasni.
Azaz a nyomgomb világit, ha az ajto nyitva van.
Az én most épülö berendezésemnek tehát ki kell olvasnia mind a 8 ajto pillanatnyi állapotát, s ha a feladat ugy kivánja egyik másik ajtot csuknia kell a másikokat meg nyitni. Mivel azonban minden impulzus ellenkezö állapotba billenti az ajtot, csak arra a bemenetre küldhetek imoulzust, ahol változnia kell a pillanatnyi állapotnak. Az én berendezésemen van még további 8 bemenet, amik állapota határozza meg, hogy a 8 ajtonak az adott pillanatban milyen állapotban kell lennie.

Kb igy néz most ki a bemenet. A az adott berendezés

Az 1 kohmos ellenálláson küldöm az impulzust ha kell ( attol függ, hogy világit vagy sem a LED.)
A hozzászólás módosítva: Dec 30, 2014

image.jpg
    
(#) Massawa válasza kapu48 hozzászólására (») Dec 30, 2014 /
 
Nem az impulzusra kell várni, hanem eldönteni, hogy kell-e egyáltalán impulzust küldeni a külsö ( uj berendezésböl). Pl. Csak akkor, ha a LED nem világit mehet az impulzus.
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Ez esetben:
A vezérlő Port alapesetben Bemenet, amit beolvasol.
És Pin-enként kiértékelve eldöntöd, hogy kel e vezérlés?
Majd a Port.Pint Kimenetre váltod és az adott Pin-en kiküldöd az impulzust.
A hozzászólás módosítva: Dec 30, 2014
(#) Massawa válasza kapu48 hozzászólására (») Dec 30, 2014 /
 
Azaz, minden portra kell egy rutint irnom, ami elöször beolvassa az állapotot, s ha az nem jo, akkor átvált kimenetre és kiküld egy impulzust, majd visszavált bemenetre.
Jo lesz igy?
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Kel 1 rutin!

Amelynek paraméterekben megadod a vizsgált PORT, PIN értéket.
És eszerint elvégzi az adott portra a műveletet.

Esetleg még vissza is jelez, hogy mit végzett!
A hozzászólás módosítva: Dec 30, 2014
(#) kapu48 válasza Massawa hozzászólására (») Dec 30, 2014 /
 
Kevés segítség!

Amennyiben AtmelStudiot használsz?
Nálam Mega64 esetén.
Megnyitod:
A Solution Explorer ablak, Dependencies > iom64.h (illetve amit használsz?).
Állományban többek között megtalálod a kérdéses I/O Constansok meghatározását.
...
(#) Massawa válasza kapu48 hozzászólására (») Dec 31, 2014 /
 
Studiot használok, de olyasmiröl mint solution explorer még nem is hallottam. Magam irkálom a rutinokat meg mindent. ( asm-ben, minden máshoz hülye vagyok ) .
(#) kapu48 válasza Massawa hozzászólására (») Dec 31, 2014 /
 
Eddig úgy tűnt mintha használtad volna a szabványos:
1. #include <avr/io.h>
2. #include <util/delay.h>
3. #include <avr/interrupt.h>
Fájlokat?
A.Studio > View menü > Solution Explorer ablak, > Dependencies > Ben megtalálod az Projectben alkalmazot összes Header fylet, dupla klik a: iomxx.h

A kérdéses rutint asm-ben is meg írhatod!

Az iomxx.h ismerete csak segítség, a Proci adatlapjának összefoglaló kivonata.
(#) Massawa válasza kapu48 hozzászólására (») Dec 31, 2014 /
 
Valakivel összekeversz.

Az én programjaimban ilyet még soha nem használtam. A gyári rutinok közül szinte kizárolag a chip rutinját használom ( pl. M644pdef.inc). Minden más include parancs a saját kodjaimra utal (equats, macros, eermbs stb.).
Igaz, hogy studio 4-t használok ( egyébb kompatibilitási okok miatt) de abban a VIEW fül alatt nincs Solution explorer).

Nem gond, az asm rutint megirom, s majd azzal vizsgálom a portok állapotát.

Kösz a segitséget.
(#) mucsa hozzászólása Dec 31, 2014 /
 
Üdv uraim.

Erre van az apróhirdetés!
-moderátor-
A hozzászólás módosítva: Dec 31, 2014
(#) kapu48 válasza Massawa hozzászólására (») Dec 31, 2014 /
 
Bocsi!
Tényleg össze kevertelek az előtted kérdezővel! (Akkor a választ neki szántam!)

Viszont az általad felvetett téma részletei is érdekelnének!
Ha az Új évben még vissza térhetünk rá?

Addig is BUÉK mindenkinek!

A hozzászólás módosítva: Dec 31, 2014
(#) Massawa válasza kapu48 hozzászólására (») Dec 31, 2014 /
 
Természetesen! Addig az egészségedre!

B
U
E
K

2015
!!!
(#) holex hozzászólása Jan 1, 2015 /
 
Sziasztok. Az miért van, hogy ha az OCR2A=0, a porton akkor is az idő 0,4%-ában logikai magas szint jelenik meg?
(#) vzoole válasza holex hozzászólására (») Jan 2, 2015 /
 
Ha PWM-re gondolsz, ott én is belefutottam ebbe a hibába.
Arra nem jöttem rá, hogy miért van, de PC PWM-nél nincs ez a jelenség, ezért én azt használtam Fast PWM helyett.
(#) holex válasza vzoole hozzászólására (») Jan 2, 2015 /
 
Köszönöm, PC PWM-mel tényleg jó. Utánanézek Fast PWM-nél miért van így, mert elég fura ez a dolog.
(#) fifadani hozzászólása Jan 2, 2015 /
 
Sziasztok!
Először is BÚÉK!
UV levilágítót szeretnék majd építeni. Ehhez egy mega8-at fogok használni.
Készítettem egy programot, Proteusban tökéletesen működik.
Véleményeznétek? Mivel lehetne szebbé varázsolni? A tanácsokat és az eddigi segítségeket köszönöm szépen...

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #define F_CPU 16000000UL
  4.  
  5.  
  6. volatile unsigned int szam; //globalis valtozok
  7. volatile unsigned char utem1,utem2,start;
  8. //- utem1 a kijelzesnek - utem2 a szamlalasnak(masodpercenkent szamol)
  9.  
  10.  
  11.  
  12. void inits(void)
  13. {
  14.  
  15.         //PORT-ok konfiguralasa
  16.         DDRC |= 0xFF;  //0b11111111 - digitek
  17.         DDRB |=  0x1F; //0b00001111 - szamkijelzes
  18.         DDRD = 0x03;   //0b00000011 - PD0 levilagitas jelzo - PD1 rele
  19.         PORTD |= 0x0C; //0b00001100, belso felhuzo R-ek bekapcsolva
  20.  
  21.  
  22.         //Timer0 konfiguralasa
  23.         TCNT0   = 0;
  24.         TIMSK  |= (1 << TOIE0);             // timer0
  25.         TCCR0 |= (1 << CS02) | (1 << CS00); // Előosztó 1024 , timer indítás 16MHz/1024 = 15625Hz   (15625/255 = 61Hz 1sec)
  26.        
  27.        
  28.         //Kulso megszakitasok, INT0, INT1 konfiguralasa (nyomogombok)
  29.         GICR |= (1<<INT0) | (1<<INT1);
  30.         MCUCR |= (1<<ISC01) | (1<<ISC11); //INT0,INT1 logikai ertekenek valtozasa hozzaletre a megszakitast
  31.        
  32.  
  33.         //Az osszes megszakitas engedelyezese
  34.         sei();
  35.  
  36. }
  37.  
  38.  
  39.  
  40. ISR (INT0_vect) //megszakitas ha START gombot lenyomod
  41. {
  42.  
  43.         start=1;
  44.  
  45. }
  46.  
  47.  
  48. ISR (INT1_vect) //megszakitas ha IDO gombot lenyomod
  49. {
  50.  
  51.         szam+=10;
  52.  
  53. }
  54.  
  55.  
  56. ISR (TIMER0_OVF_vect) //megszakítás rutin, timer0 ha tulcsordul
  57. {                                      
  58.  
  59.         utem1++;
  60.         utem2++;
  61. }
  62.  
  63.  
  64.  
  65.  
  66.  
  67. int main(void)
  68. {
  69.        
  70.         inits(); //beallitasok meghivasa
  71.  
  72.         utem1=0;
  73.         utem2=0;
  74.         szam=10;
  75.         start=0;
  76.  
  77.         PORTC= 0x0F; //PNP tranzisztorok a kijelzokon
  78.  
  79.         while(1)
  80.         {
  81.        
  82.                
  83. //masodperc szamlalas, szam ertekenek figyelese        
  84.                 if(start==1)
  85.                 {
  86.                         PORTD |= (1<<PD0) | (1<<PD1);
  87.  
  88.                         if(utem2>=61)
  89.                         {
  90.                                 szam--;
  91.                                 utem2=0;
  92.                         }
  93.                 }
  94.  
  95.                 if(szam>=630) // max 10,5 perc levilagitasi ido
  96.                 {
  97.                         szam=10;
  98.                 }
  99.                
  100.                 if(szam<1) //ha szam kissebb mint 1, akkor rele es a muk.jelzo led kikapcs.
  101.                 {
  102.  
  103.                         start=0;
  104.                         PORTD &= ~(1<<PD0);
  105.                         PORTD &= ~(1<<PD1);
  106.                         szam=10;
  107.                                
  108.                 }
  109.  
  110.  
  111. //szamkijelzes
  112.                 if(utem1==10)
  113.                 {
  114.                        
  115.                         PORTC = ~(1<<PC0);
  116.                         PORTB = szam/100; //szazasok
  117.                        
  118.                 }
  119.  
  120.                 if(utem1>=20)
  121.                 {
  122.                         PORTC = ~(1<<PC1);
  123.                         PORTB = (szam%100)/10; //tizesek
  124.        
  125.                 }
  126.                
  127.                 if(utem1>=30)
  128.                 {
  129.                
  130.                         PORTC = ~(1<<PC2);
  131.                         PORTB = (szam%100)%10; //egyesek
  132.                         utem1=0;       
  133.                 }
  134.                
  135.        
  136.        
  137.         }      
  138.  
  139. return 0;
  140. }
A hozzászólás módosítva: Jan 2, 2015
(#) kapu48 válasza fifadani hozzászólására (») Jan 2, 2015 /
 
  1. 1.      //Ezt a számkijelzést nem igazán értem?
  2. 2.      // 7 szegmenses multiplexelt kijelzésről lenne szó?
  3. 3.                      if(utem1==10)   // Ez az ág csak 1* hajtódik végre
  4. 4.                      {
  5. 5.                             
  6. 6.                              PORTC = ~(1<<PC0);
  7. 7.                              PORTB = szam/100; //szazasok
  8. 8.                             
  9. 9.                      }
  10. 10.      
  11. 11.                     if(utem1>=20)   // Ez itt 10secig ahányszor csak ráfut a program (ez lehet pár 1000 végrehajtás!)?
  12. 12.                     {
  13. 13.                             PORTC = ~(1<<PC1);
  14. 14.                             PORTB = (szam%100)/10; //tizesek
  15. 15.            
  16. 16.                     }
  17. 17.                    
  18. 18.                     if(utem1>=30)   // ez megint csak 1* fut le, mert rögtön utem1=0
  19. 19.                     {
  20. 20.                    
  21. 21.                             PORTC = ~(1<<PC2);
  22. 22.                             PORTB = (szam%100)%10; //egyesek
  23. 23.                             utem1=0;      
  24. 24.                     }
  25. 25.       // Nem igazán tiszta ez a működés?            
  26. 26.            
  27. 27.            
  28. 28.             }

(#) Lucifer válasza fifadani hozzászólására (») Jan 2, 2015 /
 
Valami prellmentesítést tegyél a gombokra. A start még működhet is, de az IDO gomb lenyomásakor nem egy hanem több INT1 fog generálódni, ami meg fogja nehezíteni az idő beállítását .
(#) holex hozzászólása Jan 2, 2015 /
 
Sziasztok. Van egy érdekes problémám: a watchdogtól lefagy a mikrokontroller.
Bekonfigolom a main elején így:
wdt_reset();
WDTCSR = (1<<WDCE)|(1<<WDE);
WDTCSR = (1<<WDE)|(1<<WDP1)|(1<<WDP2);

És a while elején mindig resetelem.

Ettől elvileg 1 mp után resetelnie kéne a mikrokontrollernek, ha nem fut le a while ennyi idő alatt. Ha próbaképpen berakok egy _delay_ms(1500)-at, akkor viszont lefagy az egész, csak a tápfesz levételével és újra ráadásával lehet újraindítani, de persze amikor elér az 1500ms-os késleltetéshez a program, akkor újra lefagy. Mi ennek az oka?

Szerk: ha a wdt.h könyvtárat használom és így állítom be az elején:
wdt_reset();
wdt_enable(WDTO_1S);

és a while-ban resetelek, akkor teljesen jó, az 1500 ms-os delaynél újraindul a mikrokontroller.

Akkor már csak egy kérdés maradt: mit rontottam el?
A hozzászólás módosítva: Jan 2, 2015
(#) rolandgw válasza holex hozzászólására (») Jan 2, 2015 /
 
Csak a headert használd.Ez első esetben a fordító az optimalizációtól függően szétdobhatja a két setup sort,aminek szigorúan követnie kell egymást.Egyébként cli/sei közé is kell tenni.
(#) fifadani válasza kapu48 hozzászólására (») Jan 2, 2015 /
 
Igen az lenne.
Javítottam.
Köszi
A hozzászólás módosítva: Jan 2, 2015
(#) holex válasza rolandgw hozzászólására (») Jan 3, 2015 /
 
Rendben, köszi.
(#) fifadani válasza Lucifer hozzászólására (») Jan 3, 2015 /
 
Szép estét, sziasztok!
Prell-mentesítésnek jó ez a megoldás?

ISR-ben kikapcsolom a megszakítást.
Timer0 segítségével másodpercenként megnézem hogy ki van-e kapcsolva a megszakítás, ha igen akkor vissza kapcsolom.
  1. ISR (TIMER0_OVF_vect) //megszakítás rutin, timer0 ha tulcsordul
  2. {                                      
  3.  
  4.         utem1++;        //kijelzes utemezoje
  5.         utem2++;        //masodperc eloallitasa
  6.         utem3++;        //megszakitas visszakapcsolasahoz
  7. }
  8.  
  9. ISR (INT0_vect) //megszakitas ha START gombot lenyomod
  10. {
  11.  
  12.         start=1;
  13.         GICR &= ~(1<<INT0); //INT0 megszak kikapcsolasa
  14. }
  15.  while(1)
  16. {
  17.         if(utem3==244)
  18.         {
  19.  
  20.                 if((GICR &(1<<INT0)) == 0)
  21.                 {
  22.  
  23.                 GIFR |= (1<<INTF0);        // INT0-hoz tartozo jelzobit torlese
  24.                 GICR |= (1<<INT0);        // INT0 megszakitas engedelyezese
  25.                 utem3=0;
  26.  
  27.                 }
  28.         }


Működni működik, szerintetek jó így?
Köszi szépen.
(#) killbill válasza fifadani hozzászólására (») Jan 4, 2015 /
 
Szia!
Felesleges bonyolitas es a megszakitas kulonben sem arra valo, hogy nyomogombokat erzekelj vele, bar ketsegtelenul lehet arra is hasznalni. A foprogramodban 20..50ms idonkent nezd meg a gomb allapotat es ha megvaltozott az elozo vizsgalat ota, akkor lenyomtak vagy felengedtek. Ez a modszer automatikusan kiszedi a prellezest es nem igenyel kulon megszakitast. Azon felul ezzel tobb gombot is lehet kezelni, akar egesz billentyumatrixokat. Elsore talan bonyolultnak tunhet, de abbol indul ki a dolog, hogy valami idoalap mindenkeppen van a programban, ahogy a tiedben is van.

  1. /*
  2.  * Ezt a fuggvenyt 20..50ms-onkent kell meghivni.
  3.  * Ha megnyomtak a gombot, akkor 1-et ad vissza, egyebkent 0-t
  4.  */
  5. int testbutton(void)
  6. {
  7. /*
  8.  * Ennek a valtozonak az erteke akkor is megmarad,
  9.  * ha a fuggveny visszater. Kezdeti erteke 0 lesz.
  10.  * Ez a valtozo a tobbi fuggveny szamara lathatatlan, es ez igy van jol
  11.  */
  12. static char laststate;
  13.  
  14. /*
  15.  * ez egy sima lokal valtozo
  16.  */
  17. char x;
  18.  
  19.   /*
  20.    * beolvassuk a gomb allapotat. x=1 ha nyomjak, x=0 ha nem (A gomb GND-t ad a labra)
  21.    */
  22.   x = !(PINB & (1 << PINB0));  // mondjuk a gomb a B port 0 biten van
  23.  
  24.   if(laststate != x){   // megvaltozott
  25.      laststate = x;      // eltaroljuk az uj erteket
  26.      if(x == 1)           // benyomtak
  27.         return 1;
  28.   }
  29.   return 0;
  30. }
Következő: »»   636 / 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