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   605 / 838
(#) holex hozzászólása Máj 22, 2014 /
 
Ha letiltom a globális megszakítást, kajd később engedélyezem, akkor a letiltás ideje alatt történő megszakítások le fognak futni egymás után? (Persze csak ha különböző típusúak voltak).
(#) tursaba válasza holex hozzászólására (») Máj 22, 2014 /
 
Szerintem nem.
(#) Zsora válasza holex hozzászólására (») Máj 22, 2014 /
 
Szerintem meg igen. A megszakításjelző flag-ek az engedélyezéstől függetlenül magasra állítódnak egy esemény bekövetkeztekor. A tiltás csak annyit tesz, hogy nem veszi ezt figyelembe a proci, és nem szakítja meg az éppen futó programot. Viszont ahogy újra engedélyezzük a megszakításokat, a magas megszakításjelző flag-ek egyből megszakítást generálnak sorjában a prioritási szintnek (vagy a belső logikának) megfelelően.
Próbáld csak ki!
Sőt! Amennyiben a megszakításkezelő rutinod nem törli a megszakításjelző flag-et, kilépés után újra megszakítás generálódik.
(#) holex válasza Zsora hozzászólására (») Máj 23, 2014 /
 
Köszönöm! De amúgy amikor lefut a megszakításkezelő rutin, az alapból törli a flag-et, nem?
(#) rolandgw válasza Zsora hozzászólására (») Máj 23, 2014 /
 
A megszakítás kezelő rutin törli a flag-et a RETI utasítással.
A flag-ek minden esetben beállnak,mint ahogy írtad is,de az adott megszakítás csak akkor fut le,ha az engedélyezve van és a global is 1-es. Flag-et 1-be írással lehet törölni.
Tehát a megszakítás így fut le: global 0-ba áll ,majd reti utasításra 1-be és törlődik az adott flag is,mindez hardveresen.
(#) rolandgw válasza rolandgw hozzászólására (») Máj 23, 2014 /
 
Bocs,annyit korrigálnék,hogy a flag akkor törlődik,amikor, a PC(program counter) az adott vektorra mutat,tehát az elején.Így létrejöhet az a helyzet is amit írtál,ha a lefutás alatt jön még egy megszakítás kérés,feltéve persze,ha nem ugrik be egy nagyobb prioritású is,mert akkor övé az elsőbbség.Elnézést a figyelmetlenségért !
A hozzászólás módosítva: Máj 23, 2014
(#) AMD válasza TavIR-AVR hozzászólására (») Máj 23, 2014 /
 
Köszönöm a segítséget. Letöltöttem az eXtreme Burner programot és azzal sikerül a fuse bit állítás.
(#) Zsora válasza rolandgw hozzászólására (») Máj 23, 2014 /
 
Üdv!
Inkább nekem kellene elnézést kérnem, mert nem igazán korrekt amit írtam, így ezt most javítom.
Tehát... Kétféle megszakítástípus létezik:

Az első típushoz tartozóknak van megszakításjelző flagjük, ami egy esemény bekövetkeztekor magasra állítódik, még ha épp tiltva is van a megszakítás. Mihelyt engedélyezve lesz, az azonnal programmegszakítást generál. (Hacsak nem jött ezalatt egy nála magasabb prioritású, mert akkor azé az elsőbbség, ő pedig várhat tovább.) A megszakításkezelő rutinba való belépéskor a flag automatikusan törlődik és minden megszakítás tiltásra kerül, de ha ezután (a megszakításkezelő rutin végrehajtása közben) mégis bekövetkezik egy esemény, az újra magasba billenti a flaget, ami majd újabb megszakítást generál kilépés után. Akár a jelenleg futó megszakításkezelő rutin is megszakítható, ha közben engedélyezzük a megszakításokat. Egyébként a flagek manuálisan is törölhetők 1-es érték beírásával. Kilépéskor (RETI) újra engedélyeződnek a megszakítások, és az esetleg addig várakozók most sorrakerülnek.

A második típusba a flag nélküli megszakítások tartoznak. Ezek csak akkor szakítják meg a programot, ha a megfelelő feltétel ideje alatt a megszakítás engedélyezve van. Útólagosan már nincsenek hatással a program menetére.
(#) zombee válasza rolandgw hozzászólására (») Máj 23, 2014 /
 
Magyarul: amikor a megszakítás LEFUT, a rutin meghívásakor törlődik a flag, azaz nem fut le újra.
Egy kivétel van: az USART "UDRE" flag. Ez mindig "1", ha üres a kimenő adat regiszter.
Ezt nem fogja törölni a megszakítás lefutása. Ha a megszakításrutinban nem történik
egy újabb bájt átvitele(pl. mert elfogyott) akkor TILTANI KELL:
  1. UCSRB &= ~(1<<UDRIE);


Természetesen, ha van új elküldendő bájt(sorozat) akkor engedélyezni kell. Ezzel a módszerrel
teljesen a "háttérben" lehet elvégezni az adatátvitelt, a főprogram futásakor elegendő
az adat feldolgozását végezni, nem kell várni az átvitelre vagy annak befejezésére.
A hozzászólás módosítva: Máj 23, 2014
(#) rolandgw válasza zombee hozzászólására (») Máj 24, 2014 /
 
When the Program Counter is vectored to the actual Interrupt Vector in order to execute
the interrupt handling routine, hardware clears the corresponding flag that generated the interrupt.
Tehát rögtön a megszakításra ugrással törlődik a flag,ami azt jelenti,hogy a megszakítás lefutása alatt is újra beállhat,újabb megszakítást generálva,amint a global megint 1-es lesz,mint ahogy ezt Zsora is írta.
Hozzá kell tenni,hogy két megszakítás között a főprogramból még egy utasítás végrehajtódik,ezt a tulajdonságot lehet debug-ra használni.
(#) elektros90 hozzászólása Máj 26, 2014 /
 
Sziasztok!
Ennek mi lehet az oka?
Már egyszer újratelepítettem, de nem segített. Az .elf fájl pedig megvan.
(#) Fizikus válasza elektros90 hozzászólására (») Máj 26, 2014 /
 
Csak egy tipp: lehet hogy a konyvtarnevekben levo ekezetes betuket nem szereti...
(#) elektros90 válasza Fizikus hozzászólására (») Máj 26, 2014 /
 
Az lesz a probléma. Köszi!
(#) grieves13 hozzászólása Máj 26, 2014 /
 
Hello, engem az erdekelne, hogy atmeg328-ast ha olyan bekotesbe rakom bele, amiben van kulso kristaly, de nem allitom at belsore, akkor az gondot okozhat?
(#) yohnsee hozzászólása Máj 26, 2014 /
 
Sziasztok!
Egy kis segítségért fordulok hozzátok.
C-ben próbálok megoldani egy programozási problémát, de valahogy nem igazán sikerül.
Attiny24 a vezérlő, rá van kötve 6db relé. Külöböző portokon, különböző lábakon. Ezeket beraktam tömbbe, nekem tetsző sorrendben. Így sorban tudom őket egymás után egy "for" ciklussal ki-be kapcsolni. És itt jön a számomra megoldhatatlannak tűnő feladat: egy relét addig kellene bekapcsolva tartani, amíg:

-az ADC4 lábról érkező A-D eredmény 5 egymást követő alkalommal nem kevesebb, mint 2 (ez az érték fix lesz, csak ki kell még számolnom) AKKOR csak lépjen egyet előre a for ciklus a tömb következő elemére,
DE HA
-nyomva tartom az "A" vagy "B" gombot kb. 20ms-ig
vagy
-az ADC4 lábról érkező A-D eredmény 5 egymást követő alkalommal túllépi a referencia értéket (ez az érték adott, az A-D konverzió free-run módban fut a háttérben) AKKOR hagyja abba a for ciklust, és ugorjon a következő parancsra.

Hogyan kellene a ciklusokat egymásba ágyazni, illetve ez így egyáltalán kivitelezhető-e? Esetleg megszakításokkal? Most eléggé tanácstalan vagyok.
(#) TavIR-AVR válasza grieves13 hozzászólására (») Máj 27, 2014 /
 
nem. A belső 1 MHz-ról jár.
(#) AzIgaziCsaby válasza yohnsee hozzászólására (») Máj 27, 2014 /
 
Én ezt inkább egy while ciklusba szervezném. Azon belül néhány segédváltozóval.
while (aktiv_relé<6)
- "aktiv_relé" értéke megadja, hogy melyik relé aktív.
- "feltétel_1" számolja az ADC4 alacsony értékeit. Ha elérte a határt, növeli az aktiv_relé értékét és nullázza a feltételeket.
- "feltétel_2" számolja, hogy hány ciklus óta nyomod a gombot. Ha elérte a határt, növeli az aktiv_relé értékét és nullázza a feltételeket. Hogy hány ciklust kell kivárnia, az órajeled szabja meg.
- "feltétel_3" számolja az ADC4 magas értékeit. Ha elérte a határt, azonnal 6-ra növeli az aktiv_relé értékét és ezzel kilép a ciklusból.
A hozzászólás módosítva: Máj 27, 2014
(#) AzIgaziCsaby válasza AzIgaziCsaby hozzászólására (») Máj 27, 2014 /
 
Azóta rájöttem, hogy figyelmetlenül olvastam. A feltétel_2 is 6-ra növeli az aktiv_relé változót.
(#) yohnsee válasza AzIgaziCsaby hozzászólására (») Máj 27, 2014 /
 
Köszönöm, ez a megközelítés még nem jutott eszembe. Viszont egy bökkenő még van:
ahhoz, hogy elkezdjek mérni az ADC lábon, ahhoz előbb el kell indítsak egy relét. Mivel a rendszer úgy lenne összerakva, hogy egy 0.05 ohm-os ellenálláson eső feszültséget mér az ADC, így érzékelve az adott relén lévő motor áramfelvételét.
A gondom a program felépítésével van. Hogyan tudom számoltatni a ciklusokat (vagy időt) úgy, hogy közben meghúzva maradjon a relém? Tehát addig ne lépjen ki, amíg nem tartom elég ideig nyomva a gombot, vagy (egy ideig) nem túl nagy az áramfelvétel.
A hozzászólás módosítva: Máj 27, 2014
(#) AzIgaziCsaby válasza yohnsee hozzászólására (») Máj 27, 2014 /
 
A ciklusba lépés előtt 1-re állítod az aktiv_relé értékét.
A ciklust úgy kezdeném, hogy vagy egy switch-case vagy 5 db if vizsgálattal bekapcsolnám a megfelelő relét:
magasat_mér=0;
aktiv_relé=1;
while (aktiv_relé<6)
{
if (aktiv_relé==1) {relé1=be, minden más relé=ki;}
if ...

gombot_nyomtak=gombot_nyomtak+1;
magasat_mér=magasat_mér+1;
if (gombot_nyomtak==ciklus_max) {aktiv_relé=6;} //ciklus max a gombnyomás ideje alatt lefutó ciklusok száma
if (magasat_mér==2) {aktiv_relé=6;}
}
(#) holex hozzászólása Máj 27, 2014 / 1
 
50 Hz-es frekvenciájú PWM kimenetet hogy lehet beállítani, úgy, hogy a TCNT1 regiszter értékén ne kelljen változtatni? (Használom másra is a Timer1-et, ezért jó lenne, ha nem kellene nullázni).
A hozzászólás módosítva: Máj 27, 2014
(#) kapu48 válasza holex hozzászólására (») Máj 27, 2014 /
 
Ha meghatározott kimeneti frekvenciát akarsz el érni, akkor vagy az órajelet variálod, vagy a számláló indulási értékét állítod be, minden túlcsordulás után.

Segítség: AVRCalc

AVRCalc
Az AVRCalc egy igazán hasznos segédprogram a mikrovezérlő fejlesztéséhez. De mire is képes:
* megjeleníti a lebegőpontos számoknak megfelelő hexanumerikus értékpárját
* Adatátviteli sebesség (Baud-rate) beállítását meghatározó UBR regiszter értékét adja meg a kristályfrekvencia és a tervezett sebesség függvényében.
Mellette a névleges és a tényleges érték eltérését is feltűnteti.
* Az előosztás mértékét, az előbeállítás adatait, a számláló- (Timer0 és Timer1) regiszterek értékét megadja a deklarált periódusidő (msec, usec), frekvencia alapján.

Adatátviteli sebesség kiszámítása
A példában a tervezett adatátviteli sebesség 9600 bps legyen és a chip frekvenciája 4.0 MHz. Ehhez az AVR BaudRate mezőbe a lenyíló menüből
válasszük ki a 9600-at. A Crystal freq(in MHz) menüből a 4.0-t kell megjelölni. A programablak aló részén az UpDate gombra kattintva meg is történik
a meghatározás.
Az UBRR regiszter értéke és a %ERR hiba megjelenítésre kerül. Ha Bascom rendszerben programozunk, akkor a UBRR regisztert a fordítóprogram
automatikusan kiszámolja nekünk. A hibatűrés - ha PC-vel kommunikálunk - a 2-3%-ot ne haladja meg. A program figyelmeztet,
ha nem beéállítható sebesség-frekvencia páros akarunk alkalmazni (pl. 14.7456 MHz és 300 bps). Ekkor kérdőjelekkel jutalmazza ténykedésünket.

Adott frekvencia előállítása
A Timer0 számlálót szeretnénk felhasználni 100Hz-es jel előállítására. a Timer0 8 bites számláló, így az értéke 0...255 között változhat.
A túlcsorduláskor megjelenő megszakításban kell beállítani az újraindulási értékét és itt lehet a kimeneti port állapotváltozását is megadni.
vagy használhatjuk a hardveres kimenet is (OC0). A számoláshoz meg kell adni a chip órajelét a Crystal freq(in MHz) menüből,
a példánkban ez legyen 4 MHz, így a 4.0-t kell megjelölni. A Prescale TCCRx regiszterben megadjuk a tervezett beállítandó előosztás mértékét,
ez legyen pl. 256 (lenyíló menüből kiválasztható). A Needed timer mezőbe beírjuk a 100-as értéket, és a rádiógombok segítségével a Units:Hz-t
kiválasztjuk. Ha a hardveres kimenetet használjuk, akkor figyeljünk arra, hogy mit állítunk be. Az OCx toggled kipipálásával a Timerx leketyegéskor
állapotváltozást adjuk meg, míg egyébként csak tüske keletkezik a kimeneten. (frekvencia kétszerezés). Az UpDate megnyomásával a beállítandó TCNT0
regiszter újraindulási értékét kapjuk meg. Mellette a ténylegesen elérhető időzítést (ez jelen esetben a feltételek mellett 100,2 Hz).
Timer1 használatával, 8-as előosztással elérhető a 100 Hz jel.
A hozzászólás módosítva: Máj 28, 2014
(#) yohnsee válasza AzIgaziCsaby hozzászólására (») Máj 28, 2014 /
 
Köszönöm, megpróbálom összehozni.
(#) kapu48 válasza kapu48 hozzászólására (») Máj 28, 2014 /
 
Bocsi!
Rossz az előző link!

Ez lesz: AvrCalc

Amiről a leírás szól.
(#) szaboa1 hozzászólása Máj 28, 2014 /
 
Sziasztok! Lenne egy kérdésem, napok óta bajlódom vele. (Megjegyzném, hogy eléggé kezdő vagyok még ezen a téren)

Van egy HC 06 -os bluetooth modulom, azt akarom, hogy tudjak kommunikálni egy atmega8 kontrollerrel PC-ről, uarton keresztül. Azt szeretném, hogy azt a karaktert amit PC-ről elküldök (putty), azt küldje vissza a kontroller. Ez nem működik..tehát nem ugyanazokat kapom vissza, azonban ha a kontrolleről direkt küldöm a karaktereket akkor azt jól megkapom. A beállítások egyeznek. (9600 baudrate, no parity, 1 stop bit, no flow control). Próbáltam külső kristály oszcsillátorral is de ugyanaz a helyzet. A BT modult kipróbáltam egy arduinoval is, azzal működött..(ugyanazt kaptam vissza amit küldtem)

Esetleg tudnátok segíteni?
Előre is köszönöm.
A hozzászólás módosítva: Máj 28, 2014
(#) Zsolt2 válasza szaboa1 hozzászólására (») Máj 28, 2014 /
 
A fogadast hogy ellenorzod megszakitassal vagy pollingal? Mekkora orajelet hasznalsz? Estleg csatold a kodot is.
(#) TavIR-AVR válasza szaboa1 hozzászólására (») Máj 28, 2014 /
 
Programkód? HW rajz?
- hibás bekötés,
- nembufferelt soros vétel,
- hibás kommunikáció megadása
- ...
(#) Droot hozzászólása Máj 28, 2014 /
 
Sziasztok!

Adott egy string-em, ami a következőt tartalmazza:
+CSPN: "Telenor HU",0

Szeretném a két idzőjel közti karaktersorozat első 9 karakterét egy string be másolni.
Hogyan lehet megcsinálni?
(#) szaboa1 válasza Zsolt2 hozzászólására (») Máj 28, 2014 /
 
Nem használok megszakításokat, mert egyelőre csak leakarom tesztelni, hogy müködik - e.
8MHZ - es órajelet használok, próbáltam belső oszcillátort és külső kristály oszcillátort is.

  1. #include <avr/io.h>
  2. #include <inttypes.h>
  3.  
  4. #define F_CPU 8000000UL
  5.  
  6. void USARTInit(uint16_t ubrr_value)
  7. {
  8.  
  9.     //Set Baud rate
  10.   UBRRL = ubrr_value;
  11.   UBRRH = (ubrr_value>>8);
  12.  
  13.    /*Set Frame Format
  14.  
  15.  
  16.    >> Asynchronous mode
  17.    >> No Parity
  18.    >> 1 StopBit
  19.    >> char size 8
  20.  
  21.    */
  22.  
  23.    UCSRC=(1<<URSEL)|(3<<UCSZ0);
  24.  
  25.  
  26.    //Enable The receiver and transmitter
  27.    UCSRB=(1<<RXEN)|(1<<TXEN);
  28.  
  29.  
  30. }
  31.  
  32. void USARTWriteChar(char data)
  33. {
  34.     //Wait until the transmitter is ready
  35.  
  36.     while(!(UCSRA & (1<<UDRE)))
  37.     {
  38.         //Do nothing
  39.     }
  40.  
  41.     //Now write the data to USART buffer
  42.  
  43.     UDR=data;
  44. }
  45.  
  46.  
  47.  
  48. char USARTReadChar()
  49. {
  50.     //Wait untill a data is available
  51.  
  52.     while(!(UCSRA & (1<<RXC)))
  53.     {
  54.         //Do nothing
  55.     }
  56.  
  57.     //Now USART has got data from host
  58.     //and is available is buffer
  59.  
  60.     return UDR;
  61. }
  62.  
  63. int main()
  64. {
  65.  
  66.    char data;
  67.    USARTInit(51);    //UBRR = 51
  68.  
  69.    //Loop forever
  70.  
  71.    while(1)
  72.    {
  73.       //Read data
  74.       data=USARTReadChar();
  75.  
  76.       /* Now send the same data but but surround it in
  77.       square bracket. For example if user sent 'a' our
  78.       system will echo back '[a]'.
  79.  
  80.       */
  81.  
  82.       USARTWriteChar('[');
  83.       USARTWriteChar(data);
  84.       USARTWriteChar(']');
  85.  
  86.    }
  87.  
  88.    return 0;
  89. }
(#) szaboa1 hozzászólása Máj 28, 2014 /
 
Minden esetben megkapom a két zárójelet, de közöttük hibás karaktert kapok. Általában 'k'-ra [B] -t, 'j'-re [@]-t, 'h'-ra [@]-t, 'g'-re [F]-t. (ha ez segít valamit).
Az új kódban ellenőrzöm az errorokat is, minden karakter után frame errort kapok.
Következő: »»   605 / 838
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