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
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   666 / 666
(#) rolandgw válasza krisztianAMG hozzászólására (») Vas, 17:09 /
 
Nem Mega16,de az Avr242 app. note segíthet,ha járatos vagy az asm-ben.
(#) zombee válasza krisztianAMG hozzászólására (») Vas, 17:35 / 1
 
Tartok tőle hogy ezt senki nem fogja megírni neked.

Ott kellene elindulni hogy a kijelzőt multiplexálod, amihez egy időzítő megszakítást használsz. Az időzítőt úgy állítsd be hogy 1-5 ms - enként megszakítást generál. A megszakításrutinban egyrészt kezeled a multiplexálást, utána növeled az óra számlálóját és feltételes láncban (pl. "ha eléri a 60-at a másodperc akkor...") végigmész a kijelzendő értékek számlálóin is. Igazából a "főprogram" nem fog semmit sem csinálni, mindent a megszakításrutin kezel le. Esetleg nyomógomb kezelést beletehetsz amivel az óra beállítható.
(#) csatti2 válasza zombee hozzászólására (») Vas, 19:55 /
 
Én inkább kihasználnám, hogy ez a uC is támogatja az asszinkron módot az egyik időzítőnél (timer 2) egy külső kristállyal. Ha a programhoz a belső oszcillátort használja és ráköt egy külső 32.768kHz-es kristályt akkor egy jól kezelhető és pontos órát kap. Annyi dolga van csak, hogy asszinkron módra kapcsolja a T2-t, majd úgy állítja be a regisztereket, hogy minden másodpercben hívja meg a megszakítást (esetleg fél másodpercenként vagy hasonló módon, hogy a pontokat is villogtathassa a hétszegmenses kijelzőn). A program többi részén így már időzítenie sem kell, alárendelhet minden mást az idő beállításának (gombok, PCINT megszakítással) és kijelzőn megjelenítésének.
Továbbfejlesztési lehetősége, ha betesz egy plusz 3V-os gombelemet és figyeli, hogy leesik-e a betáp fesz. Ha igen, akkor leáll a kijelző meghajtással és energiatakarékos módra kapcsol, ahol csak a külső kristály meghajtása a fontos (meg az idő követése).
(#) kapu48 válasza krisztianAMG hozzászólására (») Vas, 23:47 /
 
Lásd, milyen jó vagyok hozzád!
Elvezetlek a megoldáshoz!

Bővebben: Link
Alul jobbra: avr-source

Digital clock with ATmega16 and 7-segment displays
Bővebben: Link
(#) killbill válasza krisztianAMG hozzászólására (») Hé, 0:28 /
 
Az assembler az a fordito program maga, ami az assembly nyelven irt forrast forditja. Szoval nem assembrelben, hanem assembly-ben lehet programot irni.
(#) zombee válasza csatti2 hozzászólására (») Hé, 3:25 /
 
Ennek az a szépséghibája hogy fél-egymásodperces megszakítással a kijelzőt nem fogja multiplexálni. Mindenképp kell egy gyorsabb időzítő megszakítása is, de ez akár a T2 is lehet aszinkron módban kisebb előosztóval.
(#) kapu48 válasza zombee hozzászólására (») Hé, 3:29 /
 
Rajta javítsátok ki!
(#) csatti2 válasza zombee hozzászólására (») Hé, 5:45 /
 
Nem feledkeztem meg róla. Egyszerűen mivel csak ennyi a program a kijelző frissithető úgy, ahogy csak a csövön kifér, nincs szükség külön időzítőre.
(#) csabeszq válasza wbt hozzászólására (») Hé, 11:18 /
 
Az I2C az sosem egyszerű, pláne kezdő szinten.

Nekem is napjaim mentek ez azzal, hogy megpróbáljam kitalálni, hogy mi a fene baj van.
Azóta vettem 2000 pénzért az Ebay-en logikai jelanalizátort és a fejlesztési idő drámaian lecsökkent.

Az 1-2-3 hónap idő kezdőként reális. Ennél gyorsabb, ha veszel egy Arduino-t és a kész könyvtárakat használod hozzá.

A hálózati kommunikáció mindig macerás, pláne ha eszközeid sincsenek hozzá.
A hozzászólás módosítva: Hé, 11:28
(#) zombee válasza csabeszq hozzászólására (») Hé, 19:25 /
 
Idézet:
„Az I2C az sosem egyszerű”

Ezzel vitatkoznék. Kezdőként, aláírom hogy az I2C bonyolult. Hiába tanultam meg pár éve bitről bitre, újra elő kellett vennem a cuccost hogy mi és miért meg hogyan. Most sem tudnám fejből elmondani, mikor lehet STOP feltételt kiadni az UC-vel és mikor nem, meg hogyan lehet elkerülni a végtelen ciklust ha épp nem válaszol a cucc, de kis gyakorlattal a hátam mögött már nem kell analizátor(eredetileg sem volt), meg többnapos kutakodás hogy meg tudjak szólaltatni egy IC-t. Meg ha kéznél van egy épkézláb I2C könyvtár(saját gyártmány!!!) akkor azt a 20 perces guglizást és doksiolvasást is meg tudom spórolni. A szoftver I2C csak annyival nehezebb hogy az órajelet és a mintavételezést neked kell megoldani, a START/STOP feltételt pedig "jókor" kiadni. Slave esetén talán egyszerűbb, csak figyelni kell a START feltételt, az első 7 biten azonosítani a saját cimet, ha van akkor ACK-ot kiadni, majd az órajel alapján adni/venni, (master felőli) olvasáskor nemutolsó bájtnál ACK-ot, utolsó bájtnál NACK-ot adni, (master felőli) íráskor meg minden bájtnál ACK-al válaszolni és figyelni a STOP feltételt...
A hozzászólás módosítva: Hé, 19:33
(#) Szabi1 hozzászólása Hé, 20:10 /
 
Sziasztok! Valaki átnézné a következő kódom?
Tehát adott az Atmega 8 mikrovezérlő és két PWM kimenet OC1A és OC1B. Az ADC olvassa be a két poti állását, eszerint csinálja a PWM kitöltési tényezőjét.
INT0-n van egy kapcsoló, ami megszakítja a programot, és az egyik PWM kitöltési tényezőjét 100%-ra állítsa, mikor újra megnyomódik, akkor a neki megfelelő poti alapján készíti a kitöltési tényezőt. A PWM frekvenciák körülbelül 500Hz-en kellene működjenek.
  1. #define F_CPU 8000000UL
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4.  
  5. int pressed;
  6.  
  7. unsigned char Beolvas8bitADC(unsigned char csatorna)
  8. {
  9. ADMUX = (ADMUX & 0b11110000) | csatorna;   // ADC csatorna kivalasztasa
  10. ADCSRA |= (1<<ADSC);    // ADC konverzio elinditasa
  11. while (ADCSRA & (1<<ADSC));    // varas az atalakitasra
  12. ADCSRA |= (1<<ADSC);         // konverzió elindítás
  13. while (ADCSRA & (1<<ADSC));    // varas az atalakitasra
  14. return (ADCH);     // ADC ertek visszaadasa (csak a felso 8 bit (ADCH), az also 2 zajos bit elhagyasa)
  15. }
  16.  
  17. ISR (INT0_vect)
  18. {
  19.     if(pressed==0)
  20.     {
  21.         pressed=1;
  22.     }
  23.     else
  24.     {
  25.         pressed=1;
  26.     }
  27. }
  28.  
  29. int main (void)
  30. {
  31.     GICR |= (1<<INT0);
  32.       MCUCR = (1<<ISC01) ;
  33.       TCCR1A |= (1<<WGM10);     /*8 bites fazishelyes PWM*/
  34.       TCCR1B |= (1<<CS10);         /*elooszto = FCPU/1*/
  35.       TCCR1B |= (1<<CS11);         /*elooszto = FCPU/1*/
  36.       TCCR1A |= _BV(COM1A1);     /*** nem-invertalt PWM, A csatorna*/
  37.       DDRB |= _BV(PB1);          /*** PORTB PB1 lab kimenet*/
  38.       TCCR1A |= _BV(COM1B1);      /***nem-invertalt PWM, B csatorna*/
  39.       DDRB |= _BV(PB2);          /*** PORTB PB2 lab kimenet*/
  40.       DDRB |= _BV(PB0);          /*** PORTB PB2 lab kimenet*/
  41.  
  42.  
  43.         ADMUX |= (1<<REFS0)|(1<<ADLAR);    // Vcc mint referencia, balra rendezett ADC eredmeny
  44.     ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
  45.         pressed=0;
  46.       //OCR1A = _duty;         /***motor1 pwm kitoltesi tenyezo*/
  47.       //OCR1B = _duty;
  48.       sei();
  49.       while(1)
  50.       {
  51.           if(pressed==0)
  52.           {
  53.               OCR1A =Beolvas8bitADC(0);
  54.           }
  55.           else
  56.           {
  57.               ORR1A=255;
  58.           }
  59.           OCR1B =Beolvas8bitADC(1);
  60.       }
  61.  
  62.  
  63. }
A hozzászólás módosítva: Hé, 20:12
(#) csatti2 válasza Szabi1 hozzászólására (») Hé, 21:05 / 1
 
Az else után szerintem pressed=0; kellene. Prellezést is kéne kezelned (kapcsoláskor könnyen ide oda csapkodhat majd a mód). PWM rész ránézésre jónak tűnik (nagyon látszik a copy-paste azonban, (1<<WGM10) az ugyanaz, mint _BV(WGM10) ).

500Hz-es PWM-ben biztos vagy? Cincogni fognak a motorok.
(#) Jaedong válasza Szabi1 hozzászólására (») Hé, 21:08 / 1
 
Nagyon hulla vagyok most este már ahhoz hogy belenézzek a kódba még ha nem is hosszú , viszont az kiszúrja a szemem, hogy a pressed az nem volatile.
(#) csabeszq válasza zombee hozzászólására (») Hé, 21:19 /
 
Ha már van tapasztalat, akkor oké, nem olyan bonyolult.

Nekem sikerült egy felhúzó ellenállást a CLK mögül rossz helyre kötni (föld) és minden megakadt. Egy óra elment vele, míg rájöttem, hogy miért vár mindenki. A jelanalizátorral látod, hogy az adó mit ad ki és a vevő mit fogad. Ez roppant nagy előny, mert tudod, hogy egy bonyolult folyamatban ki a hibás.

Arról nem is beszélve, hogy ha a vevő 1 MHz-en megy, az adó meg 16 MHz-en, azért érhetnek meglepetések.

AVR alatt egyébként azért TWI-nek hívják a protokolt, mert nem tartják az I2C szabványt.
A legrondább ugye a STOP kezelése slave módban (0xA0):

- master küld egy STOP jelet
- a slave STOP után már nem tudja tartani a vonalat, mert nincs busy wait (CLK-val)
- közben a master új kérést küld a slave-nek
- a slave az előző STOP-ot még nem dolgozta fel, ezért az új kérésre automatikus NACK-ot küld
- a slave végre feldolgozza a 0xA0 státuszt, engedélyezi újra magát a buszon
- a master új kérését már kész fogadni

Amikor olyan implementációt látsz AVR alatt, hogy az első NACK után még kétszer újra megkérdezi a slave-et, az ezért van. Vagy amikor az interrupt első 10 órajelében lekezelik az 0xA0-t, az is ugyanilyen okból történik. Gondolom az I2C minősítést nem kapták volna meg ezzel a megoldással.
A hozzászólás módosítva: Hé, 21:21
(#) zombee válasza csabeszq hozzászólására (») Hé, 21:30 /
 
Mi úgy tanultuk, szabadalmi oka van annak hogy TWI-nek hívják, mert az "I2C" a Philips szabadalma.
A másik ok hogy TWI-n másfajta kommunikáció is megvalósítható, a harmadik amit mondasz az az
hogy az AVR master módban egyáltalán nem érzékeli ha a slave lehúzva tartja az SCK vonalat.
(#) Szabi1 válasza csatti2 hozzászólására (») Hé, 21:58 /
 
Köszönöm szépen a segítséget, kijavítottam a hibákat:
  1. #define F_CPU 6528000UL
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4. #include <util/delay.h>
  5. volatile pressed;
  6.  
  7. unsigned char Beolvas8bitADC(unsigned char csatorna)
  8. {
  9. ADMUX = (ADMUX & 0b11110000) | csatorna;   // ADC csatorna kivalasztasa
  10. ADCSRA |= (1<<ADSC);    // ADC konverzio elinditasa
  11. while (ADCSRA & (1<<ADSC));    // varas az atalakitasra
  12. ADCSRA |= (1<<ADSC);         // konverzió elindítás
  13. while (ADCSRA & (1<<ADSC));    // varas az atalakitasra
  14. return (ADCH);     // ADC ertek visszaadasa (csak a felso 8 bit (ADCH), az also 2 zajos bit elhagyasa)
  15. }
  16.  
  17. ISR (INT0_vect)
  18. {
  19.     if(pressed==0)
  20.     {
  21.         pressed=1;
  22.     }
  23.     else
  24.     {
  25.         pressed=1;
  26.     }
  27.     GICR &= ~(1<<INT0);
  28. }
  29.  
  30. int main (void)
  31. {
  32.     GICR |= (1<<INT0);
  33.       MCUCR = (1<<ISC01) ;
  34.       TCCR1A |= (1<<WGM10);     /*8 bites fazishelyes PWM*/
  35.       //TCCR1B |= (1<<CS10);         /*elooszto = FCPU/1*/
  36.       TCCR1B |= (1<<CS12);         /*elooszto = FCPU/1*/
  37.       TCCR1A |= _BV(COM1A1);     /*** nem-invertalt PWM, A csatorna*/
  38.       DDRB |= _BV(PB1);          /*** PORTB PB1 lab kimenet*/
  39.       TCCR1A |= _BV(COM1B1);      /***nem-invertalt PWM, B csatorna*/
  40.       DDRB |= _BV(PB2);          /*** PORTB PB2 lab kimenet*/
  41.       DDRB |= _BV(PB0);          /*** PORTB PB2 lab kimenet*/
  42.  
  43.  
  44.         ADMUX |= (1<<REFS0)|(1<<ADLAR);    // Vcc mint referencia, balra rendezett ADC eredmeny
  45.     ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0)// ADC engedelyezese, ADC eloosztas = 8 (125 KHz)
  46.         pressed=0;
  47.       //OCR1A = _duty;         /***motor1 pwm kitoltesi tenyezo*/
  48.       //OCR1B = _duty;
  49.       sei();
  50.       while(1)
  51.       {
  52.            if((GICR & (1<<INT0)) == 0)
  53.             {
  54.  
  55.             _delay_ms(400);
  56.  
  57.             GIFR |= (1<<INTF0);
  58.             GICR |= (1<<INT0);
  59.             }
  60.        
  61.           if(pressed==0)
  62.           {
  63.               OCR1A =(Beolvas8bitADC(0)/2);
  64.           }
  65.           else
  66.           {
  67.               ORR1A=127;
  68.           }
  69.           OCR1B =(Beolvas8bitADC(1)/2);
  70.       }
  71.  
  72.  
  73. }

Az MCU órajelét módosítanom kell 6528000Hz-re, a prescallert meg 256-ra, mivel 50Hz-es marad a PWM, és a kitöltési tényező max 127 lehet, ezért az ADC értékeket mielőtt OCR megkapja 2-vel osztom.
Csak most nemtudom biztosan, hogy ehez az "ULKA szivattyuhoz" milyen frekijű PWM kell.
A hozzászólás módosítva: Hé, 22:03
(#) Szabi1 válasza Szabi1 hozzászólására (») Hé, 22:47 /
 
Maradok a B tervnél, és kb 290Hz-es PWM-t csinálok, mert ha csak 50 Hz-est csinálok akkor a pompa vagy elkapja a pozitív részét a szinusznak, vagy nem és akkor egyáltalán nem megy.
Következő: »»   666 / 666
Bejelentkezés

Belépés

Hirdetés
Frissek
2015. Máj, 05. Kedd
1:11:19
Jelenleg 97 fő olvassa az oldalt
Online tagok:
Lapoda.hu     XDT.hu     HEStore.hu