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   721 / 837
(#) zombee válasza Sick-Bastard hozzászólására (») Feb 1, 2016 /
 
Ha nem küldesz adatot az AVR felé attól még lehet jel, pl. bekapcsoláskor. Elég egy pillanatra
átbillenteni az RxD bemenetet (start bit) és már indul is a vétel!
Tipp #1: felhúzó ellenállás RxD-re
Tipp #2: SUT_CKSEL (fuse bitek) nagyobb bekapcsolási késleltetés
Tipp #3: Ne engedélyezd, vagy ha igen akkor kezeld le azt a nyamvadt megszakítást!
(#) Sick-Bastard válasza zombee hozzászólására (») Feb 1, 2016 /
 
Köszönöm a tippeket!
A hármasat alkalmaztam is, mivel az AVR-nek jelenleg nem kell adatot fogadnia. Véletlenül maradhatott benne.
(#) vyky válasza Sick-Bastard hozzászólására (») Feb 1, 2016 /
 
Köszönöm nézem
(#) vyky válasza gerry hozzászólására (») Feb 1, 2016 /
 
Köszi
(#) vyky válasza Ricsi89 hozzászólására (») Feb 1, 2016 /
 
Sajnos első nekifutásnak csak azt tudtam össze rakni,de szerencsére vannak itt segítő emberek
(#) Axel válasza zombee hozzászólására (») Feb 1, 2016 /
 
Ezt természetesen ellenőriztem az AVR Tools-ban és az mfile-ban is. Atmega8-at gond nélkül tudok programozni, és tudtam korábban ezt a most hibásnak tűnő atmega128-ast is. Azóta a fuse biteken semmit sem módosítottam. Érdekes, hogy van olyan kisebb méretű program amit fel tudok rá tölteni, az látszólag működik is de akkor is ezt a hibaüzenetet kapom.
(#) zombee válasza Axel hozzászólására (») Feb 1, 2016 /
 
Az AVR Tools IC-beállítása és a makefile (tudomásom szerint) inkább a fordítónak szól, nem a
programozót kezelő szoftvernek. Parancssorban próbáld meg az égetést, a jó IC-t (m128) megadva.
A hozzászólás módosítva: Feb 1, 2016
(#) wbt hozzászólása Feb 1, 2016 /
 
Valaki vezérelt már AVR-el WS2812B okos RGB LED-eket?
Az a bajom, hogy infra távirányító bejárat is kellene a vezérlőhöz, de a LED vezérlése időkritikus. Hogyan lehetne összehozni a kettőt? (már hogy ne köszönjön bele a LED-vezérlésbe a bármikor jöhető infra jel lekezelése). Kicsi AVR-el kellene megoldani, STM32xxx-el menne a dolog a DMA miatt, de itt nincs ilyen.
(#) zombee válasza wbt hozzászólására (») Feb 1, 2016 /
 
A WS2812B statikus működésű, azaz ha megkapta a jelet, a világításhoz nem kell további jelátvitel.
Egy okos RGB (tudtommal) statikus, azaz egy távirányító-nyomás hatására képet vált, majd ismét figyelni fogja az infrát. Csak szólok hogy "egyszerű" AVR-el sem piskóta egy ilyen meghajtása.
A PWM pl. tudja ezt, mert ott az 1200ns-os bitidő alatt csak 1-szer kell beavatkozni(OCR-t írni)
USART-ra is van egy elméletem hogy működne, 3 bitidő alatt 1-szer kell beavatkozni(UDR-t írni).
Természetesen a PWM és USART megoldás is szinkronizált, nem kritikus hogy az éppen adás alatt
lévő bit (vagy 3-bit) melyik szakaszában állítod be a következő csomagot.
A hozzászólás módosítva: Feb 1, 2016
(#) Kovidivi válasza Axel hozzászólására (») Feb 1, 2016 /
 
Nekem van egy tippem. Fogadjunk, hogy nincs 100nF kondi az AVR lábainál!
(#) zombee válasza fecus hozzászólására (») Feb 2, 2016 /
 
Tessék, itt az idei i2c verzióm. Ezzel már EEPROM-ot is kezelhetsz, és "csak" két függvény
használatát kell megtanulni: I2C_READ_REGISTERS, I2C_WRITE_REGISTERS.
Egyszerű (regisztercímzés nélküli) cuccokhoz is jó(pl. PCF8574), bár utóbbihoz külön függvény is van.
A hozzászólás módosítva: Feb 2, 2016

i2c.h
    
(#) zombee válasza wbt hozzászólására (») Feb 2, 2016 /
 
Ha az okos LED folyamatosan változtatja a színét és nem láncba vannak kötve(mindegyik ugyanazt a színt adja), akkor még megoldható 1 darab AVR-el: az infra sebessége max. 2400 bit/sec, kb. ezerszer (!!!) lassabb mint a LED adatvonala. Ehhez annyit kell tenni hogy a 24 bit átvitele után mindig megnézed, van-e jel az infrán. Egyetlen bitről se maradsz le, hidd el nekem.
(#) wbt válasza zombee hozzászólására (») Feb 2, 2016 /
 
A kivitel SW, nincs UART, de belegondolva, nekem kimaradt a msec és a nsec között a usec, tényleg elkapható az infra két, akár 8-bites blokk kiküldése között is, mert van legalább 30 usec, míg strobe-jel keletkezne. Mondjuk, elég érdekes lesz a program, mert a színek megalkotása közben is figyelni kell (ott mehet INT alapon is) meg a 100 LED adatainak kiküldése között is. (és maradt rá 800 byte-om, na, lesz, ami lesz).
Köszi a felhomályosítást!
(#) fecus válasza zombee hozzászólására (») Feb 2, 2016 /
 
Köszönöm.
(#) Gj hozzászólása Feb 3, 2016 /
 
Üdv!

Az alábbi kód egy ATTiny25-re írt program.
Nem értem, mi a probléma vele. Nem dolgoztam még konkréten ezzel az IC-vel, de más AVR-ekkel elég sokat foglalkoztam már és nem volt semmi gondom velük.

Egyszerűen olyan, mint ha nem érezné a bemeneteit. Se a PB1, se a PB2 lábon nem működik (többet nem próbáltam ki). Ha csak simán programból kapcsolgatom a LED-et a PB3 lábon, akkor nincs gond, a kimenet működik.

Mit rontok el?

  1. int main(void)
  2. {
  3.     DDRB |= (1<<PINB3);
  4.     while (1)
  5.     {
  6.                 if(PINB & (1<<PINB1))
  7.                 {
  8.                         PORTB &= ~(1<<PINB3);
  9.                 }
  10.                 else
  11.                 {
  12.                         PORTB |= (1<<PINB3);
  13.                 }
  14.     }
  15. }
A hozzászólás módosítva: Feb 3, 2016
(#) Balázs válasza Gj hozzászólására (») Feb 3, 2016 /
 
A kód jónak néz ki. Olyan ötleteim vannak, hogy:
1. Nem látjuk az áramkört, de a belső felhúzóellenállást nem kapcsoltad be, úgyhogy vagy kell külső, vagy push-pull módon kell meghajtani a bemenetet.
2. Az 1-es láb nincs-e lehúzva (reset)?
3. A fuse bitekkel biztosan olyan órajel van-e beállítva, ami neked kell?
4. A makródefiníciókkal minden rendben van-e? Esetleg próbáld meg átírni a PINBx-eket a megfelelő számértékre.
(#) Gj válasza Balázs hozzászólására (») Feb 3, 2016 /
 
Sikerült közben megoldanom. Az IC volt a hibás. Egyik lába sem működött bemenetként jól, végigpróbáltam. Másikkal működik.

De köszönöm a választ!
(#) Droot hozzászólása Feb 4, 2016 /
 
Sziasztok!

3x4-es keypad-ot szeretnék kezelni. Milyen logika szerint kell?

A bekötése:
Ezeken van felhúzóellenállás:
COL1 PB2
COL2 PB0
COL3 PB4
Ezeken nincs felhúzó:
ROW1 PB1
ROW2 PB6
ROW3 PB5
ROW4 PB7
(#) Massawa hozzászólása Feb 4, 2016 /
 
Egy kérdésem lenne.
Van egy sereg sztatikus állapot egy berendezésben ( <256 jelenleg) ezeket az állapotokat kellene egy távolabb levö kezelöpulton kijelezni. Nyilván nem akarok 256 vezetéket huzni, igy keresek egy egyszerü megoldást, ahol néhány vezetékkel (<5) lenne jo ezeket a jeleket átvinni a berendezésböl a pultba.
Mi lenne a legegyszerübb megoldás.
1. RS232-be konvertálni majd vissza
2. Kitalálni egy egyedi kodot
3. Egyébb ötlet.

Kösz.
(#) Droot válasza (Felhasználó 15355) hozzászólására (») Feb 4, 2016 /
 
Ajajj, a hw fix, max kiforrasztani tudom az ellenállásokat. De úgy meg ellenállás nélkül marad.

Mehet fordítva is, úgy hogy a sor kimenet és oszlop bemenet?
És a magasba billentés helyett lehet testre húzni, úgy használhatnám a felhúzó ellenállást az AVR-ben.
A hozzászólás módosítva: Feb 4, 2016
(#) csatti2 válasza Massawa hozzászólására (») Feb 4, 2016 /
 
Feltételezem, hogy csak egy irányba megy a kommunikáció.
A legegyszerűbb ha kihúzol két vezetéket és az egy optoban találkozik a másik oldalon. Ezen az oldalon természetesen nem direktben hajtod meg, hanem mondjuk egy mosfeten keresztül (plusz előtét ellenállás és diódás védelem, ami kimenet az bizonyos szemszögből bemenet is ugye ).

A kommunikáció történhet úgy, hogy a preamble szakaszban fel-le húzod a jelet párszor (ezzel megmérhető a másik oldalon az órajele a kommunikációnak), majd átlövöd 8 biten az állapotot és kész.

Ezzel a módszerrel csak két vezeték szükséges, viszonylag érzéketlen a feszültségesésre (nagy távolságok is áthidalhatóak) és megoldott a galvanikus leválasztás a két rész között.
A hozzászólás módosítva: Feb 4, 2016
(#) Droot válasza (Felhasználó 15355) hozzászólására (») Feb 4, 2016 /
 
Most pontosan úgy kötöttem be, mint ebben a cikkben. Azonban nem jó. Ezzel a kóddal próbálkozom:
  1. PORTB = (1<<PB1);
  2.         if(PINB & (1<<PB2)) return 1;
  3.         if(PINB & (1<<PB0)) return 2;
  4.         if(PINB & (1<<PB4)) return 3;
  5.         PORTB &= ~(1<<PB1);


A konfig bedig: DDRB = (1<<PB1) | (1<<PB6) | (1<<PB3);

A PB1, PB6, PB3 a sorok.
(#) Massawa válasza csatti2 hozzászólására (») Feb 4, 2016 /
 
Az optok a berendezésben megvannak, ezt már igy terveztem, hogy galvanikusan le tudjam választani a pulttól. Azaz majd lesz (most még nincs annyi) kb 200 opto kimenet, ezeket kéne leszkennelni (leolvasni) majd kivinni a pultra.
(#) Droot válasza Droot hozzászólására (») Feb 4, 2016 /
 
Nos, az egyszerűség kedvéért a képen látható a kapcsolási rajz. Az ellenállásokat átkötöttem a testre, így lefelé húznak.
És ezt a keypad-et használom.
(#) killbill válasza Massawa hozzászólására (») Feb 4, 2016 /
 
Tehetsz egy kazal shift regisztert, es harom droton atviszed a jelet (-> LOAD, -> CLOCK, <- DATA). Igy nem kell mikrokontroller arra az oldalra, ahol a 256 jeled keletkezik, csak a shiftek (pl. 74HCT165). Ha mikrokontrollerrel is lehet dolgozni, akkor eleg egyetlen jel, es 10-12 byte-on atkuldod a 256 bitet, az mar tenyleg csak fantazian mulik.

Az atviteli medium az tavolsag es kornyezet kerdese. Az aramhurkos optos megoldas eleg jo, es nem is tul draga. A sebessege moderalt, de 100-200 kbit/s siman atmegy rajta (TLP118, HCPL2630). Ado oldalon egy aramgenerator, a vevo oldalon pedig az opto LED-je. Az aramgeneratort meg az atvinni kivant jel vezerli ki/be. (Pl. rovidre zarja a kimenetet egy FET-tel.)

Ha nem kell galvanikus levalasztas, akkor is van sok megoldas, differencial, RS232, de ha csak 1-2m, akkor meg az open kollektoros meghajtas, vevo oldalon 220 ohm tapra, Schmitt triger. Utobbi esetben szalagkabel hasznalata, 1 fold, 1 jel, 1 fold, 1 jel bekotesben javasolt.
(#) Massawa válasza killbill hozzászólására (») Feb 4, 2016 /
 
A távolság csak 3 méter ( már ott van a 90 eres vezeték).
Kösz az ötleteket, utánnanézek mi hentereg valamelyik fiok alján mert én is alapbol valami klasszikus HW-s megoldásra gondoltam az AVR-k már ott vannak, részben azok generálják azokat az állapotokat, amiket a pulton ki szeretnék jelezni. Nem kell galvanikus leválasztás, mert az már megvan a bemeneten, a kimeneteken meg csak LED-k vannak.
(#) Droot válasza Droot hozzászólására (») Feb 4, 2016 /
 
A main-em pedig a következő:
  1. int main(void)
  2. {
  3.         InitLCD();              //LCD inicializálás
  4.  
  5.     DDRD |= (1<<PD5) | (1<<PD7);
  6.  
  7.     OCR0B = 255;
  8.         //Init PWM
  9.     TCCR0A |= (1 << COM0B1);
  10.     TCCR0A |= (1 << WGM01) | (1 << WGM00);
  11.     TCCR0B |= (1 << CS01);
  12.  
  13.         DDRB = (1<<PB1) | (1<<PB6) | (1<<PB3) | (1<<PB5);
  14.  
  15.         uint8_t key = 255;
  16.         char tmp[10];
  17.         while(1)
  18.         {
  19.                 //key = 10;
  20.                         PORTB = (1<<PB1);
  21.                         if(PINB & (1<<PB0)) key = 2;
  22.                         if(PINB & (1<<PB2)) key = 1;
  23.                         if(PINB & (1<<PB4)) key = 3;
  24.                         PORTB &= ~(1<<PB1);
  25.  
  26.                         PORTB = (1<<PB6);
  27.                         if(PINB & (1<<PB0)) key = 5;
  28.                         if(PINB & (1<<PB2)) key = 4;
  29.                         if(PINB & (1<<PB4)) key = 6;
  30.                         PORTB &= ~(1<<PB6);
  31.  
  32.                         PORTB = (1<<PB5);
  33.                         if(PINB & (1<<PB0)) key = 8;
  34.                         if(PINB & (1<<PB2)) key = 7;
  35.                         if(PINB & (1<<PB4)) key = 9;
  36.                         PORTB &= ~(1<<PB5);
  37.  
  38.                         PORTB = (1<<PB3);
  39.                         if(PINB & (1<<PB0)) key = 0;
  40.                         if(PINB & (1<<PB2)) key = 10;
  41.                         if(PINB & (1<<PB4)) key = 11;
  42.                         PORTB &= ~(1<<PB3);
  43.  
  44.                         lcd_goto(0,1);
  45.                         sprintf(tmp,"%i ",key);
  46.                         lcd_puts(tmp);
  47.                
  48.  
  49.         }
  50.  
  51.         return 0;
  52. }


Jelenlegi bekötéssel azt csinálja, hogy a középső oszlop nem működik, tehát a 2, 5, 8, 0. Érdekes, hogyha a if(PINB & (1<<PB0)) if(PINB & (1<<PB2)) if(PINB & (1<<PB4)) key = 11; sorokat cserélgetem, akkor mindig egy sor nem működik. Általában az, ami a PORTB = (1<<PBx); után jön közvetlenül.

Szerk. 1: Az ATmega328-ban nincs valami akármi, amit ki kell kapcsolni és beleszólhat?
Már mindenhogy próbáltam, de mindig olyan hibába ütközöm, ami tök evidens és nem úgy kéne működnie... a bekötést is 1000-szer átnéztem és kimértem.

Szerk. 2: Ha a PORTB = (1<<PBx); után van 1ms delay, akkor meg működik minden oszlop.

Szerk. 3: 1us delay-el is működik a PORTB = (1<<PBx); sor után.
A hozzászólás módosítva: Feb 4, 2016
(#) rolandgw válasza Droot hozzászólására (») Feb 5, 2016 /
 
Egy másik módszer,4x4-es,át kell írni:
  1. uint8_t keyscan( void )
  2. {
  3.   uint8_t col = 0, row = 0;
  4.  
  5.   KEY_PORT = 0xFF;
  6.   KEY_DDR = 0xF0;
  7.   KEY_PORT = 0x0F;
  8.   NOP();                        
  9.   if( ~KEY_PIN & 1<<0 ) col = 4;
  10.   if( ~KEY_PIN & 1<<1 ) col = 3;
  11.   if( ~KEY_PIN & 1<<2 ) col = 2;
  12.   if( ~KEY_PIN & 1<<3 ) col = 1;
  13.   row = col;
  14.   if( col ){
  15.     KEY_PORT = 0xFF;
  16.     KEY_DDR = 0x0F;
  17.     KEY_PORT = 0xF0;
  18.     NOP();
  19.     if( ~KEY_PIN & 1<<4 ) row = 5;
  20.     if( ~KEY_PIN & 1<<5 ) row = 9;
  21.     if( ~KEY_PIN & 1<<6 ) row = 13;
  22.     if( ~KEY_PIN & 1<<7 ) row = 17;
  23.   }                             // 0 = no key
  24.   return row - col;             // 1..16 = key
  25. }
(#) zombee válasza Droot hozzászólására (») Feb 5, 2016 /
 
Van egy jó hírem: ha mezei ebay-es a billentyűzet max. 10-15 centi szalagcsíkkal, akkor nem is kell feltétlenül felhúzó ellenállás, elég az AVR-ben lévő 47kOhm-os felhúzó is. Ha teszel akkor vagy a sorokhoz, vagy az oszlopokhoz. Mind a 7 vezetékre is tehetsz, de fölösleges. Ha lehúzót teszel(földre húzol) akkor egy picit módosul a program logika is, de ezt beolvasáskor úgyis korrigálod. Ha nincs ellenállás akkor felhúzót(47kOhm belső) kell beállítanod vagy a sor, vagy az oszlopokra. A lényeg hogy a fel/lehúzott blokk lesz a bemenet, a másik blokk kimenet.

Beolvasáskor egyik kimenetet bekapcsolod: DDR=1, PORT=0 vagy 1 attól függően hogy fel-vagy lehúzó ellenállás van a bemeneti blokkon. A többi kimenetnél DDR=0, PORT=0; azaz teljesen ki kell kapcsolni! Aztán beolvasod a bemeneti blokkot, letárolod majd váltasz kimenetet és így tovább.

Én timer megszakításban kezelem a billentyűzetet, és ez azért jó mert a programban nem kell a portok kapcsolgatásával, beolvasgatásával foglalkoznom: a billentyűzet kezelése a "háttérben" működik. Az időzítő megszakítás (nálam) egy ütemben csak egy sort/oszlopot olvas be, majd a művelet végén átkapcsol a következőre. Így a következő időzítő-megszakításig bőven lesz idő a tranziensekre ami az átkapcsolásból adódik. Megjegyzem hogy egy 3x4-es billentyűzet rövid kábellel egyetlen időzítő-megszakításban is kezelhető és talán úgy egyszerűbb is.

Ha lenyomtak egy gombot(és csak egyet), azt egy egyszerű 8 bites változóban ("keypressed") beállítja a megszakítás. Ezt a változót főprogram bármikor tudja olvasni (volatile legyen!), nem kell hozzá port-állítgatás Ha nincs gombnyomás vagy többet nyomtak le egyszerre akkor (nálam) 255 az érték. Ezt a változót még meg lehet bolondítani úgy hogy csak lenyomáskor állítsa be a megszakítás (előző ciklusban nem volt semmi, most meg lenyomva van akkor beállítom az értéket), illetve kiegészíthető némi pergésmentesítéssel (pl. csak akkor állítom be a keypressed-et ha x megszakítás óta nem volt billentyűzet esemény).

Ha egyszerre több gombot is lenyomhatnak akkor kicsit bonyolultabb lesz a programod, pl. használnod kell több keypressed változót, esetleg a speciális funkcióra segédváltozót. A legutóbbi projektemben a * és # egyszerre lenyomásakor újraindítás kellett. Ehhez nem kellett még segédváltozó sem, mert a funkciót(összes port kikapcsolása, watchdog bekapcsolás, végtelen ciklusba állás) az időzítő megszakításon belül meg lehetett oldani.
A hozzászólás módosítva: Feb 5, 2016
(#) killbill válasza zombee hozzászólására (») Feb 5, 2016 /
 
Idézet:
„Én timer megszakításban kezelem a billentyűzetet, és ez azért jó mert a programban nem kell a portok kapcsolgatásával, beolvasgatásával foglalkoznom:”
Ehhez azert tegyuk hozza, hogy ilyenkor az adott porton a maradek labakat nem tudod egyszeruen billegetni, mert a port regisztert az interrupt is allitja. Ugy lehetseges, ha letiltott megszakitas mellett allitod, vagy ha garantalni tudod, hogy egy processzor utasitassal allitasz at egy bitet. De azt nem teheted meg, hogy a megszakitas bizergalja mondjuk a PORTB-t, es te a foprogramodban is irsz egy olyat, hogy PORTB |= 1;
A PORTB |= 1; egy olvasas, logikai OR es egy iras muveletre fordul, es ha az utasitasok kozott a megszakitas is valamit valtoztat a PORTB-n, akkor annak az eredmenye elvesz, amikor a foprogramban legv PORTB |= 1; visszairja a port-ra a modositott byte-ot.

Prellmentesitesnek meg minden faxni nelkul teljesen eleg az, ha a billentyuket 20..50ms indonkent olvasod be. A prell ennel rovidebb ideig tart, igy nem kell vele kulon foglalkozni.
Következő: »»   721 / 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