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   430 / 840
(#) blackdog hozzászólása Márc 27, 2012 /
 
Sziasztok!

Korábban írtam, hogy szeretnék egy potméterrel állítható időzítőt is készíteni a kapcsolásomban. Az egyik ADC bemenetre teszek egy 10k potit. Ez eddig rendben.
Viszont a referencia lábakkal mit kell teni?
Oda is kell fesz. osztó, hogy a referencia a 2,5V legyen és ne 5V? Vagy nem számít, hogy a bemenet sosem éri el az 5V-t?
(#) blackdog válasza blackdog hozzászólására (») Márc 27, 2012 /
 
De, ha jól sejtem akkor elég lenne nekem a 2,56V belső referencia is. De azért érdekel, hogy mi a helyzet, ha külsőt használok.

Egyébként az ADC eredményét, hogyan tudom felhasználni a TIMER0-ban? Az eredmény arra kellene, hogy hány percig tartson egy késleltetés. Vagy ehhez nem szükséges TIMER elég, ha írok hozzá egy saját delay függvényt?
(#) blackdog válasza blackdog hozzászólására (») Márc 27, 2012 /
 
Elnézést! Még egy és befejezem a blogolást:
Az ADC konverzióra úgy vagy szükségem, hogy nem kell állandóan futnia.
Ez a poti nem egy állandóan tekergetett poti lenne. Elvileg egyszer be van állítva és kész.
Nos oly módon szeretném használni, hogy mikor szükségem van az iőzítőre előtte megnézem az ADC-t (poti állását) és ezután fut le a visszaszámlálás. Más esetben nincs rá szükségem.
[off]
Mielőtt még megkérdezitek:
Azért nem szoftveresen állítom az időt mert több helyre is szánom ezt a panelt és mindenhol más-más időzítés kell. Van ahol nem kell van ahol 2perc vagy 8perc, de 10perc.
(#) vzoole válasza blackdog hozzászólására (») Márc 27, 2012 /
 
Egy kis infó adc-hez: AVR ADC

Habár én inkább beraknék egy kijelzőt és egy enkódet, és mindent menüből lehetne állítani.
(#) blackdog válasza vzoole hozzászólására (») Márc 27, 2012 /
 
Köszönöm megnézem.
Ennél a kapcsolásnál nem cél sőt hátrány és fölösleges az LCD. Vannak még ilyen esetek.
Szerk.:
Ez nem az amit szeretnék Eddig én is eljutottam.
(#) sikolymester válasza blackdog hozzászólására (») Márc 27, 2012 /
 
Arra ügyelj, hogy a referenciád legyen több, mint a lehetséges max fesz a bemeneten. Tönkre nem fog menni, hogyha betartod az abszulút tolerancia határokat, csupán telítésbe megy a mért értéked már esetleg félúton.

Az ADC eredményét eltárolod, majd csinálsz vele késleltetést. a _delay_ms() függvényt viszont, hogyha egy runtime változóval hívod meg, az nagyban növeli a kódméretet. dobd be egy while loopba és a while loopnak add meg hány ms késleltetést akarsz.
(#) sikolymester válasza Axel hozzászólására (») Márc 27, 2012 /
 
Nem kellene melegednie.
Nem tudom amúgy hogyan kötötted be a ledeket, de mindig úgy érdemes, hogy a katódját kötöd az AVR-re, így kevésbé terheled a kimenetét. Ekkor persze kell előtét ellenállás, mert amúgy kidurranna a LED.
(#) dc001 válasza blackdog hozzászólására (») Márc 27, 2012 /
 
Az időzítő lejártakor a D1 lábat magasra állítja.

Az aref bekötése és leírás: #1195608 hozzászólásomban.

  1. volatile unsigned int cnt;
  2. volatile unsigned int adc;
  3.  
  4. ISR(TIMER1_COMPA_vect)
  5. {
  6.     if(cnt)
  7.     {
  8.         cnt--;
  9.         if(!cnt)
  10.         {
  11.             PORTD |= (1<<PIND1);
  12.         }
  13.     }
  14. }
  15.  
  16. ISR(ADC_vect)
  17. {
  18.     adc = (ADCL | (ADCH<<8));
  19. }
  20.  
  21. int main(void)
  22. {
  23.     unsigned char adc_channel;
  24.     adc=0;
  25.     cnt=0;
  26.  
  27.     adc_channel = 0;                                           /// potméter az ADC0-ra kötve
  28.  
  29.    DDRD|=(1<<PIND1);                                     /// D1 kimenet
  30.  
  31.     ADMUX|=(1<<REFS0);                                  /// ref: avcc + 100nF aref
  32.     ADCSRA=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);            /// ADC freq:  93.75 kHz div: 128 (CPU=12MHz)
  33.     ADCSRA|=(1<<ADEN)|(1<<ADIE);
  34.     ADMUX=(ADMUX&0xF0)|adc_channel;
  35.  
  36.     TCCR1B=(1<<WGM12)|(1<<CS11);                        /// F_CPU/8
  37.     OCR1A=(F_CPU/8/100)-1;                              /// 100Hz = 10ms timer1
  38.     TIMSK|=(1<<OCIE1A);
  39.  
  40.     sei();
  41.     while(1)
  42.     {
  43.         if(adcbeolvas)
  44.         {
  45.             ADCSRA |= (1<<ADSC)|(1<<ADIE);
  46.         }
  47.         if(idozitoindul && adc)
  48.         {
  49.             cnt=adc*59;                                 /// 1023 * 59 = 60357 * 10ms = 00:10:03.57
  50.         }
  51.     }
  52. }
(#) patmosis hozzászólása Márc 28, 2012 /
 
Sziasztok,letöltöttem ezt a processing nevű programot , amivel ábrázolni lehet az értékeket.
egy gyorsulás mérőt szeretnék kipróbálni de nem használtam még ezt a programot.
Valaki tud ebben segíteni?
Köszönöm.
(#) hp hozzászólása Márc 28, 2012 /
 
Sziasztok! Egy nem várt -első látásra banálisnak tűnő- jelenséggel szembesültem AVR-GCC-ben, és nem találtam rá megoldási javaslatot.
A következő -leegyszerűsített- kódot fordítom le:

  1. #include <avr/io.h>
  2. #include <inttypes.h>
  3.  
  4. /*HOLTER_MODE*/
  5. typedef enum {
  6. HOLTER_OFF = 1,
  7. HOLTER_IDLE = 2,
  8. HOLTER_ACQUISTION = 3,
  9. HOLTER_RECHARGE = 4,
  10. HOLTER_USB = 5
  11. }HOLTER_MODE;
  12. HOLTER_MODE volatile holter_mode_actual = HOLTER_IDLE;
  13.  
  14. int main(void){
  15.  
  16. volatile uint16_t i = 1;
  17. volatile uint16_t j = 3;
  18.  
  19.  
  20. holter_mode_actual = HOLTER_IDLE;/*Definition*/
  21. for(;;){
  22. switch(holter_mode_actual){
  23. /*Switch off*/
  24. case HOLTER_OFF:{
  25. for (i = 0; i < 500; i++)/*Something dummy instead of delay.h...*/
  26. {
  27. j = j + j << 1;
  28. }
  29. holter_mode_actual = HOLTER_IDLE;
  30. break;
  31. }
  32.  
  33. /*Temporal IDLE state*/
  34. case HOLTER_IDLE:{
  35. for (i = 0; i < 500; i++)/*Something dummy instead of delay.h...*/
  36. {
  37. j = j - j << 1;
  38. }
  39. holter_mode_actual = HOLTER_OFF;
  40. break;
  41. }
  42. }
  43. }
  44. }


A fordító azonban minden optimalizációs szinten úgy fordít, hogy a végtelen ciklusba lépve, a "case" feltételvizsgálat nélkül (és a késleltető for nélkül) megtörténik először a "holter_mode_actual" értékadása. Ezek után a program futása a c programnak megfelelő. Amit nem sikerült megfejtenem, hogy miért fordulnak be az értékadó utasítások közvetlenül a for ciklus előtti, inicializáló értékadás után? Disassembly listám itt található: Disassembly

Megjegyzés: próbáltam már enum helyett konstanssal, switch helyett if-fel, kommentek eltávolításával, különböző gcc verziókkal, stb. de az eredmény ugyanaz.
Előre is köszönök minden hozzászólást!
Peti
(#) sgt válasza hp hozzászólására (») Márc 28, 2012 /
 
Nem néztem végig, de az enum deklarációd valahogy nem oké. Ez alapján készítsd el Bővebben: Link

delay.h-val mi a problémád egészen pontosan?
(#) hp válasza sgt hozzászólására (») Márc 28, 2012 /
 
Szia!
Típust definiáltam, azért tér el az általad küldött linkben szereplőtől. Enum helyett sima konstansot használva is teljesen ugyanaz a tünet. Én is az enumra gyanakodtam először, de sima
  1. volatile int holter_mode; //változóval és
  2. holter_mode == 1 //teszteléssel

esetén is ugyanaz történik.
Peti
(#) sgt válasza hp hozzászólására (») Márc 28, 2012 /
 
Aztán észre vettem, hogy van névtelen enum is (a lap alján van). Szval nem ott van a gond. Ami viszont szintén furcsa (nem láttam még ilyet mint az enum esetében), hogy a case-nél {} operátorokat használod. Enélkül is azt csinálja amit kell.

RE: delay.h-val mi a problémád egészen pontosan?
(#) hp válasza sgt hozzászólására (») Márc 28, 2012 /
 
Szia!
Köszönöm válaszod, minden tipp jól jön!
A {}-t csak kínomban tettem oda, anélkül is ugyanaz. Meg if-fel is ugyanaz.
Bocs, a delay.h kérdésre nem válaszoltam: egyik ismerősöm szimulátorban kutatja a jelenség okát, ahol nem valós időben fut a delay rutin, ezért cseréltem ki. A várakozás magja csak memóriaszemetet termel, nem lényeges.

Peti
(#) sgt válasza hp hozzászólására (») Márc 28, 2012 /
 
Bocsi, hogy így bele kötök mindenbe, de tényleg nem látom okát, hogy miért nem működik.

C szimulátor AVR Studioban? Asszem meg van a hiba . Élesben az eszközön próbáljátok ki, és használjatok delay függvényt. Asm szimulátor se hibamentes, de az legalább használható. Én C szimulátorban egyetlenegy programot se tudtam rendesen végig szimulálni.
(#) dc001 válasza hp hozzászólására (») Márc 28, 2012 /
 
Ha jól értem a kérdésedet:

  1. ->->->->->->->->->->->->->->->->holter_mode_actual = HOLTER_OFF;
  2. 00000120  LDI R21,0x01Load immediate
  3. ->->->->->->->->->->->->->->->->holter_mode_actual = HOLTER_IDLE;
  4. 00000121  LDI R20,0x02Load immediate


itt feltölti az enum értékkel az R21 és R20 regisztert, hogy később megspóroljon egy-egy utasítást:

  1. 00000141  STS 0x2000,R20    Store direct to data space

illetve
  1. 0000015C  STS 0x2000,R21    Store direct to data space


ha előtte nincs az értékadás, akkor utána nem egy hanem két-két utasítás kellene:
  1. LDI R21,0x01
  2. STS 0x2000,R21

illetve
  1. LDI R20,0x02
  2. STS 0x2000,R20


Az egész azért van mert közvetlenül nem lehet memóriának értéket adni, csak regiszteren keresztül. Az alábbi kódrészlet optimalizált változata:
  1. holter_mode_actual = HOLTER_IDLE;

  1. holter_mode_actual = HOLTER_OFF;
(#) hp válasza dc001 hozzászólására (») Márc 28, 2012 /
 
Köszönöm a válaszokat!
sgt: az eszközre is ugyanazt fordította. De az ismerősömnek nem volt hol futtatnia.
dc001: ezek szerint csak a debugger "hibája", hogy utasításonkénti léptetés esetén úgy látszik, mintha a feltétel vizsgálata nélkül elvégezné az utasítást, tehát teljes értékadás történne.
Valóban, nem figyeltem meg, hogy ott csak regisztert ír, holott a volatile típus miatt állandóan a memóriában kell tartania, s az máshol történik meg.
Mindannyiótoknak nagyon köszönöm, hogy foglalkoztatok a problémával, nagyon sokat segítettetek!
(#) blackdog hozzászólása Márc 29, 2012 /
 
Sziasztok!

Még egy dolog van amit nem igazán látok át.
RS232-n keresztül szeretném az AVR 1-2 változójának az értékét módosítani. Például a következőre gondolok:
Legyen egy LED. Úgy írom meg a programot, hogy óránkét 5 percre bekapcsolja a ledet majd ki.
Ezt a kódot felprogramozom az AVR-re. Később, hogyan tudom megvalósítani, hogy újraprogramozás nélkül RS232-n keresztül mondjuk módosítom, hogy óránként ne 5 hanem 10 percre kapcsoljon be a LED. Vagy ne óránként hanem 30 percenként 1 percre?
(#) kiborg válasza blackdog hozzászólására (») Márc 29, 2012 /
 
Ehhez kell az áramközhöz RS232 illesztés, gondolom ez eddig ok.
Másrészt használnod kell az epromot. Ide menti el az RS232-n kapott értékeket és innen használja őket, így ha kikapcsolod az utolsó feltöltött értékeket fogja használni.
Üdv Kiborg
(#) blackdog válasza kiborg hozzászólására (») Márc 29, 2012 /
 
Addig oké, hogy RS232 és azt is tudom, hogy kell legalább a belső EEPROM.
Csak nem látom át nem értem, hogy hogyan van ez. Példakódot kerestem, de sikertelenül. Vagy nem figyeltem.
(#) sgt válasza blackdog hozzászólására (») Márc 29, 2012 /
 
Jönnek a bitek rs232-n. UDR-ből amit kiolvasol, azt elmented az eeporom.h-ban lévő függvények valamelyikével, amit majd szintén az ebben lévő függvény valamelyikével tudod kiolvasni. Arra kell figyelni, hogy a legelső bekapcsolást is lekezeld.
(#) dc001 válasza sgt hozzászólására (») Márc 29, 2012 /
 
A #1192171 hozzászólásomban linkelt cikkben és onnan letölthető forrás kódban nézd meg a SIGNAL(SIG_UART_RECV), isRxCmd(), getRxData() és process_command() függvényeket.

Itt találsz mintát üzenet fogadására, feldolgozására és eeprom-ba történő elmetésére a soros portról.

Az alábbi rész kihagyásával (SIG_UART_RECV-ből) RS232-n is használható RS485 helyett.
  1. if(TxCheckPtr<TxDataPtr && TxDataPtr) {
  2. ...
  3. }


Ha kérdésed van ezzel kacsolatban írj nyugodtan.
(#) oregharcos hozzászólása Márc 29, 2012 /
 
Üdv mindenkinek!
2009-ben feltettem ezt a kérést, de azóta sem kaptam rá választ. most ismét előtérbe került a csengő, mert szeretném megcsinálni.
Előre bocsátom, hogy a programozásban gyenge vagyok. A Kapcsolásokban\csengő- leírásban, Topinak csengőjét szeretném megcsinálni.
Úgy szeretném megoldani, hogy egy dallamot tudjak beprogramozni az AVR-be. Olyan gondom van, hogy az AVR Studioval nem bírom lefordítani a main.c file-t.
Próbáltam egy egyszerű villogó kódját is lefordítani, amit szintén Topi készített, de nem megy.
Hiába állítom be a frekvenciát, portot, STK500-at.
Szerintem programozó nélkül is menni kellene a fordításnak, de nem hajlandó.
Valamit nagyon elrontok, de nem tudom, hogy mit.
Ezt a hibát írja ki.
rm -rf main.o elso.elf dep/* elso.hex elso.eep elso.lss elso.map
Build succeeded with 0 Warnings...
mmcu=attiny45 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT main.o -MF dep/main.o.d -c ../csengo/main.c
/usr/bin/sh: -Wall: command not found
make: [main.o] Error 127 (ignored)
Build succeeded with 0 Warnings...

Kérlek benneteket, hogy segítsetek.
Köszönettel!
oregharcos
(#) sgt válasza oregharcos hozzászólására (») Márc 29, 2012 /
 
Segítünk, csak tedd fel a forrás kódot .
(#) sikolymester válasza oregharcos hozzászólására (») Márc 29, 2012 /
 
Ezt nézted: Bővebben: Link ?
(#) sgt válasza sgt hozzászólására (») Márc 29, 2012 /
 
blackdog várja a segítséget.

blackdog: egy kis támpont:
  1. #define <avr/eeprom.h>
  2. ...
  3. ISR(USART0_RX_vect)
  4. {
  5.  unsigned char temp = UDR;
  6.  if(...) // ha ezt az értéket szeretnéd letárolni
  7.    {
  8.      eeprom_write_byte(temp, 0x01); // eeprom.h-ban több infó van erről a fgv-ről
  9.    }
  10. }
  11.  
  12. int main(void)
  13. {
  14.   unsigned char data = eeprom_read_byte(0x01);
  15.  
  16.   while(1) {...}
  17. }

De ez csak egy vázlat, ehhez nem muszáj ragaszkodni. Még sokféleképpen meg lehet oldani, ami teljesen rajtad áll, és hogy hogyan képzelted el.
(#) blackdog hozzászólása Márc 30, 2012 /
 
Sziasztok!

Találtam egy lib-et az LCD kezeléshez gondoltam kipróbálom. De sehogyan sem jött össze.
Az LCD-t AVRDuino laphoz kötöttem hozzá. Simán feltöltöttem a programot, de azon kívül, hogy tudom állítani a kontrasztot és ki/be kapcsolni a háttérvilágítást semmi nem történik.
Az lcd.h file-ban beállítottam, hogy melyik porton vannak az LCD kivezetései, de semmi akár hova is teszem nem jelenik meg semmi. Én szúrtam el valamit vagy az LCD halt meg?


stg, dc001
Köszönöm az iránymutatást most csak ennyi kellett. Eltettem magamnak.
(#) oregharcos válasza sgt hozzászólására (») Márc 30, 2012 /
 
Szia Gtk!
Először ezt próbáltam lefordítani.

  1. #ifndef F_CPU
  2. #define F_CPU 8000000
  3. #endif
  4.  
  5. #include <avr/io.h>
  6. #include <util/delay.h>
  7.  
  8. //-------------------------------------
  9. void m_delay_10ms(unsigned char val) {
  10. //-------------------------------------
  11. //a _delay_ms max 65.535 ms-et képes sleepelni,
  12. // tehát nagyobb időzítést többből lehet "összerakni"
  13.            unsigned char i;
  14.            for(i=0;i<val;i++) {
  15.                _delay_ms(10);
  16.            }
  17. }
  18.  
  19. //-------------------------------------
  20. int main(void) {
  21. //-------------------------------------
  22.            DDRB = (1<<PINB3)|(1<<PINB4); //csak a PB3 a PB4 kimenet
  23.            PORTB = 0x00;    //mindent kikapcsol
  24.            while(1) {
  25.                if(PORTB & (1<<PINB3)) PORTB &= (1<<PINB3);
  26.                                  else PORTB |=  (1<<PINB3);
  27.                if(PORTB & (1<<PINB4)) PORTB &= ~(1<<PINB4);
  28.                                  else PORTB |=  (1<<PINB4);
  29.                m_delay_10ms(100); //100*10ms = 1s
  30.            }
  31.            
  32.            return 0;
  33. }


Innen másoltam:

Bővebben: Link

(Moderálás: Máskor használd a kód beillesztést légyszíves. Köszi, -- Topi)
(#) sikolymester válasza oregharcos hozzászólására (») Márc 30, 2012 /
 
Van feltelepítve WinAVR ?
(#) blackdog hozzászólása Márc 30, 2012 /
 
Sziasztok!

Szerettem volna egy Atmega168-at felprogramozni.
STK500 programozóm van tőle: Bővebben: Link

Fejlesztő környezet AVR Studio 5.1. Op. rendszer Win7 64bit. FTDI driver elvileg a legfissebb.
Az AVR Studio felismeri az STK500-at, de mikor csatlakozni szeretnék hozzá akkor ez a hiba üzenet jön:
Timestamp:2012-03-30 17:34:06.928
Severity:ERROR
ComponentId:20000
StatusCode:0

Unable to connect to tool context: 'Atmel.VsIde.AvrStudio.Services.TargetService.TCF.Internal.Services.Remote.ToolProxy+ToolContext'.


Vajon miért? Úgy viselkedik mintha mégsem lenne csatlakoztatva az STK500.
AVR Studio 5.0 és 4 ugyan így nem áll vele szóba. Próbáltam COM1 - COM10 között mindenhol.
Következő: »»   430 / 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