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   682 / 837
(#) Droot válasza Max26 hozzászólására (») Júl 29, 2015 /
 
Szia!

Próbáld ki úgy, hogy a wdt a legnagyobb időre konfigolod és megáll-e a program. Pl a DHT11 kiolvasása sokáig tarthat. Vagy ki is szedheted a WDT-t.

Más:
A PA0-t mire használod? Bármire is, az R19 helyett egy feszültség osztó szerintem jobb lenne. Igaz, hogy minimálisan terheli az akkut, elvileg az ATmega32-ben is van belső zéner, de azért jobb a békesség.

Az R2-R5, R17-nek nem nagyon látom értelmét, mert a belső felhúzóellenállást is bekapcsolhatod.

Tulajdonképpen ez a sok tranzisztor mi volna? Lekapcsolod egyesével a perifériákat? Mert elég lenne csak a tápot lekapcsolni. Egy csomó mindent spórolnál vele.

A C2-nek 12-22pF-nek kell lennie.

A kijelző működik 3.3V-ról?
Ha igen akkor ne használj step-up konvertert, energiatakarékosabb lesz szerintem egy step-down, tovább bírja majd az akku. Inkább az LCD háttérvilágításhoz tegyél egy FET-et, aminek a Gatejét esetleg PWM kimenetre kötöd, normál esetben nagyon alacsony fényerővel világít, ha megnyomtak egy nyomógombot akkor pedig fényesebben.

Bocs, nem kötözködésből írtam ennyi mindent, hanem segítségből.
(#) Max26 válasza Droot hozzászólására (») Júl 29, 2015 /
 
Ha ezt a konfigot használom és a wdt-nek 2 másodpercet adok, akkor is resetel a program.:
- UART kommunikációt
- I2C kommunikációt - Hőmérséklet, páratartalom, légnyomás mérést
- SD kártya loggolást
- 4x4 gombmátrixot
- LCD kijelzőt
- ADC lábat
Ha nincs benne wdt a teljes projektbe, amiben az sd kártya loggolás is szerepel, akkor megáll a program (végtelen ciklusba futna?) PA0 analóg láb, az akku %-os értékét mérem vele. Az N csatornás fetek a szintillesztéshez kellenek 5V<->3.3V. A kijelző nem működik 3.3V-ról. Háttérvil-el ráérek még.
A hozzászólás módosítva: Júl 29, 2015
(#) Droot válasza Max26 hozzászólására (») Júl 29, 2015 /
 
Az AD konverteren mindig feszültség osztóval mérünk. Nem adhatsz rá nagoybb feszültséget mint amiről az AVR megy, mert túlcsordul. Érdemes úgy megválasztani a feszosztót, hogy a maximum feszültség közelében érje el a referencia feszültséget. Az AVR belső 2.56Vos referenciáját használd, ne a tápfeszt, mert ahogy merül úgy csökken a referencia. Úgy válaszd a feszosztót, hogy kb. 5V-nál (mivevl elvileg max 4.2V lehet a bemeneten) legyen 2.56V. Pl 4.7K-4.7K tökéletes.

Én szintillesztéshez szintén feszosztót szoktam használni, de csak az alacsonyabb feszültség írányába, mert ami magasabb feszültségről megy, jelen esetben 5V-ról, a 3,3V-ot még magas szintnek fogja érzékelni. Érdemes megnézni az adatlapokat, de a fenti eszközöket ismerem és azok tudnak úgy működni.

Van 3,3V-ról máködő LCD-is. (Érdekesség képp mondom. )

Visszatérve az eredeti kérdéshez:
Akkor vagy át kell nézni, vagy másik library-t kell használni.
(#) killbill válasza Droot hozzászólására (») Aug 2, 2015 / 1
 
Idézet:
„Az AD konverteren mindig feszültség osztóval mérünk.”
Adott egy 5V tápról járatott AVR és adott egy 3.7V-os akku. Mégis miért kellene ide osztó? Mivel stabilizalt az 5V, az akku merülése nem változtatja a tápot. Igaz, a belso referencia stabilabb és akkor már kell az osztó. De ez nem kőbe vésett szabály.
Idézet:
„Nem adhatsz rá nagoybb feszültséget mint amiről az AVR megy, mert túlcsordul.”
Nem túlcsordul, hanem tönkremegy! Óriási különbség.
(#) Balázs hozzászólása Aug 3, 2015 /
 
Sziasztok!

ATmega128-ra kellene bootloadert írnom, de valamiért nem akar a BLS-ből indulni a program. Már teljesen lebontottam a kódomat, de így sem megy. A 0x0000 címre az alábbi egyszerű kódot fordítottam be:

  1. #include <avr/io.h>
  2. int main(){
  3.         DDRD|=0x80;
  4.         PORTD|=0x80;
  5.         while(1);
  6.         return 0;
  7. }


A 0xF000 címre pedig majdnem ugyanezt, csak az egy másik LED-et gyújt ki (a BOOTSZ fuse bitekkel ezt a kezdőcímet állítottam be a BLS-nek). A hibajelenség az, hogy mindenképpen a 0x0000 címen lévő kód fut, a BOOTRST fuse bit állapotától függetlenül.

A chip teljes flash memóriáját visszaolvastam, és belenéztem a kapott .hex fájlba, minden a helyén van.

Ha valakinek van ötlete, mi lehet a baj, akkor előre is köszönöm!
A hozzászólás módosítva: Aug 3, 2015

hex.jpg
    
(#) Kovidivi válasza Balázs hozzászólására (») Aug 3, 2015 /
 
A bootloader nem a flash végéből csíp ki egy szeletet? Reset során oda ugrik, majd utána a főprogramra ugrik? Megkérdezhetem, hogyan írtál egy bizonyos címre? Bootreset bit is be van állítva? Köszi.
(#) killbill válasza Balázs hozzászólására (») Aug 3, 2015 / 2
 
Az a 0xf000 az a valosagban 0x1e000. A flash 128k hosszu, annak az utolso 8k-ja nem kezdodhet 0xf000 cimen.
(#) Balázs válasza Kovidivi hozzászólására (») Aug 3, 2015 /
 
De, a flash végén van a Boot Loader Section, a kezdőcíme BOOTSZ0=BOOTSZ1=0 esetén 0xF000. Ha a BOOTRST fuse bit is be van állítva, akkor elvileg a 0x0000 cím helyett ide ugrik reset után a program (nekem viszont ez látszólag nem teljesül). A főprogramra ezután sem ugrik automatikusan, ezt legegyszerűbben egy asm("jmp 0x0000") paranccsal lehet elintézni, ha készen vagyunk a bootolással. Esetemben ilyen sincs, a LED bekapcsolása után meg kellene akadnia egy végtelen ciklusban, nem hívja a főprogramot.

A programozást úgy csináltam, hogy két külön .hex fájlt fordítottam, az egyiket csak simán (ez megy a 0x0000 címre), a másiknál pedig megadtam a linkernek, hogy az egész menjen a 0xF000 címre (-Wl,--section-start=.text=0xF000). Ezután töröltem a flash tartalmát, majd egymás után beégettem a két fájlt. Ezzel a visszaolvasás tanúsága szerint nem is volt gond, minden a helyére került.
(#) Sick-Bastard hozzászólása Aug 3, 2015 /
 
Üdv!

Írtam két új funkciót meglévő programomhoz, de a funkciók nem akarnak jól működni.
A gond, hogy a funkciókba felveszek egy vagy több változót, amit/amiket módosítani szeretnék. Egy változó esetében a return()-t használva jól működik a kód, de ha többet kell módosítani, akkor ezt már nem használhatom.

Példa:

  1. void Set_Clock_form_UDP(unsigned char array[], unsigned int year, unsigned char month, unsigned char date, unsigned char hour, unsigned char min)
  2. {
  3.         unsigned int temp_year = (int)(array[46] << 8) + array[47];
  4.        
  5.         if(temp_year != year)
  6.         {
  7.                 year = temp_year;
  8.         }
  9.         if(month != array[48])
  10.         {
  11.                 month = array[48];
  12.         }
  13.         if(date != array[49])
  14.         {
  15.                 date = array[49];
  16.         }
  17.         if(hour != array[50])
  18.         {
  19.                 hour = array[50];
  20.         }
  21.         if(min != array[51])
  22.         {
  23.                 min = array[51];
  24.         }
  25. }


Az array[] az AVR altal fogadott UDP csomagot foglalja magában a funkció meghívásakor.
A year, month, date, hour és min valózok mind volatile unsigned char-ek, amiket az ISR(TIMER2_COMPA_vect)-ben használok az órához.

A fenti funkció feladata az óra beállítása lenne, ha az eltérne a valós időtől.

A probléma, hogy ezek nem módosulnak a funkció meghívása során. Azt is megpróbáltam, hogy a funkcióban unsigned char helyett volatile unsigned char-nak deklaráltam a változókat, de ez nem jött be.

A másik funkcióban is ugyan ez a gond.

egyszerűsített példa a problémára:

  1. unsigned char valtozo = 2;
  2. unsigned char foo(unsigned char adat)
  3. {
  4.      adat = adat*2;
  5.      return(adat);
  6. }
  7.  
  8. foo(valtozo);
  9. PORTA = valtozo;   // 2 marad
  10.  
  11. valtozo = foo(valtozo);
  12. PORTA = valtozo; // 4 lesz


Amitől még érdekesebb a dolog, hogy van másik 3 tucat funkcióm, amik tökéletesen működnek.

Ez lehet a fordító hibája? (WinAVR)

SB
(#) Balázs válasza killbill hozzászólására (») Aug 3, 2015 /
 
Óbasszus, összekevertem a byte és a word címeket! Na, erre nagyon sokára jöttem volna rá... Nagyon köszönöm!
(#) killbill válasza Sick-Bastard hozzászólására (») Aug 3, 2015 /
 
A year, month, date, hour, min valtozok irasakor te nem a kulso volatile valtozokat valtoztatod, hanem a fuggvenynek atadott ugyanilyen nevu valtozokat, aminek az erteke elvesz a fuggveny visszateresekor.
(#) Sick-Bastard válasza killbill hozzászólására (») Aug 3, 2015 /
 
Még ilyenkor is:

  1. volatile unsigned char year = 2015, month = 8, date = 3, hour = 10, min = 20, sec = 0;
  2. ...
  3.  
  4. void Set_Clock_form_UDP(unsigned char array[], unsigned int year, unsigned char month, unsigned char date, unsigned char hour, unsigned char min)
  5. {...}
  6. ...
  7.  
  8. int main(void)
  9. {
  10.      while(1)
  11.      {
  12.           // ... stb. pl.: csomagok fogadása, ellenőrzése
  13.           if(UDP_csomag_erkezett)  
  14.          {
  15.                Set_Clock_form_UDP(UDP_csomag, year, month, date, hour, min);
  16.          }
  17.      }
  18. }
  19.  
  20. ISR(TIMER2_COMPA_vect)
  21. {
  22.     clock();
  23. }
(#) Max26 hozzászólása Aug 3, 2015 /
 
Sziasztok! 1 másodperc időzítésre volna szükségem. Az alábbi kód 8MHz-es kristályt használ, nekem 16MHz-es kristályom van. Hogyan kapjuk a 999-es értéket?

  1. #define DO_LOG_MSTIME 1000 //mintavételezés ideje
  2.         uint8_t do_log = 0;
  3.  
  4.         #define TIMER1_OCR1A 999
  5.         #define TIMER1_PRESCALER (1 << CS11)
  6.         #define TIMER_1MSTICKS 1 //timer ticks to count 1 msecond
  7.  
  8.         void timer_init(void)
  9.         {
  10.                 TIMSK &= ~(1 << TOIE0);
  11.  
  12.                 //timer 1 set at mode ctc, compare to oscr1a
  13.                 OCR1A = TIMER1_OCR1A; //set value = fcpu / prescaler
  14.                 TCCR1B |= (1 << WGM12); //mode 4, CTC on OCR1A
  15.                 TIMSK |= (1 << OCIE1A); //interrupt on compare match
  16.                 TCCR1B |= TIMER1_PRESCALER; // set prescaler
  17.  
  18.                 TIMSK |= (1 << TOIE0);
  19.         }
  20.  
  21. ISR (TIMER1_COMPA_vect)
  22. {
  23.         static uint16_t timer2_step = 0;
  24.         static uint32_t do_log_mstime = 0;
  25.  
  26.         timer2_step++;
  27.  
  28.         if(timer2_step == TIMER_1MSTICKS)
  29.         {
  30.                 timer2_step = 0;//we are here every ms
  31.                 logger_mstick();//tick the logger
  32.                 do_log_mstime++;
  33.  
  34.                 if(do_log_mstime == DO_LOG_MSTIME)
  35.                 {
  36.                         do_log_mstime = 0;
  37.                         do_log = 1;
  38.                 }
  39.         }
  40. }
(#) killbill válasza Sick-Bastard hozzászólására (») Aug 3, 2015 /
 
Idézet:
„Még ilyenkor is:”
Ez most kérdés vagy közlés?
(#) csatti2 válasza Max26 hozzászólására (») Aug 3, 2015 /
 
ezt:
  1. #define TIMER1_OCR1A 999

írd át erre:
  1. #define TIMER1_OCR1A 1999


A mikrokontrollered kézikönyve adja meg a képletet (nem írtad meg milyen). Függ attól is, hogy hány bites a timer.

Pl. ATMega328P timer 1 esetén:
fOC1A = fCLKIO / (2 * N * (1+OCR1A))

fCLKIO = 16MHz
N = 8 (Prescaler)
fOC1A = 1kHz

OCR1A = (fCLKIO / ( 2 * N * fOC1A)) - 1
OCR1A = 999
Tehát neked nem ilyen uC-d van. Mivel neked 8MHz-re jött ki ennyi.
(#) csatti2 válasza Sick-Bastard hozzászólására (») Aug 3, 2015 /
 
Nem esett le, hogy az ÉRTÉK szerint átadott BELSŐ változóid ÉRTÉKÉT állítod a függvényben majd kilépsz? Kifelé nem csinálsz semmit sem...
Ha tényleg állítani akarod a külső változóid értékét a függvényen belül, akkor REFERENCIA szerinti átadást kell megvalósítani.
Add meg a link feliratát

Vagy csak simán kiveszed a paraméterek közül a year, stb. változókat és hagyod, hogy a kívűl definiált változókat használja a fordító...
A hozzászólás módosítva: Aug 3, 2015
(#) killbill válasza csatti2 hozzászólására (») Aug 3, 2015 /
 
Cim szerint. C, nem C++. De egyebkent teljesen egyetertek. Mellesleg erre egy kazal Warningot kellene kiirjon a fordito, ha ugy van parameterezve (-Wall). Csak az IDE-k szeretik ezt elfelejteni, igy rengeteg fejtorest okozva a programozonak.
(#) Sick-Bastard válasza csatti2 hozzászólására (») Aug 3, 2015 /
 
killbill, csatti2

Köszönöm szépen a felvilágosítást!

Ma is tanultam valamit. Eddig ezt rosszul tudtam.

Azt azért jól tudom, hogy a tömböket már nem csak beolvassa, de módosíthatja is?

  1. char tomb[2] = {8,16};
  2. void foo(char array[])
  3. {
  4.      array[0] =  array[0]*4;
  5.      array[1] +=  array[0];
  6. }
  7.  
  8. foo(tomb);
  9.  
  10. // eredmény foo() után:
  11. // tomb[0] = 32;
  12. // tomb[1] = 48;


Ebben ugye nem tévedtem?
(#) killbill válasza Sick-Bastard hozzászólására (») Aug 3, 2015 /
 
Jelen peldaban a foo(tomb); hivas nem a tombot adja at, hanem a tomb cimet, ezert tudja meghivott fuggveny modositani a tartalmat. A foo() fuggvenyt deklaralhatnad igy is:

void foo(char *array)
{
}

Egy sima valtozo cimet az & operator allitja elo, es a csillaggal lehet a mutatott ertekre hivatkozni:

  1. int valtozo;
  2.  
  3. void foo(int *p)
  4. {
  5.   *p = 3;
  6. }
  7.  
  8. void main(void)
  9. {
  10.   // legyen valtozo erteke harom
  11.   foo(&valtozo);
  12. }
A hozzászólás módosítva: Aug 3, 2015
(#) Max26 válasza csatti2 hozzászólására (») Aug 4, 2015 /
 
Működik, köszi!
(#) ravigupta hozzászólása Aug 4, 2015 /
 
can anyone support me or help me for programming AVR Microcontroller Programming for generating Variable PWM(Square) output and ADC port programming for measure the voltage and current(DC), a variable PWM means , its duty cycle can b change during the program.

thanku
(#) Magyar Csaba hozzászólása Aug 4, 2015 / 1
 
Mi a kérdés?
Hol akadtál el?
Miben programozol?

Van egy arduino topic itt, szerintem ott hamarabb megválaszolják a pontosan feltett kérdésed.
Sőt!
Szerintem bármilyen programnyelven elég egyértelmű a pwm kitöltési tényező beállítása egy lábon akár bármilyen, tehát bemeneti változóként definiált portlábon levő mért érték alapján.

Ha félreértettem a kérdésed, akkor bocsánat, de mindenképpen pontosítani kellene, és a megfelelő topicban folytatni, ahol segítenek is érdemben.

További szép napot, estét!
(#) Kovidivi hozzászólása Aug 4, 2015 /
 
Hello. Kifogytam a szabad kimenetekből, viszont kellene egy láb, amivel a DC-DC konvertert tudom ki (GND az EN-re) és bekapcsolni (5V az EN lábra). Arra gondoltam, hogy az Aref-et használom lehúzó ellenállással (100k-ra gondoltam, spórolni kell az árammal). Szerintetek használható lenne így? Csak nagyon ritkán kell ADC-znem, olyankor is 5V-ot használok referenciának. Köszönöm.
(#) kapu48 válasza Kovidivi hozzászólására (») Aug 5, 2015 /
 
Milyen AVR? Láttad az adatlapját?

Az AREF csak feszültség referencia szokott lenni! Nem használható másra.
(#) Kovidivi válasza kapu48 hozzászólására (») Aug 5, 2015 /
 
Atmega328. Az Aref lábon megjelenik a referencia feszültség, kondenzátorral hidegíthető is GND felé. Az én terhelésem MCP1640 EN lába, ami valószínű uA-eket igényel. Ha pedig lekapcsolom az Aref-et, akkor High-Z-be megy, ilyenkor a lehúzó ellenállás miatt GND lesz a szint.
Kicsit utánanézem, úgy tűnik, működőképes. Sőt, majdnem olyan, mint egy 2 bites DAC A kimeneti feszültség lehet 0V 1V1 5V. Atmega644-nél van még 2.56V-os Aref is, és rövidzárlatban 80mA folyik. Bővebben: Link
"VREF can also be measured at the AREF pin with a high impedance voltmeter."
Ennek örülök, legalább nem kell plusz bonyodalom, hogy egy már használt PIN-ről vezéreljem az EN lábat.
(#) csatti2 válasza Kovidivi hozzászólására (») Aug 5, 2015 /
 
Léteznek port extender IC-k. De használhatsz még shift regisztereket is ha több ki/bemenetre van szükséged. Léteznek párhuzamso be/soros ki, illetve soros be/párhuzamos ki kivitelek is. Így 3 (esetleg 4 ha az output enable is kell) láb segítségével csinálhatsz 8, 16 stb. számú további ki/bemenetet.
(#) Kovidivi válasza csatti2 hozzászólására (») Aug 5, 2015 /
 
Szia. Köszi a tippet. Nagyon kevés a hely, és csak 1 kimenet kell, úgyhogy használom ezt a megoldást.
(#) Max26 hozzászólása Aug 7, 2015 /
 
Sziasztok!

Megépítettem ezt az áramkört, de a világért nem akar működni. Dupla tápot használ, de egyszerre csak az egyikről működik. Ha van USB csatlakozás, akkor az akkumulátort le van választva egy relé segédérintkezőjével. Ez működik. Ha nincs usb, akkor az akkumulátorról ketyeg(ne).
Alaphelyzet: fesz mentes.
a) Bekapcsolom az áramkört (nincs usb +5V), akkor pár másodpercenként resetre fut a watchdog timer.
b) Bekapcsolom az áramkört (csak usb van, akku nincs), akkor kb. 15 percenként van 1 reset.

Számomra érthetetlen, mert alapból futott a program wdt reset nélkül, úgy hogy csak usb táp volt, meg úgy sem volt gond, ha csak step up konverterről ment. Volt már valakinek hasonló tapasztalata?
A hozzászólás módosítva: Aug 7, 2015

kapcs.png
    
(#) kapu48 válasza Max26 hozzászólására (») Aug 7, 2015 /
 
Én ezt egyáltalán nem érte!

Mi az „Áramkorlát 85mA” áramkör feladata?
85mA felett rövidre zárja a tápvonalat?
(#) vzoole válasza Max26 hozzászólására (») Aug 7, 2015 /
 
Paneltervet tudsz csatolni?
Én rámérnék szkóppal tápvonalra és az áramlimitre is, nem-e néha bekapcsol egy pillanatra.
Ha R22-t kiveszed/átkötöd, akkor is csinálja?

Itt egy hasonló megoldás, esetleg továbbfejlesztéshez:
Bővebben: Link

kapu48...
Úgy működik, hogy a táp GND(1) és az áramköri GND(2) szét van választva az R22 ellenállással és T1 tranzisztorral.
Az áramkorlát értéke alatt a T1 nyitva van az R20 miatt és összeköti a két földet.
Az áramkorlát értéke felett a T2 kinyit, ami lezárja a T1-et és így megszűnik a GND.
Következő: »»   682 / 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