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   525 / 840
(#) sikolymester válasza Hooligan01 hozzászólására (») Márc 12, 2013 1 /
 
Belinkelnéd az adatlapját.
Én felcsaptam 2 Ramtron FRAM adatlapot, ahol 10^14 írás/olvasás ciklust adnak meg.
Bővebben: Link
Bővebben: Link

Csak kíváncsi vagyok, mert szokatlan szóhasználatnak tűnik egy adatlapban. Főleg annak függvényében, hogy legjobb tudomásom szerint az FRAM tényleg véges élettartamú.

update:
Ne fáradj, megtaláltam googlival.
Bővebben: Link
A hozzászólás módosítva: Márc 12, 2013
(#) csabeszq hozzászólása Márc 12, 2013 /
 
Az EEPROM írásánál én a bájtonkénti keresést és a pozíciótárolást ötvözném:

- EEPROM-ban tárolsz mondjuk egy 1k-s címet
- utána visszaolvasod az 1k adatból, hogy melyik volt az utolsó adat
- amikor laphatárt lépsz át, növeled a címet (ritka)

De lehet még szórakozni azzal, hogy ha a puffer végére érsz, akkor a számlálóba 0xFFFF-et írsz, ami azt jelenti: elhasználva. Ilyenkor a következő 2 byte-ot fogja használni számlálásra.

Lehet trükközni a dologgal.
(#) zombee válasza sikolymester hozzászólására (») Márc 12, 2013 /
 
A merevlemezek is hasonló elven rögzítenek, aztán idővel mégis bad sectoros lesz.
És biztos hogy nem a csapágy miatt...
(#) benjami válasza blackdog hozzászólására (») Márc 12, 2013 /
 
Én úgy oldanám meg a tárolást az EEPROM-ban, hogy minden adathoz hozzárendelnék egy 32 bites számlálót is. Ezt a számlálót minden rögzítésnél növelném, és tárolnám is a hőmérsékletek és a dátum/időponttal együtt. A program indulásakor megkeresném a legnagyobb értékű számlálót (bináris kereséssel nagyobb méretű memóriában is hamar meg lehet találni hová történt az utolsó adat rögzítése), az utána következő helyre már mehet is a rögzítés folytatása. Így a memória minden cellája kb. ugyanannyiszor kerülne írásra. További lehetőség, hogy minden memóriacella írása előtt megnézném a cella aktuális értékét. és csak akkor írnám ha az különbözik a beírandó értéktől (ha pl. a hőmérséklet nem változott az előző körben beírt hőmérséklethez képest akkor felesleges az adott memóriacellába ugyanazt az értéket még egyszer beírni).
(#) skimen hozzászólása Márc 12, 2013 /
 
Sziasztok!

Egy kis segítséget szeretnék kérni:
Az alábbi program egy LEDet kapcsolna fél másodpercig be, aztán ki.
Valójában a timer kezelés lenne a lényeg, sajnos nagyon pontatlan.

A mC egy Attiny13, ami gyári beállításokkal 9,6 Mhz /8-al ketyeg (1,2Mhz).
A timert úgy szeretném beállítani, hogy 125 us-enként adjon megszakítást.

Jó e a számításom?
1/1200000/1000000=0,833333

azaz 0,833333 us alatt növekszik egyel a TCNT0 reg.
125/0,833333=150

azaz 150-el kell visszaállítani a TCNT0 reget.

Ilyenkor 256 ból kell kivonni ezt az értéket vagy 255-ből?

Miután a 125us-ból képezem a másodperces jelet így kis eltérés
a végeredményt nagyon rontja.

Köszönöm a választ!

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <avr/io.h>
  4. #include <avr/interrupt.h>
  5.  
  6. #define bs(sfr,bit) (_SFR_BYTE(sfr)|=_BV(bit))   //bit set
  7. #define bc(sfr,bit) (_SFR_BYTE(sfr)&=~_BV(bit)) //bit clear
  8. #define btg(sfr,bit) (_SFR_BYTE(sfr)^=_BV(bit)) //bit toggle
  9. #define tb(sfr,bit) (bit_is_set(sfr,bit))
  10.  
  11. #define s_led bs(PORTB,4);
  12. #define c_led bc(PORTB,4);
  13.  
  14. volatile unsigned int tik=0;
  15. volatile unsigned int mp=0;
  16.  
  17. ISR(TIM0_OVF_vect){  //125us
  18.         TCNT0=105;
  19.         tik++;
  20. }
  21.  
  22. int main(void){
  23.         TCCR0A=0;
  24.         TCCR0B=_BV(CS00);
  25.         TCNT0=105;
  26.         TIMSK0=_BV(TOIE0);
  27.         bs(DDRB,4);     //led
  28.         bs(DDRB,3);     //duda
  29.         sei();
  30.  
  31.         while(1){
  32.                 if (tik<=4000){
  33.                         s_led;
  34.                 }
  35.                 else{
  36.                         c_led;
  37.                 }
  38.                 if (tik>=8000){
  39.                         tik=0;
  40.                         mp++;
  41.                 }
  42.         }
  43. }
(#) csabeszq válasza skimen hozzászólására (») Márc 13, 2013 /
 
Attiny13

Lapozz a 72. oldalra, ott látod a TIMER0 működési módjait.

Neked olyan kell, ami 0-tól OCRA-ig számol, az OCRA meg legyen 150. Ezt Avr Studio-val érdemes kipróbálni.
(#) sikolymester válasza skimen hozzászólására (») Márc 13, 2013 /
 
Csabeszq kollégára ne hallgass. Amit csináltál az teljesen jó, csak azt nem vetted figyelembe, hogy az interruptod nem 0 órajel alatt hajtja végre a dolgokat.
Studio szimulátor megadja a választ a turpisságra, lásd a képen. A képen két interruptba ugrás eltelt idejét láthatod.

Amit tehetsz, hogy beállítasz egy előosztást a timerre, ami miatt pontosabb lesz az egész, mivel most a timered elvileg 125us -et mér, az interrupt pedig csak amíg bepusholja a regisztereket, elmegy 18us. Ha a timered 500ms-et mérne, akkor ez a 18us szinte semekkora jitter lenne.

Persze ha pró vagy, akkor teljesen kézben tarthatod az interrupt hosszát, de én a timer előosztót javasolnám.
A hozzászólás módosítva: Márc 13, 2013
(#) skimen válasza sikolymester hozzászólására (») Márc 13, 2013 /
 
Köszönöm a hozzászólást!

Nekem a 125 us-os megszakítás fontos (egy csipogó miatt).
Viszont az is fontos, hogy a másodpercet pontosan tudjam mérni,
akkor ez azt jelenit, hogy 143 ms-nak kell számolni a megszakítás meghívását?

Azaz nem 8000 lesz a másodperc letelte, hanem 1000000/143=6993?
(#) csabeszq válasza sikolymester hozzászólására (») Márc 13, 2013 /
 
Interruptban állítani a TCNT0-át és utána ezt "pontos" időnek venni marhaság, úgy ahogy van.

Egy cli() meghívása után a pontos idődet megeheted, arról ne is beszéljünk, hogy az utasítások 1-8 órajel között bármilyen hosszúak lehetnek. Ennél csak egy nagyobb marhaság van, az, hogy kidebuggolni AVR studioval, hogy a push/pop-ok mennyi időbe kerülnek és ezt felhasználni. Jön egy új gcc verzió és megint megeheted az egészet.

Amit én írtam, abban a hardver elszámol OCRA-ig, interrupt és újrakezdi a számolást. Ennél kevés egyszerűbb dolgot tudok elképzelni. Állandóan ezt csinálom ATmega48 alatt. Ott kicsit jobbak a timerek, de sima ügy.

Zenét úgy adok ki, hogy OCRB-t beállítom OCRA/2-re, OCRA-ig számol, így adja ki a négyszög jelet a PWM-en.

Az egész LED villogtatást a hardver maga megoldaná, neked csak egy

while(1);

ciklus kellene.
A hozzászólás módosítva: Márc 13, 2013
(#) csabeszq válasza csabeszq hozzászólására (») Márc 13, 2013 /
 
Idézet:
„PWM with 2ms period and 10% duty

Configure timer 0 to generate a 2ms period with a 10% duty cycle.

The fast PWM mode where the period is controlled by OCRA has (WGM2,WGM1,WGM0) = (1,1,1). The compare match B output must be used and it should turn on at TOP and reset at match. This happens when (COM0B1,COM0B0) = (1,0). The prescaler is set to 64.

TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(WGM02) | _BV(CS01) | _BV(CS00);
OCR0A = 250;

The duty cycle (period the PWM is on) is controlled by OCR0B. The range of OCR0B is from 0 to OCR0A (or 250 in this case). If OCR0B exceeds OCR0A, then the PWM output will be always on. A duty cycle of 10% is set by:

OCR0B = OCR0A * 10% = 250 * .1 = 25

The configuration is complete when OCR0B is assigned:

OCR0B = 25;

Changing the output compare control setting (COM0B1,COM0B0) = (0,1) inverts the waveframe (i.e., the output will be off for 10% and on for 90%).”
A hozzászólás módosítva: Márc 13, 2013
(#) sikolymester válasza csabeszq hozzászólására (») Márc 13, 2013 /
 
Így bizony sokkal elegánsabb.
Skimen, tévedtem: halgass csibeszq -re.

Az órajel tévedés hátterének rejtélye mindenesetre fel lett fedve.
(#) skimen válasza csabeszq hozzászólására (») Márc 13, 2013 /
 
Nagyon köszönöm!

Sikerült beállítani
(#) pittosi hozzászólása Márc 13, 2013 /
 
Ha tud valaki segíteni atiyi45 ez a kis progi . Hogy kell át írni, hogy felváltva villogjanak a ledek ?
(#) pittosi hozzászólása Márc 13, 2013 /
 
Gyakorlás miatt kéréném a segítséget
(#) killbill válasza pittosi hozzászólására (») Márc 13, 2013 /
 
Csak a valtoztatast irom:

  1. 23.     PORTB = 1 << PINB3;    //az egyik vilagit, a masik nem
  2. 24.     for(;;){
  3. 25.         PORTB ^= (1 << PINB3) | (1 << PINB4);
  4. 29.         m_delay_10ms(100); //100*10ms = 1s
  5. 30.      }
(#) dB_Thunder hozzászólása Márc 14, 2013 /
 
Hali mindenki!

Szívok egy kicsit (1.5 napja) mega8 és 2*16-os LCD-vel.
Az alapgondolat az volt hogy átportolom az itteni enkóderres (2xdekodolás) cikket Tinyről megára, de kijelzőn csak "kockák" vannak. LCD bekötése ua. minta tinynél (PORB-re)
Ezután elkezdtem nézegetni, tesztelni a HE-n fellelhető LCD drivereket és példaprogramokat.
Mindegyikhez megcsináltam a portbeállítást, kicsipogtam hogy minden vezeték oda megy ahova kell. Mega belső 8MHz-ről megy, ezt is beállítottam a programban, de a kockák maradtak !
A kijelző tökéletesen megy az LCM3-ban, a mega is új, más hardver nincs is rajta csak a kijelző.

Hol bukhat még el a projekt??
(#) kiborg válasza dB_Thunder hozzászólására (») Márc 14, 2013 /
 
Szia!
Leggyakoribb a szoftver. Másik kérdéses dolog, hogy milyen kijelző? (44780 kompatibilis?) 4 vagy 8 bites üzemmódban használod? A nem bekötött lábakkal mit csináltál? Figyeled a kijelző foglaltságát vagy időzített az adatküldés?
Kiborg
A hozzászólás módosítva: Márc 14, 2013
(#) dB_Thunder válasza kiborg hozzászólására (») Márc 14, 2013 /
 
Kijelző: DEM16216 természetesen hd44..kompatibilis, azért is írtam hogy működik LCM3 műszerben, 4bit módban (abból szedtem ki) 4 bites módban használnám a "maradék" láb a földre van kötve.
Köszönöm a válaszod!
(#) kiborg válasza dB_Thunder hozzászólására (») Márc 14, 2013 /
 
Akkor nagy a valószínűsége, hogy mégis a programmal van valami. Lehet átnézni a programot és kitalálni a hibát. AZ AVR megy rendesen? Külső/belső órajel ? Megfelelő frekin megy? Időzítések rendben vannak?
Kiborg
(#) dB_Thunder válasza kiborg hozzászólására (») Márc 14, 2013 /
 
Idézet:
„AZ AVR megy rendesen?”

Ez az amit ugye nem látok.. kellene a kódba szúrnom egy led villogtatást...
Belső RC 8Mhz-en kellene neki ketyegnie, a programban megadtam az F_CPU-t, elvileg ettől az időzítésnek is jónak kellene lennie.
(#) dannu hozzászólása Márc 14, 2013 /
 
ATMEGA48 lehet-e pic kit 2 vel programozni , ha igen hogyan ?
(#) zsozsoX hozzászólása Márc 14, 2013 /
 
Sziasztok
AVR studioban nem jelenik meg az 'external dependencies'-ben a külső fájlok, valaki esetleg tudna segíteni?
Köszi
(#) blackdog válasza dB_Thunder hozzászólására (») Márc 15, 2013 /
 
Idézet:
„Az alapgondolat az volt hogy átportolom az itteni enkóderres (2xdekodolás) cikket Tinyről megára,”
Melyik ez a cikk ? Keresem, de nem találom..

Amúgy én is jártam már így és az LCD inicializálással volt gondom. Az időzítésekkel. Nálad is lehet mert nem éled fel az AVR.
(#) sikolymester válasza zsozsoX hozzászólására (») Márc 15, 2013 /
 
Melyik verzióban?
(#) Robi98 hozzászólása Márc 15, 2013 /
 
Sziasztok!

Szeretnék készíteni egy olyan programot ami egy gomb megnyomására generál egy véletlenszerű számot 0 és 100 között majd ezt kiírja egy 7 szegmenes kijelzőre. AVR esetén ezt hogyan kell csinálni? Mert azzal a módszerrel amit itt olvastam azzal hibát jelez a fodító.

Köszönök minden választ!
(#) mzozo95 hozzászólása Márc 15, 2013 /
 
Sziasztok!
Atmega48 timer megszakítást szeretnék létrehozni, 8as előosztással, és a counter alapértékét 246 ra szeretném állítani, ezzel 80as előosztást elérve.
Ennyire jutottam, de valami gond lehet a kódommal, mert nem pontos az osztás, mintha nagyobb lenne az előosztás...
  1. void InitTimer(void)
  2. {
  3. TCCR2B = (1<<CS21);
  4. TCNT2=246;
  5. TIMSK2 |= (1<<TOIE2);
  6. }
  7. //...
  8. ISR(TIMER2_OVF_vect)
  9. {
  10. TCNT2=246; //10szeres osztás, összesen 80szoros, 100khz, 100 egység=1ms
  11. if (ciklus==0){PORTC=255;PORTB=255;PORTD=255;};
  12. ciklus+=1;
  13. if (ciklus>=2000){ciklus=0;}; //20ms
  14. }

Valaki tudna segíteni? Miért nem 80 az előosztás?
Üdv.: Zoli
(#) zsozsoX válasza sikolymester hozzászólására (») Márc 15, 2013 /
 
AVR Studio 4.18
(#) kiborg válasza Robi98 hozzászólására (») Márc 15, 2013 /
 
Ezzel a véletlenszám dologgal nem vagy egyedül.
Több megoldás is van. ha pl gombnyomásra kell kiírnia, akkor a legegyszerűbb, ha pörgetsz gyorsan egy számlálót és gombnyomásra megállítod. (pl 100kHz es órajellel) ekkor esélytelen kiszámolni, hogy mi lesz az eredmény. De ha programozni akarod, akkor nehezebb a dolgod sajnos. Van hardveres random generátor, de az macerás. De az tuti. Szoftveresen még nem találtam meg az igazit.
Kiborg
(#) sikolymester válasza kiborg hozzászólására (») Márc 15, 2013 /
 
Én a szabadon lógó ADC bemenetet használom véletlen szám generálására. 10-szer beolvasom a mért értékét, aminek rendre az LSB bitjét beshiftelem balra egy kezdetben üres változóba. A végén lesz egy 10 bites, eléggé véletlenszerűnek tekinthető eredményem.

Majd egyszer loggolok pár 10 ezer mérést ezzel a módszerrel, és megnézem mennyire egyenletes az eloszlása.
(#) Robi98 hozzászólása Márc 15, 2013 /
 
Köszönöm az ötleteket, sikerült megoldanom!

A megoldás nálam ennyi:
  1. int szamjegy;
  2.  
  3.    while(1)
  4.    {
  5.      while(!(PINC&(1<<PC0)))
  6.          {
  7.          szamjegy++;
  8.          if(szamjegy==100) szamjegy=0;
  9.          
  10.          }
  11.          
  12.          PORTD|=(1<<PD6);
  13.         PORTD&=~(1<<PD7);
  14.         PORTB=szamok[szamjegy/10];
  15.         _delay_ms(10);
  16.                 //____________________________
  17.                  PORTD|=(1<<PD7);
  18.           PORTD&=~(1<<PD6);
  19.         PORTB=szamok[szamjegy%10];
  20.         _delay_ms(10);
  21.    }

Lehet, hogy nem a legtökéletesebb megoldás, de így is eléggé véletlenszerű.
Következő: »»   525 / 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