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   553 / 840
(#) fifadani hozzászólása Aug 10, 2013 /
 
Sziasztok!
Nos összedugdostam egy 4x4-es mátrixot. Mivel még most kezdtem a programozással foglalkozni, még picit magas amit Zombee írt..

Annyira jutottam, hogy a mátrix szélén körbe járatom a fényt...

Megmutatom, de elég hosszú.
  1. int main (void)
  2. {
  3.  
  4.  DDRD = 0b00111111;  
  5.  DDRC = 0b00111111;
  6.  
  7.  //PC3 4.o
  8.  //PC2 3.o
  9.  //PC1 2.o
  10.  //PC0 1.o
  11.  //PD0 1.s
  12.  //PD1 2.s
  13.  //PD2 3.s
  14.  //PD3 4.s
  15.  
  16.  unsigned char vil_ido=100;
  17.  unsigned char lep_ido=10;
  18.  
  19.  while(1)
  20.  
  21.  {
  22.  
  23.  PORTC = (1<<PC3); //oszlop
  24.  PORTD = (1<<PD0); //sor
  25.  _delay_ms(vil_ido);
  26.  PORTC = 0;
  27.  _delay_ms(lep_ido);
  28.  
  29.  PORTC = (1<<PC3); //oszlop
  30.  PORTD = (1<<PD1); //sor
  31.  _delay_ms(vil_ido);
  32.  PORTC = 0;
  33.  _delay_ms(lep_ido);
  34.  
  35.  PORTC = (1<<PC3); //oszlop
  36.  PORTD = (1<<PD2); //sor
  37.  _delay_ms(vil_ido);
  38.  PORTC = 0;
  39.  _delay_ms(lep_ido);
  40.  
  41.  PORTC = (1<<PC3); //oszlop
  42.  PORTD = (1<<PD3); //sor
  43.  _delay_ms(vil_ido);
  44.  PORTC = 0;
  45.  _delay_ms(lep_ido);
  46.  
  47.  PORTC = (1<<PC2); //oszlop
  48.  PORTD = (1<<PD3); //sor
  49.  _delay_ms(vil_ido);
  50.  PORTC = 0;
  51.  _delay_ms(lep_ido);
  52.    
  53.  PORTC = (1<<PC1); //oszlop
  54.  PORTD = (1<<PD3); //sor
  55.  _delay_ms(vil_ido);
  56.  PORTC = 0;
  57.  _delay_ms(lep_ido);
  58.  
  59.  PORTC = (1<<PC0); //oszlop
  60.  PORTD = (1<<PD3); //sor
  61.  _delay_ms(vil_ido);
  62.  PORTC = 0;
  63.  _delay_ms(lep_ido);    
  64.        
  65.  PORTC = (1<<PC0); //oszlop
  66.  PORTD = (1<<PD2); //sor
  67.  _delay_ms(vil_ido);
  68.  PORTC = 0;
  69.  _delay_ms(lep_ido);
  70.  
  71.   PORTC = (1<<PC0); //oszlop
  72.  PORTD = (1<<PD1); //sor
  73.  _delay_ms(vil_ido);
  74.  PORTC = 0;
  75.  _delay_ms(lep_ido);
  76.  
  77.  PORTC = (1<<PC0); //oszlop
  78.  PORTD = (1<<PD0); //sor
  79.  _delay_ms(vil_ido);
  80.  PORTC = 0;
  81.  _delay_ms(lep_ido);
  82.  
  83.  PORTC = (1<<PC1); //oszlop
  84.  PORTD = (1<<PD0); //sor
  85.  _delay_ms(vil_ido);
  86.  PORTC = 0;
  87.  _delay_ms(lep_ido);
  88.  
  89.  
  90.   PORTC = (1<<PC2); //oszlop
  91.  PORTD = (1<<PD0); //sor
  92.  _delay_ms(vil_ido);
  93.  PORTC = 0;
  94.  _delay_ms(lep_ido);
  95.  
  96.  }
  97.  
  98. return 0;
  99. }


Öhm, hogy lehet lerövidíteni?
Mert így már 540 byte. Ha valami szöveget akarok majd kiírni, hát gyorsan megtelik a 8Kbyte. Vagy tévedek?
(#) zombee válasza fifadani hozzászólására (») Aug 10, 2013 /
 
Ez (szoftver oldalról) még messze nem mátrix kezelés, hiszen mindig 1-1 LED-et gyújtasz ki
és úgy animálsz vele. De kezdésnek bőven megteszi, legalább tanulsz belőle!
Egy apróság: változót SOHA nem adunk meg a _delay_ms() függvénynek, használj #define-t!
A programra a válasz: mindig algoritmussal kell gondolkodni, leprogramozni hogy mit is akarsz,
és azt egy ciklusba rendezni a lehető legegyszerűbb módon és legkevesebb sor felhasználásával.
Szóval az én algoritmusom: fogok 2 változót, amelyek a következő lépés irányát
adják meg. Az egyik mindig nulla, a másik +1 vagy -1. Ha a léptetett érték(X vagy Y) eléri a határt,
akkor le kell nullázni és a másik változónak +1 vagy -1 értéket adni. Ez a lépés fizikailag
egy "kanyarodásnak" felel meg. Azért ilyen egyszerű lesz a dolog, mert a specifikáció,
tehát a körbehaladás is nagyon egyszerű feltétel! Ha a tied működik, akkor a lenti kód is jó lesz!
A végén a sok if/else nem túl szép, de nagyon szépen demonstrálja a "kanyarodás"
feltételeit és az ilyenkor szükséges teendőket. Ez még jobban tömöríthető tömbökkel,
de azért nem ezt a megoldást írtam le mert több kérdést felvetne mint amennyit megválaszolna...

  1. int main (void)
  2. {
  3.  DDRD = 0b00111111;  
  4.  DDRC = 0b00111111;
  5.  #define vil_ido 100
  6.  #define lep_ido 10
  7.  char X=0;
  8.  char Y=0; //X,Y kiindulópont: bal felső sarok
  9.  char dx=1;
  10.  char dy=0; //dx, dy lépés iránya: "jobbra"
  11.  while(1)
  12.  {
  13.   PORTC = 1<<X;
  14.   PORTD = 1<<Y;
  15.   _delay_ms(vil_ido);
  16.   PORTC = 0;
  17.   _delay_ms(lep_ido);
  18.   X+=dx;
  19.   Y+=dy;
  20.   if(X>3) {X=3; dx=0; dy=1;}  //jobb felső sarok: lefelé fordul!
  21.   else if(Y>3) {Y=3; dx=-1; dy=0;}  //jobb alsó sarok: balra fordul!
  22.   else if(X<0) {X=0; dx=0; dy=-1;}  //bal alsó sarok: felfelé fordul!
  23.   else if(Y<0) {Y=0; dx=1; dy=0;}  //bal felső sarok: jobbra fordul!
  24.  }
  25. }
A hozzászólás módosítva: Aug 10, 2013
(#) zombee hozzászólása Aug 10, 2013 /
 
Íme a tömbös megoldás:
  1. int main (void)
  2. {
  3.  DDRD = 0b00111111;  
  4.  DDRC = 0b00111111;
  5.  #define vil_ido 100
  6.  #define lep_ido 10
  7.  char X = 0;
  8.  char Y = 0;
  9.  char iranyok[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
  10.  uint8_t irany = 0;
  11.  uint8_t cnt = 0;
  12.  
  13.  while(1)
  14.  {
  15.    PORTC = 1<<X;
  16.    PORTD = 1<<Y;
  17.    _delay_ms(vil_ido);
  18.    PORTC = 0;
  19.    _delay_ms(lep_ido);
  20.    X+=iranyok[irany][0];
  21.    Y+=iranyok[irany][1];
  22.    if(++cnt==3)
  23.    {
  24.     cnt=0;
  25.     irany = (irany+1) & 0b00000011;
  26.    }
  27. }
A hozzászólás módosítva: Aug 10, 2013
(#) fifadani hozzászólása Aug 10, 2013 /
 
Egyenlőre a nem tömbös megoldással szemezek.
Nem tudtam rájönni, hogy miért nem jó.
Azt csinálja,hogy szépen kezd a bal felsőben, végig is megy egészen a bal alsóig.
De aztán a jobb alsóban folytatódik és megy a bal alsóba. Tehát kimarad a kezdőponthoz való visszatérés. Nem tudtam rájönni, hogy lenne jó..
Illetve a sarkakban kétszer villan.

(a tömbös frankón megy)
A hozzászólás módosítva: Aug 10, 2013
(#) zombee válasza fifadani hozzászólására (») Aug 10, 2013 /
 
Az első, "if-es" cucc valóban nem egészen jó, mert ha rendesen működne akkor is 2-szer villan a sarkokban. Ezt rögtön láthatod: ha már túlfutna a cucc valamelyik irányba akkor a túlfutást visszaállítja, majd csak ez után fog irányt váltani - azaz elfordulni.
A tömbös sokkal tömörebb, itt már látszik hogy egy algoritmussal van dolgod. Ennél a megoldásnál az irány megváltoztatása jóval egyszerűbb, mert csak az iránytömb értékeit kell megfordítani, de ügyelni kell az "irany" kezdőértékére is. Az első megoldásnál meg az "if"-es részekbe kell belenyúlni.

Van egy harmadik lehetőség. Ez a Te megoldásodat utánozza, tehát nem algoritmus adja az alapját. Kihasználja hogy egyszerre csak egy LED-et gyújtasz ki, így tárolja a lépéseket.
Ezzel már bonyolultabb formációkat is ki lehet rajzolni, de minden új koordináta eszi a memóriát!
  1. int main (void)
  2. {
  3.  DDRD = 0b00111111;  
  4.  DDRC = 0b00111111;
  5.  #define vil_ido 100
  6.  #define lep_ido 10
  7.  uint8_t XY[12][2] = {{0,0},{1,0},{2,0},{3,0},{3,1},{3,2},{3,3},{2,3},{1,3},{0,3},{0,2},{0,1}};
  8.  while(1) for(uint8_t i=0; i<12; i++)
  9.  {
  10.   PORTC = 1<<XY[i][0];
  11.   PORTD = 1<<XY[i][1];
  12.   _delay_ms(vil_ido);
  13.   PORTC = 0;
  14.   _delay_ms(lep_ido);
  15.  }
  16. }
A hozzászólás módosítva: Aug 10, 2013
(#) fifadani hozzászólása Aug 10, 2013 /
 
Huh azthiszem, hogy sokat kell még tanulnom...
(#) zombee válasza fifadani hozzászólására (») Aug 10, 2013 /
 
Nem árt. Először a mátrix portok kezelését és alap algoritmusokat sajátítsd el, addig ne is törd magad "hasznos" alkalmazáson amíg ez kisujjból nem megy! Anno középsuliban PC-re írtam egy kígyós programot. Az algoritmus pontosan ugyanaz lenne AVR és LED mátrix esetén. De a megjelenítő rész teljesen más, hiszen az AVR kezeli a mátrixot, portokat, multiplexelést, stb., míg a fő algoritmus nem is kezeli a portokat és a nyomógombokat sem. Tehát AVR-nél egy jó interrupt az alap, mert a megjelenítésnek és a gombok kezelésének a "háttérben" kell futnia.
A hozzászólás módosítva: Aug 10, 2013
(#) fifadani hozzászólása Aug 10, 2013 /
 
Akkor gondolom kezdjek egy sima C-s "tanfolyammal"... Van hozzá pár doksim.
(#) zombee válasza fifadani hozzászólására (») Aug 10, 2013 /
 
Akár. De a nyelv ismerete nem elég ahhoz hogy alkalmazást is tudj írni.
A programozói logikát nem lehet tanulni, azt tapasztalni kell másképp nem megy.
(#) fifadani hozzászólása Aug 10, 2013 /
 
Igaz. Gyakorlás, olvasgatás kell. Próbálkozok! Köszi
(#) Hagens hozzászólása Aug 13, 2013 /
 
Sziasztok!
Azt szeretném kérdezni, hogy egy Atmega8 chipet le lehet végleg védeni?
Mert most vettem egy programozót, az elején szépen tudtam írni olvasni az atmega8-at, aztán meg már nem. Hogy tudnám az ic-t törölni, és alap helyzetbe állítani?
Előre is köszönöm a választ!
Csaba
A hozzászólás módosítva: Aug 13, 2013
(#) TavIR-AVR válasza Hagens hozzászólására (») Aug 13, 2013 /
 
Mit értesz levédés alatt?

A biztosítékbitek LockBiotje való erre:
- disable read and verify. Ekkor kiolvasni nem lehet a chipet sem SPI, sem nagyfesz paralell/soros módon. Chip Erase-val azomban a flash törölhető és a chip újraírható.
De van még plusz trükk a védelemhez:
- Disable ISP (csak nagyfesz soros/parhuzamos programozóval programozható utána)
- Disable RESET/Enable I/O (resetláb eltűnik, I/O láb lesz helyette!)
- Preserve EEPROM (csak akkor pipáld be, ha a törlés után az EEPROM tartalom megmaradjon)
- LockBit: ha bootloadert használsz, akkor a fetöltésre ítélt kód is titkosított legyen!

A biztosítékbitekről és programozókról...

De a chip tetejét lemaradtni és elektronmikroszkóppal ki lehet ettől még olvasni.... És így klónozni a chipet....
A hozzászólás módosítva: Aug 13, 2013
(#) wolfem válasza TavIR-AVR hozzászólására (») Aug 13, 2013 /
 
Szia!
Azt értem, hogy addig kapcsolgatja, és olyan helyzetbe az ember a lockBiteket, hogy nem lehet hozzáférni az IC-hez, és nem is lehet törölni, magyarul el lehet dobni.
Én ezt értettem alatta.
(#) TavIR-AVR válasza wolfem hozzászólására (») Aug 13, 2013 /
 
Kizárásra gondolsz - több út is van
1, hibás órajelbeállítás: nincs külső kvarc és arra teszed. Vagy External clockra
2, disable reset (Isp-n nem éred el)
3, disable ISP


Törölni _mindig_ lehet.
High Voltage programmert nem tudod kitiltani, de a chip tartalma ekkor is védhető (lockbit)
(#) wolfem válasza TavIR-AVR hozzászólására (») Aug 13, 2013 /
 
Én zártam le véletlenül szerintem az IC-t, és szeretném újra használhatóvá tenni.
Mit csináljak, nem tudom törölni sem.
(#) TavIR-AVR válasza wolfem hozzászólására (») Aug 13, 2013 /
 
High Voltage programmer kell neked. Ebből a legegyszerűbb:
- megépíteni a FuseBit doctor nevű áramkört. Ez a biztosítékbiteket alaphelyzetbe rakja.
- keríteni valakit, akinek van ilyenje
- gyári STK500 (nagy, ATMEL-es) vagy a AVR-Dragon is ismeri ezt.


De ha szerencséd van csak órajel hiba: Az XTAL1-re adj valami 1 MHz...20 MHz közti órajelet (órajelgenerátor IC, kapuchiből összerakott, másik IC ClkOut engedélyezése)
A hozzászólás módosítva: Aug 13, 2013
(#) csabeszq válasza TavIR-AVR hozzászólására (») Aug 14, 2013 /
 
Nos, egy új IC olyan 600-1500 Ft körül mozog.

Egy HVPP megépítése durván 3-4000 körül lehet, mert kell bele IC, nyák, alkatrész, miegymás...

Megfelelő darabszámú elfuserált IC-t össze kell gyűjteni ahhoz, hogy a HVPP megtérüljön.
A hozzászólás módosítva: Aug 14, 2013
(#) TavIR-AVR válasza csabeszq hozzászólására (») Aug 14, 2013 /
 
Nem gazdasági számítás volt a kérdés .
Nálam is 2.5 cső halott IC után lett STK500 (eredeti). A halott chipek ára összemérhető lett a programozóval. És csak 1 chip lett a sokból örök vadászmezős. Az 12V-t kapott az ADC bemeneten - azaz nem is fusebit halála volt...

Ha 1 chip van csak, azt félre kell tenni és gyűjtenimellé a többit...
(#) Szabi1 hozzászólása Aug 14, 2013 /
 
Sziasztok! Kazettás magnóban találok olyan IC-t ami a motrokat előre/hátra mozgatja? Vagy VHS olvasóban?
(#) TavIR-AVR válasza Szabi1 hozzászólására (») Aug 14, 2013 /
 
Igen. De ezek a VHS-ben BLDC motorok!

Inkább L297/L298 IC páros kell neked... (stepper)
Vagy L298DNE - H hídként.
(#) Szabi1 hozzászólása Aug 14, 2013 /
 
Másik kérdésem van egy érzékelő, egy motoron ami 33VAC-t ad ha teljesen forog, 1,4-4VAC-t ha pedig a leglassabban. Nos hogyha egyenirányitom akkor az MCU ADC -ével szeretném digitális jellé alakítani, és a keletkező PWM kitöltési sebességét vizsgálni, hogy lehetséges?
(#) zombee válasza Szabi1 hozzászólására (») Aug 15, 2013 /
 
Kitöltési sebesség olyan nincs. A motor érzékelője ezek szerint induktív, abból nem lesz PWM jel. Ez szinuszos váltakozó feszültség, aminek a frekijét tudod mérni. A legegyszerűbb egy NPN tranzisztor lesz, jól megválasztott alkatrészekkel és értékekkel.
(#) Panhard hozzászólása Aug 15, 2013 /
 
Sziasztok! Egy ATMEGA328P kontrollerbe szeretnék bootloadert tölteni, hogy utána FTDI adapterrel lehessen programozni. Van egy ilyen AVR-ISP égetőm. Az a kérdésem, hogy mi ennek a folyamata, AVR Studió vagy másik program kell hozzá. A bootloader .hex-et le kell tölteni valahonnan, vagy benne van a programban.
A hozzászólás módosítva: Aug 15, 2013
(#) fifadani hozzászólása Aug 15, 2013 /
 
Szép estét.
Azt szeretném kérdezni, hogy a mega8 használható 16Mhz-es kvarcal?
S milyen kerámia kondikkal?
(#) TavIR-AVR válasza Panhard hozzászólására (») Aug 16, 2013 /
 
Pontosíts. A bootloader egy általános fogalom.

"A bootloader egy olyan kis szoftver, ami a mikrokontroller külön dedikált programmemóriájában helyezkedik el (ún. BootBlock-ban). Gyakorlatilag a program flash memória egy része. A kommunikáció a kontroller perifériáin keresztül valósul meg, így lehet például RS-232, SPI-busz, I2C-busz is a bootloader külvilági kapcsolata. Feladata pedig a programmemória egyéb területén lévő tartalom megváltoztatása a külső tartalomnak megfelelően"
Bővebben: Link

Pl. Arduino tartalmaz beépítve ilyet - kötött órajel, sosos sebesség és chipekre.
A hardware/arduino/bootloaders könyvtárában van.

A Bascom-AVR esetén a samples/bootloaders alatt is van basic-ban jópár minta.
(#) TavIR-AVR válasza fifadani hozzászólására (») Aug 16, 2013 /
 
Az adatlap általában csodákat tud mondani.
http://www.atmel.com/images/atmel-2486-8-bit-avr-microcontroller-at...et.pdf
27-28. oldal.

De: Milyen mega8? ATMega8? Mega8L? Mega8P
Mi a _pontos_ típusazonosítója? Általában beszédes a kódsor.
AVR chipek típusazonosító és családsor kódfeloldása
(#) fifadani hozzászólása Aug 16, 2013 /
 
Köszi a linket. Így már tudom, hogy a 16PU az mit jelent...

Illetve lenne még egy kérdésem.
Hogy tudom azt megoldani C-ben...
Adok egy számot egy változónak, legyen ez most 7.
Annyiszor villanjon fel a led, amilyen értéket megadok.
A hozzászólás módosítva: Aug 16, 2013
(#) fifadani hozzászólása Aug 16, 2013 /
 
Így gondoltam:
5-ször villanjon fel a led.
  1. int main (void)
  2. {
  3. DDRC = (1<<PC5);
  4. char X;
  5. X=0;
  6.  
  7.   while(X<10)
  8.  //azért 10, mert a kikapcsoláskor és a bekapcsoláskor is hozzáad 1-et.
  9.   {
  10.     PORTC ^= (1<<PC5);
  11.     m_delay_10ms(10);
  12.     X=X+1;
  13.   }
  14.  
  15. }
(#) TavIR-AVR válasza fifadani hozzászólására (») Aug 16, 2013 /
 
Jó szemed van... 20 msec-t meglátsz villanásilag....
(#) TavIR-AVR válasza fifadani hozzászólására (») Aug 16, 2013 /
 
  1. for i= 0 to villanas_szam
  2. LED ON
  3. waitms 100
  4. led off
  5. waitms 100
  6. next i
Következő: »»   553 / 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