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   255 / 840
(#) kovacsj válasza zolee1209 hozzászólására (») Júl 30, 2010 /
 
Ez csak egy próba. Azt próbálgattam vele, hogy ha bekattintom a szimulátoron a 0.bitet (PINB), akkor meghívja-e a szubrutint. Igazából a státusz regiszter bitjeit és a különböző Assembly utasításokat próbálgatom csak úgy minden cél nélkül.
De jó lenne tudni, hogy ha a szimulátorban a program legelejére ugrik a mutató, akkor a valóságban is úgy van?
Mert lehet ott olyan utasítás is ami éppen felülírja a stackból elővett regiszter tartalmát.

Kipróbáltam a te verziódat - ami lényegesen kiforrottabb az enyémnél - de a ret utasítás után az "rjmp reset" sorra ugrott vissza. Én meg azt hittem, hogy a "jmp program"-ra kellene. Vagy mégsem így van?
(#) vilmosd válasza kovacsj hozzászólására (») Júl 30, 2010 /
 
Hali
Nem vagyok atmeles, de a szubrutint altalaban nem "jmp" utasitassal erjuk el, hanem "call" utasitassal. Tehat:
  1. breq megnyomva
  2. jmp program
helyett :
  1. rcall megnyomva
  2. jmp program
lenne a helyes. Igy termeszetes hogy "0" cimre ugrik , mert a stack "00" cimet tartalmaz, nem a meghivas helyenek a cimet.
Udv Vili
(#) kovacsj válasza vilmosd hozzászólására (») Júl 30, 2010 /
 
Ezek szerint a breq és a hozzá hasonló utasításokkal nem lehet szubrutint hívni?

[szerk] Megvilágosodtam! Hát pesze, hogy nem! Köszönöm mindkettőtöknek!
(#) vilmosd válasza kovacsj hozzászólására (») Júl 30, 2010 /
 
Hali
Az egyik tipus ugro utasitas, a masik hivo. Azert jo a "call" utasitas, mert mikor sokszor kell hasznalni ugyanazon utasitasok sorozatat ( Pl. "delay" ), egyszer megirod a szubrutint, es ezerszer is meghivhatod. Viszont a kodban csak egyszer kerul bele.
Udv Vili
(#) kovacsj válasza vilmosd hozzászólására (») Júl 30, 2010 /
 
Közben már rájöttem, de azért itt is megköszönöm.
Sokat segítettetek.
(#) zolee1209 válasza kovacsj hozzászólására (») Júl 30, 2010 /
 
Szia!
Elég nagy butaságot írtam...

  1. .org 0x000
  2. rjmp reset
  3.  
  4. portini:
  5. ldi r16,0
  6. out ddrb,r16 ;portb bemenet
  7. ldi r16,255
  8. out ddrc,r16 ;portc kimenet
  9. ldi r17,1
  10.  
  11. program:
  12. in r16,pinb
  13. cp r16,r17
  14. breq megnyomva
  15. jmp program
  16.  
  17. megnyomva:
  18. inc r18
  19. out portc,r18
  20. jmp     program
  21.  
  22. reset:
  23. ldi r16,low(ramend)
  24. out spl,r16
  25. ldi r16,high(ramend)
  26. out sph,r16
  27. rjmp portini


A "breq" elágazás után nem "ret"-tel kell visszatérni, mivel nem szubrutin hívás (call) történt... Bocsi a félreértés végett, még én sem vagyok profi...
(#) kovacsj válasza zolee1209 hozzászólására (») Júl 30, 2010 /
 
Viszont ezzel a részlettel is nagyon sokat segítettél.
Majd jövök még biztosan.

Köszönöm ismét mindkettőtöknek!
(#) zsuscsinyo válasza Topi hozzászólására (») Júl 31, 2010 /
 
Igazából ezzel még nem volt dolgom, tudnál adni valami forrást hozzá, hogy tudnék elindulni rajta? Előre is nagyon köszönöm!
(#) Axel hozzászólása Júl 31, 2010 /
 
Sziasztok!

Lassan készen van a tervezett "beléptetőrendszerem" szoftvere. Már csak egy apró részlet vár megoldásra. Ez pedig az, hogy adott idő eltelte után (10sec pl.) a beütött kódot nullázza ki. Azért hogy, ha véletlen megnyomódik egy gomb ne legyen letárolva annak értéke ki tudja meddig. Remélem érthetően fogalmaztam. Az általam megírt beolvasásért felelős függvényt egy for ciklus hívja meg annyiszor ahány jegyű a kód. Miután a függvény a beolvasott értékkel visszatér elindul egy számláló ami minden gombnyomáskor nullázódik. Ha viszont eléri az adott időtartamhoz tartozó értéket akkor az egész kód beolvasása kezdődik elölről. Hogyan oldható ez meg melyik timer modul-t használjam hozzá? Egyáltalán jó-e ez így ahogy elképzelem?

Köszönöm!
(#) atya válasza Axel hozzászólására (») Júl 31, 2010 /
 
(#) atya hozzászólása Júl 31, 2010 /
 
Nekem viszont a promlemam a kovetkezo:
  1. int main()
  2. {
  3.         init();
  4.         sei();
  5.  
  6.         while(1)
  7.         {
  8.                 gombok();
  9.         }
  10. }
  11.  
  12. ...
  13.  
  14. void init()
  15. {
  16.         //===IO===
  17.         DDRA = 0xFF;
  18.         DDRB = 0;
  19.         DDRC = 0xFF;
  20.         DDRD = 0;
  21.         PORTD = 0xFF;
  22.  
  23.         if(!(PIND & (1<<MNB))) {
  24.                 setup();
  25.         }
  26. ...
  27. }
  28.  
  29. void setup()
  30. {
  31.         flash_PA(2);
  32.  
  33.         while(!(PIND & (1<<MNB)))
  34.         {
  35.                 ++PORTA;
  36.                 //_delay_ms(65);
  37.         }
  38.  
  39.         while(PIND & (1<<MNB))
  40.         {
  41.                 if(!(PIND & (1<<UPB)))
  42.                 {
  43.                         ++temp;
  44.                 }
  45.                 if(!(PIND & (1<<DNB)))
  46.                 {
  47.                         --temp;
  48.                 }
  49.                 display(temp);
  50.                 _delay_ms(65);
  51.         }
  52.         //eepromba iras
  53. }


Konstrukcio a kovetkezo:
GND =vezetek=> gomb1-2-3 =vezetek=> PIND 5-6-7
Igy elvileg akkor van 0 a PIN-en, ha a gomb le van nyomva.
Namarmost miutan az EEPROM-ba iras megtortenik, a main fv elejere ugrik a progi, es a PIND7-re meno gomb allapotatol fuggetlenul ugrik be a setup fv-be.

Mit rontok el? Gyanitom valami nagyon alapveto dologrol van teves elkepzelesem

szerk:
Az AVRstudio debugere azt mutatja, hogy a gombok() fv hivasakor ugrik vissza a main() elejere.
(#) kovacsj válasza atya hozzászólására (») Júl 31, 2010 /
 
Van gombok() függvény? Mert itt nem látszik.
(#) atya válasza kovacsj hozzászólására (») Júl 31, 2010 /
 
termeszetesen.

Most igy probalkoztam:
  1. void init()
  2. {
  3.         //===INTERRUPTS===
  4.         SREG |= (1<<7);
  5.         GICR  = (1<<7);         //INT0 enable // PIND2
  6.         MCUCR = (MCUCR | 3);// ISC00=1 ISC01=1 => rising edge


Ennek hatasara, amikor a debuger a MCUCR =... sorhoz er, akkor urik vissza a main elejere.

ISTENEM!

Az INT1 lab egy sajat kommunikacios protokollhoz kell. Namarmost jol latszik, hogy komment szerint INT0-t kapcsolok be, de az egy masik projectben vmiert nem mukodott rendesen ( talan mar arra is rajottem ), ezert attettem INT1-re. Mivel mellette pont szabad volt egy lab, igy inkabb ebben a projectben is atirtam, azonban az ISR(INT0_vect)-et nem.
Ha jol tudom MCUCR/GICR valtozaskor generalodik egy interrupt, es ennek a kezelojet kereste volna, es mivel azt nem irtam at, ugrott a main elejere.
(#) atya válasza atya hozzászólására (») Júl 31, 2010 /
 
Meg mindig nem jo.. Viszont most mar a debuger szerint mukodnie kellene.

Megprobalom kideriteni honnan ugrik vissza, mert igy dbg nelkul fogalmam sincs.
(#) Axel hozzászólása Aug 2, 2010 /
 
Sziasztok!

Jól értelmezem, hogy Attiny45-nél a TCNT0 egy olyan 8 bites regiszter melynek értéke minden ("x" előosztás esetén F_CPU/x) órajel után inkrementálódik és nullázni/megállítani ezt a számlálót a TCCR0=0x00; paranccsal lehet? Valamint a flag bit szerepe az, hogy túlcsordulás (TCNT0=255 elérése) után 1 értéket vesz fel? Egyelőre csak tapogatózom a Timereket illetően, remélem nem kérdeztem túl nagy hülyeséget

Köszönöm szépen!
(#) zolee1209 hozzászólása Aug 2, 2010 /
 
Bővebben: Link
Észreveszitek a hibát? Én még agyalok, hogy vegyek-e ilyet...
(#) Topi válasza zolee1209 hozzászólására (») Aug 2, 2010 /
 
Legalább elfér egy kis nyákon.
(#) zolee1209 válasza Topi hozzászólására (») Aug 2, 2010 /
 
Táp és kvarc kell csak neki, és már megy is a cucc!
(#) tej válasza zolee1209 hozzászólására (») Aug 4, 2010 /
 
visszapillantó fűtésnek ideális
(#) Ricsi89 hozzászólása Aug 4, 2010 /
 
Helló!
Atmega8-nál használom az I2C portot és 7szegmenses kijelzőhöz multiplexnél használnám még az alsó 4 bitjét a C portnak a digitek meghajtásához. Nem fogja zavarni egymást, hogy az I2c is a C porton van, és én is használnám közben a port többi részét?
(#) gtk válasza Ricsi89 hozzászólására (») Aug 4, 2010 /
 
Hat ha zavarna az eleg kenyelmetlen lenne Atmelre nezve.
(#) (Felhasználó 4577) válasza Ricsi89 hozzászólására (») Aug 4, 2010 /
 
Ha megfelelően kezeled a regisztereket, akkor nem kellene zavarnia.
(#) Ricsi89 hozzászólása Aug 4, 2010 /
 
Oké, köszi a válaszokat. Már csak egy gondom van. Csináltam egy egyszerű megszakítás alapon működő multiplexelést, de nem megy sehogy. VFd kijelzőt használok, ehhez van csinálva a program is. Világít az összes szegmens, tehát a portok nullán vannak, pedig már a program elején mindkét portot magas szintre kapcsolom. Ötlet?
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include <avr/interrupt.h>
  4.  
  5. #define szegmens PORTB
  6. #define digit PORTC
  7.  
  8. unsigned int seg[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
  9. unsigned int szam;
  10.  
  11.  
  12.  
  13.  
  14. int main()
  15. {
  16.     TCCR0 = (1<<CS01);
  17.     TCNT0 = 0x00;
  18.     TIMSK = (1<<TOIE0);
  19.     DDRB=0xFF;
  20.     DDRC=0xFF;
  21.         PORTC = 0xFF;
  22.         PORTB = 0xFF;
  23.  
  24.    
  25.         sei();
  26.        
  27.         szam = 1234;  
  28.        
  29.        
  30.  
  31. return 0;
  32. }
  33.  
  34. ISR(TIMER0_OVF_vect){
  35.  
  36.         cli();
  37.         digit = (1<<0);
  38.         szegmens = seg[szam%10];
  39.         _delay_ms(5);
  40.         digit = (1<<1);
  41.         szegmens =  seg[szam/10];
  42.         _delay_ms(5);
  43.         digit = (1<<2);
  44.         szegmens =  seg[szam/100];
  45.         _delay_ms(5);
  46.         digit = (1<<3);
  47.         szegmens =  seg[szam/1000];
  48.         _delay_ms(5);
  49.        
  50.         TCNT0=0x00;
  51.         sei();
  52.        
  53. }
(#) levi18 válasza Ricsi89 hozzászólására (») Aug 4, 2010 /
 
Szia!
Én úgy látom, mintha, nem lenne benne végtelen ciklus.
A main()- ből milliszekundumon belül kiér a program és visszatér 0-val.
Javaslatom, hogy a
  1. szam = 1234;
után tegyél be egy
ilyet:
  1. for(;;) {;}

A végtelen ciklusod amikor fut, attól az interrupt ugyanúgy be fog következni. Remélem tudtam segíteni.
Üdv!
(#) Ricsi89 válasza levi18 hozzászólására (») Aug 4, 2010 /
 
Sajnos ez sem segít(egyébként volt benne, de akkor sem ment), mintha el sem indulna a processzor, mert a portokat sem húzza fel magas szintre. Eddig tökéletesen ment ez a proci, csak most ezzel nem akar menni.
Szerk.: Hülye voltam és figyelmetlen. Nem is azt a programot töltöttem bele. Megviccelt az avr studio.
(#) Ricsi89 válasza Ricsi89 hozzászólására (») Aug 4, 2010 /
 
Valami még mindig nem jó. elindul most rendesen, majd 2-3s múlva kiakad és csak 1 digiten mutat egy számot és kész. Áramtalanítás után megint meg pár másodpercig és kész, megint megadja magát.
(#) Topi válasza Ricsi89 hozzászólására (») Aug 4, 2010 /
 
Ne hívj delay-t interruptban. Alapszabály és vérzik a processzor tőle.
Használj státusz változót, és egyszerre, egy interruptban csak 1 számjegyet frissíts.
(#) Hp41C válasza Ricsi89 hozzászólására (») Aug 4, 2010 / 1
 
Szia!

Ha a szám 1234 decimálisan, akkor a 38. sor még jó, hiszen a (szám % 10) értéke 0..9 közé esik.
A 41. sor már túlcímez a tömbön, hiszen a 1234 / 10 = 123, ami nagyobb, mint 9. Ide a
  1. szegmens =  seg[(szam/10) % 10];

kellene.
Ugyanígy a 44. sor is túlcímez a seg tömbön, ide a
  1. szegmens =  seg[(szam/100) % 10];

kellene. A 47. sor csak azért jó, mert a szam <10000.
(#) Topi válasza Hp41C hozzászólására (») Aug 4, 2010 / 1
 
Valóban ezzel is gond lehet, sőt.

Egyébként ilyet inkább úgy célszerű megírni, hogy van egy tömböd...

  1. unsigned char act_display[4];
  2. volatile unsigned char act_digit;
  3.  
  4. ...
  5. ...
  6.  
  7. ISR(..) {
  8.   digit = 0xFF; //kikapcsolsz mindent, hogy ne legyen "derengés"
  9.   szegmens = seg[act_display[act_digit]]; //kiteszed az adatot
  10.   digit &= ~(1<<act_digit); //"bekapcsolod" a digitet
  11.   act_digit++;
  12.   if(act_digit>3) act_digit = 0;
  13. } //isr
  14.  
  15. int main() {
  16.     unsigned short tmp16;
  17.   ..
  18.   ..
  19.   szam = 1234;
  20.   act_digit = 0;
  21.  
  22.   for(;;) {
  23.     tmp16 = szam; //ha a szám globális, akkor eltesszük, mert a számmá alakítás elrontaná a tartalmát.
  24.     act_display[0] = tmp16/1000; tmp16 %= 1000;
  25.     act_display[1] = tmp16/100; tmp16 %= 100;
  26.     act_display[2] = tmp16/10; tmp16 %= 10;
  27.     act_display[3] = tmp16;
  28.     ...
  29.     ...
  30.     //ide delay vagy további folyamat jön.
  31.   } //for
  32. } //func
(#) zsozsoX hozzászólása Aug 4, 2010 /
 
Sziasztok!
Egy stoppert készítenék aminek nem kell atomóra pontosnak lennie de századmp-t mérne. Szerintetek használjak simán delay-t végtelenitett ciklussal vagy a Timer-ral probálkozzak?
Következő: »»   255 / 840
Bejelentkezés

Belépés

Hirdetés
XDT.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