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   761 / 840
(#) rascal válasza slimtomi hozzászólására (») Jan 31, 2017 / 1
 
Szia!
Az AVR Studio ingyenes, lehet benne assemblyben programozni, proci és égető nélkül is tud szimulációt futtatni. (Persze vannak korlátai, mert azt nem tudod megadni neki, hogy az ADC bemeneten 3 Volt van, a referencia feszültségre 4V-ot kötöttél, ő pedig mondja meg mit mérne.) Én csak assemblyben programoztam, kellemesen lehet makrózni és úgy már szinte magas szintű programhoz hasonlóan kódolhatsz.
(#) slimtomi válasza rascal hozzászólására (») Jan 31, 2017 /
 
Az AVR Studio-val milyen égetőt használsz?
(#) rascal válasza slimtomi hozzászólására (») Jan 31, 2017 / 1
 
Ezzel égettem: AVRISP-mkII kompatibilis programozó. Azt nem tudom, hogy az eredeti mkII-vel is kell úgy trükközni a driverekkel, mint ennél vagy az pöc-röff megy?
A hozzászólás módosítva: Jan 31, 2017
(#) csatti2 válasza slimtomi hozzászólására (») Jan 31, 2017 / 1
 
Természetesen programozhatsz C-ben is (kivéve a legkisebb uC-ket). Kezdőként szerintem szerencsésebb irány mint az assembly, mivel jóval hamarabb lesz sikerélményed. Használhatsz egyébként C-n belül (és az Arduino-s C++-on belül is) assembly betéteket, ha úgy érzed bizonyos részeket úgy jobban el tudsz készíteni.
Léteznek még (fizetős) fordítók, amikkel lehet Basic-ben és Pascal-ban is programozni, de ha már az Arduinos C++ ment, akkor a C-vel is boldogulni fogsz.
(#) Sick-Bastard hozzászólása Jan 31, 2017 /
 
Üdv!

Az Atmel Studio 7 szimulátorát próbálgattam és egyből egy problémába ütköztem.

  1. #define F_CPU           14745600UL
  2.  
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5. #include <avr/interrupt.h>
  6.  
  7. #define LED_PORT        PORTA
  8. #define LED_DDR         DDRA
  9. #define TIMER2_LED      PORTA2
  10. #define TIMER1_LED      PORTA1
  11. #define MAIN_LED        PORTA0
  12.  
  13. volatile unsigned char msec = 0;
  14.  
  15. void TIMER1_Init(void)
  16. {
  17.         //OCR1A = 14399;
  18.         OCR1AH = 0x38;
  19.         OCR1AL = 0x3F;
  20.         TCCR1A = (1<<WGM11);
  21.         TCCR1B = (1<<CS12)|(1<<CS10);
  22.         TIMSK1 |= (1<<OCIE1A);
  23. }
  24.  
  25. void RTC_Init(void)
  26. {
  27.         TIMSK2 &= ~0x07;
  28.         TCNT2 = 0;
  29.         TCCR2B = (1<<CS20)|(1<<CS22);   // (1<<CS20)|(1<<CS21)|(1<<CS22) == div/128
  30.         ASSR |= (1<<AS2);                               // 0x08 (1<<AS2)
  31.  
  32.         unsigned char i = 0;
  33.         for(; (ASSR & ((1<<TCN2UB)|(1<<OCR2BUB)|(1<<TCR2BUB))) && (i < 250);    i++)    //Wait until TC0 is updated
  34.         {
  35.                 _delay_ms(1);
  36.         }
  37.  
  38.         if(i < 250)
  39.         {
  40.                 TIMSK2 |= (1<<TOIE2);
  41.         }
  42.         else
  43.         {
  44.                 ASSR &= ~(1<<AS2);
  45.                 OCR2A = 224;
  46.                 TCNT2 = 0;
  47.                 TCCR2A = (1<<WGM21);
  48.                 TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22);
  49.                 TIMSK2 |= (1<<OCIE2A);
  50.         }
  51. }
  52.  
  53. int main(void)
  54. {
  55.     /* Replace with your application code */
  56.         LED_DDR = (1<<MAIN_LED)|(1<<TIMER1_LED)|(1<<TIMER2_LED);
  57.         LED_PORT = (1<<MAIN_LED)|(1<<TIMER1_LED)|(1<<TIMER2_LED);
  58.  
  59.         RTC_Init();
  60.         TIMER1_Init();
  61.         sei();
  62.  
  63.     while (1)
  64.     {
  65.                 LED_PORT ^= (1<<MAIN_LED);
  66.     }
  67. }
  68.  
  69. ISR(TIMER1_COMPA_vect)
  70. {
  71.         GPIOR1++;
  72.         LED_PORT ^= (1<<TIMER1_LED);            <<-- megszakitás 1.
  73. }
  74.  
  75. ISR(TIMER2_COMPA_vect)
  76. {
  77.         msec++;
  78.         if(msec > 63)            <<-- megszakitás 2.
  79.         {
  80.                 GPIOR2++;
  81.                 msec = 0;
  82.                 LED_PORT ^= (1<<TIMER2_LED);
  83.         }
  84. }
  85.  
  86. ISR(TIMER2_OVF_vect)
  87. {
  88.         GPIOR2++;
  89.         LED_PORT ^= (1<<TIMER2_LED);                   <<-- megszakitás 3.
  90. }


A kódban 3db megszakítást raktam. A leggyakrabban a 2.-dik aktiválódik. Már ennél jelentkezik egy hiba. Pontosabban a megszakítást párszor léptetem (Continue), akkor az OCR1A értéke módosul.
0x383f-ről 0x003f-re, azaz ledobja a high byte(OCR1AH) értékét. Ez szimulációs hiba, vagy én hagyok ki valamit, ami "rögzítené" az OCR1AH-t?
(#) rolandgw válasza Sick-Bastard hozzászólására (») Feb 1, 2017 /
 
Próbáld ki ezzel a beállítással:
Debug -> Options -> Tools -> Tool Settings -> Mask Interrupts while stepping -> False
(#) slimtomi válasza csatti2 hozzászólására (») Feb 1, 2017 /
 
Köszönöm a válaszaitokat!
Az AVR Studioban van C fordító esetleg? Ha nincs, ti melyik fordítót használjátok hozzá (mármint C programozáshoz)?
Gondolom a legkisebb mikrokontrollereket a kisméretű flashmemória miatt célszerűbb assemblyben programozni.
(#) slimtomi válasza Kovidivi hozzászólására (») Feb 1, 2017 /
 
Helló Kovidivi!

Mégegyszer köszönet a gombrutin kódért. A napokban alkalmaztam is. Elég nehéz volt rájönnöm a működésére, mert eddig nem ismertem a bitműveletek használati módját, azok operátorait.
Módosítottam pár dolgot:
1.) 4 gombot figyel
2.) kivettem a NOT bitoperátort a 'PIND' elől, így már a lenyomáskor értelmezi a rutin a lenyomást, nem csak felengedéskor
3.) 5s-ként fut le

Lenne pár kérdésem Próbálom tömören megfogalmazni őket!
1.) Hol figyeli a rutin a lenyomási és felengedési időtartamot (40ms és 30ms)? Ezen szeretnék változtatni.
2.) Miért csak 10s-ként fut a rutin? Gondolom nem probléma, ha nálam pl folyamatosan fut?
(#) Sick-Bastard válasza rolandgw hozzászólására (») Feb 1, 2017 /
 
Ez nem segített
(#) bandi777 hozzászólása Feb 1, 2017 /
 
ATmega128 -at C-ben programozok. avr-gcc-vel fordítok. Az MCU 16MHz-es külső órajelet kap. Az ADC valamiért kissé érdekesen működik. A konverziót helyes eredménnyel elvégzi, csak folyamatosan megszakítást generál.
A következő képpen állítom be a perifériát:
  1. void    adcinit(void)
  2. {
  3.         DDRF &= ~2;     // PF1 láb bemenet,
  4.         PORTF &= ~2;    // felhúzó ellenállás kikapcsolása.
  5.  
  6.         ADMUX = 0x41;   // AVCC a referenciaforrás, jobbra igazított
  7.                         // eredmény, ADC1 egyoldalas bemenet (PF1 láb).
  8.                         // adatlap 242. oldal
  9.         ADCSRA = 1<<ADEN | 1<<ADIE | /* ADPS2:0 */7;
  10.                         // ADC bekapcsolás
  11.                         // Egyelőre nem indítunk konverziót
  12.                         // Egyszeri lefutás mód
  13.                         // Megszakítások engedélyezése
  14.                         // 128-as órajel előosztás
  15.                         // adatlap 244. oldal
  16. }

Ennek hatására másodpercenként 7800-szor hívódik meg az ISR. (Ekkor nem sokat csináltam, csupán egy számlálót léptettem, amivel mértem ezt a 7800-at, és egy ledet ki-be kapcsolgattam a konverzió eredményétől függően. Ha több mindent is csináltam benne, akkor ez a szám csökkent valamennyit.)
  1. ISR(ADC_vect)
  2. {
  3.     adcin++;
  4.     stmp = ADCL;            // stmp egy 16bites előjeles egész
  5.     stmp |= ADCH<<8;
  6.     if( stmp > 512 )
  7.         ledon(1);       // bekapcsolja az 1-es ledet.
  8.     else
  9.         ledoff(1);      // kikapcsolja az 1-es ledet.
  10. }

Én azt vártam volna, hogy konverzió csak akkor induljon (és akkor is csak egy), ha ezek után az ADCSRA-ban beírom az ADSC bitet. Most kb. olyan mintha szabadon futó módban lenne, pedig nincs. (Próbálkoztam az ADFR bit beírásával/törlésével, de nem segített.)
Valakinek valami ötlete esetleg?

Előre is köszi!
(#) Sick-Bastard válasza bandi777 hozzászólására (») Feb 1, 2017 /
 
Az ADC-t hol indítod el? A while(1)-ban van egy egyszer lefutó parancs, vagy még a main()-ben?
(#) zombee válasza Kovidivi hozzászólására (») Feb 1, 2017 / 1
 
Csak gyűlnek a "jó" nyomógombkezelő rutinok. Íme az enyém amit régóta csiszolok, a mostani verziót az RFID kártyaolvasóba "fejlesztettem ki". Hiszterézises szimmetrikus pergésmentesítő:
  1. #define BTN (!(PINB&(1<<3)))  // nyomógomb: PORTB.3
  2. #define BTN_DEBOUNCE            10      //pergésmentesítés: 50ms (TIMER==200Hz)
  3. volatile uint8_t BTN_PRESSED
  4.  
  5. ISR(TIMER2_COMP_vect) // <-- 200Hz
  6. {
  7.         static uint8_t btncnt = 0;
  8.         if(BTN)
  9.         {
  10.                 btncnt++;                       //lenyomott gombnál számlálót növel
  11.                 if(btncnt >= BTN_DEBOUNCE)      //lenyomás jelzése 50ms után
  12.                 {
  13.                         BTN_PRESSED=1;
  14.                         btncnt=BTN_DEBOUNCE;
  15.                 }
  16.         }
  17.         else if(btncnt) btncnt--;               //felengedett gombnál csökkent
  18.         else BTN_PRESSED=0;             //felengedés jelzése 50ms után
  19. }


Működés: a nyomógombot az időzítő megszakítás figyeli, állapotától függően egy számlálót növel vagy csökkent. A számláló értéke felülről és alulról is korlátos. Ha felfelé számláláskor eléri a felső határt, egy globális változót átbillent 1-re, ha lefelé számlálva éri el a nullát akkor 0-ra. A nyomógomb lenyomás (vagy felengedés) szoftveres érzékelése a Schmitt-triggerhez hasonlítható. Ha egyszer átbillen az állapotváltozó, a "visszabillentés" időbe telik. A számláló felső korlátját (így az átbillentés késleltetését) úgy kell meghatározni, hogy a nyomógomb pergése és az érzékelés késleltetése között elfogadható kompromisszumot találjunk. Érzékeny gépeknél inkább nagy értéket(100-200ms) adok meg, hadd nyomkodja a parasztja! A megoldás előnye, hogy az egész nyomógomb figyelés precíz, órajelhez igazított, és teljesen a "háttérben" fut. Úgy mintha a "BTN_PRESSED" változóval ténylegesen egy (nem-pergő) nyomógombot kérdeznék le. Az algoritmus tömbösíthető, több nyomógombra kiterjeszthető. Egy korábbi változatát 12-gombos charlieplexingre készítettem el! Külön köszönet egy korábbi hozzászólónak a "static" bemutatásáért, így szebb lett a kód.
A hozzászólás módosítva: Feb 1, 2017
(#) csatti2 válasza slimtomi hozzászólására (») Feb 1, 2017 /
 
Én Atmel Studio 7-et szoktam használni.
(#) slimtomi válasza zombee hozzászólására (») Feb 2, 2017 /
 
Tetszik. Felépítésében hasonlít kicsit az arduino-féle debounce példaprogihoz. Azt csak egy gombra tudtam alkalmazni. Monduk így jó szolgálatot tett a fordulatszámmérő-gyújtásjeladó progim alapjaként.
A te rutinod hogyan terjeszthető ki több gombra, ciklussal alkalmazásával ès gombok bemeneteinek tömbbe(vektorba) pakolásával, igaz?
Jók ezek a rutinok egyébként, működnek is, viszont szerintem én áttérek az IC-s pergésmentesítésre.
A hozzászólás módosítva: Feb 2, 2017
(#) bandi777 válasza Sick-Bastard hozzászólására (») Feb 2, 2017 /
 
A main fv-ben, a sei(); és a while(1) előtt.
(#) Robi98 hozzászólása Feb 2, 2017 /
 
Sziasztok!

Egy hete már kísérleteztem az UART perifériával több-kevesebb sikerrel és sikerült elérnem, hogy egy szöveget ki tudjak rakni egy soros monitorba. Aztán szerettem volna egy olyan programot készíteni, ami adatot (egy karaktert) fogad a PC-től és attól függően megváltoztatja egy villogó RGB led színét valamint egy visszajelzést is küld a PC-nek, hogy éppen milyen a led színe.
A program viszont nem működik. A led nem csinál semmit és visszajelzés sem érkezik a PC felé. Szerintem valahol az adat fogadásnál lehet a hiba vagy az érték átadásnál, de eddig még nem jöttem rá.
Tudnátok benne segíteni?
  1. // Mikrokontroller: ATmega 16
  2. // Órajel: 16Mhz-es külső kvarc
  3.  
  4. #include <avr/io.h>
  5. #include <avr/interrupt.h>
  6. #include <util/delay.h>
  7.  
  8. volatile char data;
  9.  
  10. void konfigUART(void)
  11. {
  12.  
  13. UBRRL=103; //9600-as baud rate
  14.  
  15. UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 adatbit, 1 stop bit, nincs paritásbit
  16. UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE); // adó és vevő bekapcs. és vevő interrupt engedélyezése
  17. }
  18.  
  19. void transmitUART(char c)
  20. {
  21. while(!(UCSRA & (1<<UDRE)));
  22.  
  23. UDR=c;
  24. }
  25.  
  26. void transmit_stringUART(char *p)
  27. {
  28.         while(*p)
  29.         {
  30.         transmitUART(*p++);
  31.         }
  32. }
  33.  
  34. int main(void)
  35. {
  36. //LED lábak kimenetek
  37. DDRD|=(1<<PD7);
  38. DDRC=(1<<PC0)|(1<<PC1);
  39.  
  40. konfigUART();
  41. sei();
  42.  
  43.         while(1)
  44.         {
  45.         if(data=='r')
  46.         {
  47.         transmit_stringUART("COLOR: RED");
  48.         transmitUART(10); // új sor
  49.         transmitUART(13);// sor eleje
  50.  
  51.         PORTC=0x02; //piros színhez tartozó láb bekapcsolása
  52.         PORTD&=~(1<<PD7);
  53.         }
  54.  
  55.         else if(data=='g')
  56.         {
  57.         transmit_stringUART("COLOR: GREEN");
  58.         transmitUART(10); // új sor
  59.         transmitUART(13);// sor eleje
  60.  
  61.         PORTC=0x01; //zöld színhez tartozó láb bekapcsolása
  62.         PORTD&=~(1<<PD7);
  63.         }
  64.  
  65.         else if(data=='b')
  66.         {
  67.         transmit_stringUART("COLOR: BLUE");
  68.         transmitUART(10); // új sor
  69.         transmitUART(13);// sor eleje
  70.  
  71.         PORTD|=(1<<PD7); //kék színhez tartozó láb bekapcsolása
  72.         PORTC=0;
  73.         }
  74.  
  75.         _delay_ms(500);
  76.  
  77.         PORTD&=~(1<<PD7); //led kikapcsolása
  78.         PORTC=0;
  79.  
  80.         _delay_ms(500);
  81.         }
  82. }
  83.  
  84. ISR(USART_RXC_vect)
  85. {
  86. data=UDR;
  87. }
(#) zombee válasza slimtomi hozzászólására (») Feb 2, 2017 /
 
A nyomógombok bemeneteit ilyenkor switch-case szerkezetbe teszem, a számlálók és a kimeneti értékek mehetnek tömbbe. Tömb helyett bitmező is lehet a kimenet, de amennyit spórolni lehet vele, nem feltétlenül éri meg. Kivéve, ha a kimenet (pl. shift regiszter, USART) eleve bitmezőben kéri a gombok állapotát.
A hozzászólás módosítva: Feb 2, 2017
(#) Istvanpisti válasza Robi98 hozzászólására (») Feb 2, 2017 /
 
Szia!
Először meg kellene tudni, hogy a USART_RXC interruptba belép-e a program, pl. így
  1. ISR(USART_RXC_vect)
  2. {
  3. data=UDR;
  4. PORTD^=(1<<PD7);
  5. }

Ha adat érkezik a UART-on, akkor a PORTD pin7-je állapotot vált minden érkező karakternél (H->L,L->H) és ez látható lesz a LED-en.
Ha ez működik, akkor a főprogramban célszerű lenne rögtön visszaküldeni, így
  1. if(data)
  2. {
  3. transmitUART(data);
  4. data=0;
  5. }

Ha ez is megy, akkor már sínen vagy.
A soros porton érkező adatok lekezelése így nem lesz könnyű, mert ha több karakter is érkezik, amíg a főprogram éppen egy delay-ben várakozik, akkor mindig csak az utolsót fogod elkapni, ha sikerül.
Ilyenkor FIFO (first input first output) adatszerkezetet kellene alkalmazni, ami lehet egy sima tömb is. (eleinte)
(#) rolandgw válasza Robi98 hozzászólására (») Feb 2, 2017 /
 
Ha nem is akarod használni, tanulás okán is érdemes belenézni egy bevált és jól működő lib-be.
Bővebben: Link
(#) bandi777 válasza Robi98 hozzászólására (») Feb 2, 2017 /
 
a dealy -ek használatához meg kell adni az órajelet. És mivel ebből fordításidőben számolódnak az értékek, ezért szigorúan a #include<util/delay.h> előtt.
Pl.:
  1. #include <avr/io.h>
  2.  
  3. #define F_CPU 16E6
  4. #include <util/delay.h>
  5.  
  6. #include <interrupt.h>
  7. ...


Jelen esetben az egymásba ágyazott if() -ek használata fölöslegesen bonyolult. A switch-case szerkezetet pont arra vár, hogy egy ilyet váltsanak ki vele. Egy változó értéke alapján dől el, hogy melyik ágon (akármennyi lehet) fusson tovább a program. Jól működik ez így is, csak hát mégis elegánsabb így:
  1. ...
  2. switch(data)
  3. {
  4.     case 'r':
  5.         transmit_stringUART("COLOR: RED");
  6.         transmitUART(10);
  7.         transmitUART(13);
  8.        
  9.         PORTC = 0x02;
  10.         PORTD &= ~(1<<PD7);
  11.         break;
  12.     case 'g':
  13.         ...
  14.         break;
  15.     case 'b':
  16.         ....
  17. }
  18. ...
(#) enree hozzászólása Feb 4, 2017 /
 
Sziasztok!
Szükségem lenne egy kis segítségre. Megépítettem ezt a netes kis hőmérőt. Kiválóan működik, de szeretnék egy másik hátteret használni e helyett a fehér helyett.
Nézegettem a kódot, de ebből nem sokat értek... Azt tudom, hogy pl html-ben régen valahogy így meg lehetett oldani;
  1. <body background="http://valami.net/valami.png"> </body>
Ekkor elég volt egy pár pixel széles és mondjuk ezer magas színátmenet png-t csinálni és annyiszor tette be az oldal, amennyiszer kifért.
Tehát a kérdés az lenne, hogy ebbe a kódba ezt bele lehet aplikálni? Bocs mindenkitől, ha rossz helyen kérdeztem, de végül is, AVR

main.c
    
(#) rascal válasza enree hozzászólására (») Feb 4, 2017 / 1
 
Ezzel én pár éve jól el voltam, amikor kicsit kontárkodni kellett egy honlapon. Az utolsó szakasz szól a háttérképről. Először notepadban a gépeden kísérletezz, és ha az biztató, akkor a main.c-ben is megpróbálhatod a kiegészítést. Bővebben: Link
(#) enree válasza rascal hozzászólására (») Feb 5, 2017 /
 
Baromi jó kis összefoglaló, köszönöm!
(#) rascal válasza enree hozzászólására (») Feb 5, 2017 /
 
Szívesen!
(#) Robi98 válasza Istvanpisti hozzászólására (») Feb 5, 2017 /
 
Köszi a javaslatot. Kipróbáltam és azóta sikerült rájönnöm, hogy mi volt a hiba.
Az interrupt végrehajtódott, minden egyes karakter elküldése után a led állapota megváltozott. Viszont a visszaküldött karakterek között két üres sor maradt. Ha csak simán entert ütöttem, akkor meg csak egy pillanatra villant fel a led. Tehát megváltozott az állapota, aztán vissza is váltott.
A baj az volt, hogy a terminálprogramban az volt beállítva, hogy a karakter után hagyjon ki egy sort. Tehát egy karakter helyett hármat küldött el: a leütött betű pl: w, új sor, és sor elejére. Enter esetén csak az utóbbi kettő. Tehát azért hagy ki két sort, mert visszaküldi a három karaktert amit az enterrel kapott, aztán még ezután rak új sort és ugrik a sor elejére amit ugye én írtam a programba.

A kérdésem az, hogy hogy van ideje a mikrovezérlőnek visszaküldeni mind a három karaktert? Hiszen azok szünet nélkül követik egymást amikor megérkeznek a PC felől.
Amikor egy interrupt végrehajtódik (megtörténik a kiolvasás) akkor a főprogram honnan folytatódik tovább? Onnan, ahol az if szerkezet kezdődik, vagy onnan, ahol az if szerkezeten belül abbahagyta?
A probléma lényege már világos, a részleteket viszont nem igazán értem.
A hozzászólás módosítva: Feb 5, 2017
(#) zombee válasza Robi98 hozzászólására (») Feb 5, 2017 /
 
Egy terminál akkor küldi el a leütött karakter kódját, amikor leütöd. A PC-s oldalon a terminálban van küldő puffer, ami nem engedi elküldeni a karaktert amíg az előző küldése tart.
Egy becsületes terminálban az "ENTER" a egy <CR> (kocsi vissza) karaktert jelent, 13-as kóddal.
Ha úgy van beállítva, akkor mellé egy <LF> (soremelés) is társul 10-es kóddal. A szövegfájlokban (nem csak txt) is így van, annyi külnbséggel hogy linuxos cuccoknál az "új sor" kizárólag egy <LF> karaktert jelent.

A mikrovezérlő oldalán nem kell feltétlenül fogadó puffer. Az nem gond ha egymásután jönnek a karakterek, mert 9600 baud esetén kb. 1ms van közöttük. Ennyi időd van rá hogy olvasd az UDR-t és várd a következő karaktert, esetleg elkezdd feldolgozni a kapott adatot.
A hozzászólás módosítva: Feb 5, 2017
(#) rascal válasza Robi98 hozzászólására (») Feb 5, 2017 /
 
A megszakítás után oda tér vissza a program, ahol éppen tartott a program a megszakítás kiváltásának pillanatában. Pl. Van egymás után X, Y, Z utasítás a főprogramban, akkor ha Y végrehajtása után kiváltódik egy megszakítás, akkor amikor annak vége a főprogram a Z utasítással folytatja. Ezek már gépi kódú utasítások, ha egy magas szintű nyelvben programozol, pl. C, akkor annak egy utasítása több gépi kódú utasításból is állhat és így egy C nyelvű utasítás végrehajtását is félbevághatja a megszakítás.
A hozzászólás módosítva: Feb 5, 2017
(#) enree válasza rascal hozzászólására (») Feb 5, 2017 /
 
Nos, ha ez egy honlap lenne, nem okozna gondot... De ezt akármennyire studírozom, nem jutok dűlőre vele :/
A hozzászólás módosítva: Feb 5, 2017
(#) ttspeaker88 hozzászólása Feb 6, 2017 /
 
Sziasztok!

ATmega8 ADC-vel lenne egy kis problémám, rossz ADC értéket ad:
2 cellás lipo akku (max 8.4V) feszültségét szeretném mérni, az akku után van egy fesz. osztó (10K,15K értékekkel) ami a 8.4V-ból 5V-ra oszt, majd ezt az maximum 5V-os feszültséget szeretném mérni, 10 bit-es ADC-vel a PC5-ös porton, de valamiért egyfolytában 1023 értéket ad (8 bit-es módban is ugyanez a helyzet).

Az Avcc rá van kötve a Vcc-re, az Aref és a gnd között van egy 100nF kondenzátor, a referenciát pedig az Avcc-ről veszi (5V).


  1. void config10bitADC()  
  2. {
  3.         ADMUX |= (1<<REFS0);    // Vcc as reference
  4.         ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // ADC enable
  5. }
  6.    
  7.  
  8. unsigned int get10bitADC(unsigned char channel)
  9. {
  10.         ADMUX = (ADMUX & 0b11110000) | channel;
  11.        
  12.         ADCSRA |= (1<<ADSC);         // first conversion
  13.         while (ADCSRA & (1<<ADSC));      
  14.        
  15.         ADCSRA |= (1<<ADSC);          // second conversion
  16.         while (ADCSRA & (1<<ADSC));        
  17.        
  18.         return (ADCL | (ADCH<<8));
  19. }


  1. cellsADCvalue = get10bitADC(5);
  2. cellsVoltage = (cellsADCvalue * (maxVolts / maxAdcBits)) * ratio;



Előre is köszönöm a segítséget!
ttspeaker88
(#) Istvanpisti válasza ttspeaker88 hozzászólására (») Feb 6, 2017 /
 
Szia!
Valószínűleg azért, mert a leosztott mérendő feszültség az AVCC felett van. Ez adódhat abból, hogy az osztót alkotó ellenállásoknak is van pontatlansága, a VCC sem biztos, hogy pontosan 5V.
De próbáld megmérni műszerrel!
Vagy esetleg cseréld meg a feszültség osztó két tagját és nézd meg mi történik akkor!
Következő: »»   761 / 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