Fórum témák
» Több friss téma |
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
Tudom, C-ben szeretek is programozni, de most assemblert követel meg a feladat.
Üdv!
ATMega8-on hogyan lehet kódvédelmet bekapcsolni? Én még szeretnék írni bele, csak a kiolvasást akarom letiltani. Ez ISP-n megoldható?
A Lock biteket kell bekapcsolni. Ezzel a visszaolvasást tudod letiltani. Ha ki szeretnéd kapcsolni a Lock biteket, akkor egy teljes törlést kell végrehajtanod (ezután már nincs mit kiolvasni...), ezután tudod írni újra a program memóriát, majd újra beállítod (0-t kell beírni, hogy be legyen állítva) a lock biteket, és kész.
Nem Mega16,de az Avr242 app. note segíthet,ha járatos vagy az asm-ben.
Tartok tőle hogy ezt senki nem fogja megírni neked.
Ott kellene elindulni hogy a kijelzőt multiplexálod, amihez egy időzítő megszakítást használsz. Az időzítőt úgy állítsd be hogy 1-5 ms - enként megszakítást generál. A megszakításrutinban egyrészt kezeled a multiplexálást, utána növeled az óra számlálóját és feltételes láncban (pl. "ha eléri a 60-at a másodperc akkor...") végigmész a kijelzendő értékek számlálóin is. Igazából a "főprogram" nem fog semmit sem csinálni, mindent a megszakításrutin kezel le. Esetleg nyomógomb kezelést beletehetsz amivel az óra beállítható.
Én inkább kihasználnám, hogy ez a uC is támogatja az asszinkron módot az egyik időzítőnél (timer 2) egy külső kristállyal. Ha a programhoz a belső oszcillátort használja és ráköt egy külső 32.768kHz-es kristályt akkor egy jól kezelhető és pontos órát kap. Annyi dolga van csak, hogy asszinkron módra kapcsolja a T2-t, majd úgy állítja be a regisztereket, hogy minden másodpercben hívja meg a megszakítást (esetleg fél másodpercenként vagy hasonló módon, hogy a pontokat is villogtathassa a hétszegmenses kijelzőn). A program többi részén így már időzítenie sem kell, alárendelhet minden mást az idő beállításának (gombok, PCINT megszakítással) és kijelzőn megjelenítésének.
Továbbfejlesztési lehetősége, ha betesz egy plusz 3V-os gombelemet és figyeli, hogy leesik-e a betáp fesz. Ha igen, akkor leáll a kijelző meghajtással és energiatakarékos módra kapcsol, ahol csak a külső kristály meghajtása a fontos (meg az idő követése).
Lásd, milyen jó vagyok hozzád!
Elvezetlek a megoldáshoz! Bővebben: Link Alul jobbra: avr-source Digital clock with ATmega16 and 7-segment displays Bővebben: Link ![]()
Az assembler az a fordito program maga, ami az assembly nyelven irt forrast forditja. Szoval nem assembrelben, hanem assembly-ben lehet programot irni.
Ennek az a szépséghibája hogy fél-egymásodperces megszakítással a kijelzőt nem fogja multiplexálni. Mindenképp kell egy gyorsabb időzítő megszakítása is, de ez akár a T2 is lehet aszinkron módban kisebb előosztóval.
Nem feledkeztem meg róla. Egyszerűen mivel csak ennyi a program a kijelző frissithető úgy, ahogy csak a csövön kifér, nincs szükség külön időzítőre.
Az I2C az sosem egyszerű, pláne kezdő szinten.
Nekem is napjaim mentek ez azzal, hogy megpróbáljam kitalálni, hogy mi a fene baj van. Azóta vettem 2000 pénzért az Ebay-en logikai jelanalizátort és a fejlesztési idő drámaian lecsökkent. Az 1-2-3 hónap idő kezdőként reális. Ennél gyorsabb, ha veszel egy Arduino-t és a kész könyvtárakat használod hozzá. A hálózati kommunikáció mindig macerás, pláne ha eszközeid sincsenek hozzá. A hozzászólás módosítva: Máj 4, 2015
Idézet: „Az I2C az sosem egyszerű” Ezzel vitatkoznék. Kezdőként, aláírom hogy az I2C bonyolult. Hiába tanultam meg pár éve bitről bitre, újra elő kellett vennem a cuccost hogy mi és miért meg hogyan. Most sem tudnám fejből elmondani, mikor lehet STOP feltételt kiadni az UC-vel és mikor nem, meg hogyan lehet elkerülni a végtelen ciklust ha épp nem válaszol a cucc, de kis gyakorlattal a hátam mögött már nem kell analizátor(eredetileg sem volt), meg többnapos kutakodás hogy meg tudjak szólaltatni egy IC-t. Meg ha kéznél van egy épkézláb I2C könyvtár(saját gyártmány!!!) akkor azt a 20 perces guglizást és doksiolvasást is meg tudom spórolni. A szoftver I2C csak annyival nehezebb hogy az órajelet és a mintavételezést neked kell megoldani, a START/STOP feltételt pedig "jókor" kiadni. Slave esetén talán egyszerűbb, csak figyelni kell a START feltételt, az első 7 biten azonosítani a saját cimet, ha van akkor ACK-ot kiadni, majd az órajel alapján adni/venni, (master felőli) olvasáskor nemutolsó bájtnál ACK-ot, utolsó bájtnál NACK-ot adni, (master felőli) íráskor meg minden bájtnál ACK-al válaszolni és figyelni a STOP feltételt... A hozzászólás módosítva: Máj 4, 2015
Sziasztok! Valaki átnézné a következő kódom?
Tehát adott az Atmega 8 mikrovezérlő és két PWM kimenet OC1A és OC1B. Az ADC olvassa be a két poti állását, eszerint csinálja a PWM kitöltési tényezőjét. INT0-n van egy kapcsoló, ami megszakítja a programot, és az egyik PWM kitöltési tényezőjét 100%-ra állítsa, mikor újra megnyomódik, akkor a neki megfelelő poti alapján készíti a kitöltési tényezőt. A PWM frekvenciák körülbelül 500Hz-en kellene működjenek.
A hozzászólás módosítva: Máj 4, 2015
Az else után szerintem pressed=0; kellene. Prellezést is kéne kezelned (kapcsoláskor könnyen ide oda csapkodhat majd a mód). PWM rész ránézésre jónak tűnik (nagyon látszik a copy-paste azonban, (1<<WGM10) az ugyanaz, mint _BV(WGM10) ).
500Hz-es PWM-ben biztos vagy? Cincogni fognak a motorok.
Nagyon hulla vagyok most este már ahhoz hogy belenézzek a kódba még ha nem is hosszú
![]()
Ha már van tapasztalat, akkor oké, nem olyan bonyolult.
Nekem sikerült egy felhúzó ellenállást a CLK mögül rossz helyre kötni (föld) és minden megakadt. Egy óra elment vele, míg rájöttem, hogy miért vár mindenki. A jelanalizátorral látod, hogy az adó mit ad ki és a vevő mit fogad. Ez roppant nagy előny, mert tudod, hogy egy bonyolult folyamatban ki a hibás. Arról nem is beszélve, hogy ha a vevő 1 MHz-en megy, az adó meg 16 MHz-en, azért érhetnek meglepetések. AVR alatt egyébként azért TWI-nek hívják a protokolt, mert nem tartják az I2C szabványt. A legrondább ugye a STOP kezelése slave módban (0xA0): - master küld egy STOP jelet - a slave STOP után már nem tudja tartani a vonalat, mert nincs busy wait (CLK-val) - közben a master új kérést küld a slave-nek - a slave az előző STOP-ot még nem dolgozta fel, ezért az új kérésre automatikus NACK-ot küld - a slave végre feldolgozza a 0xA0 státuszt, engedélyezi újra magát a buszon - a master új kérését már kész fogadni Amikor olyan implementációt látsz AVR alatt, hogy az első NACK után még kétszer újra megkérdezi a slave-et, az ezért van. Vagy amikor az interrupt első 10 órajelében lekezelik az 0xA0-t, az is ugyanilyen okból történik. Gondolom az I2C minősítést nem kapták volna meg ezzel a megoldással. A hozzászólás módosítva: Máj 4, 2015
Mi úgy tanultuk, szabadalmi oka van annak hogy TWI-nek hívják, mert az "I2C" a Philips szabadalma.
A másik ok hogy TWI-n másfajta kommunikáció is megvalósítható, a harmadik amit mondasz az az hogy az AVR master módban egyáltalán nem érzékeli ha a slave lehúzva tartja az SCK vonalat.
Köszönöm szépen a segítséget, kijavítottam a hibákat:
Az MCU órajelét módosítanom kell 6528000Hz-re, a prescallert meg 256-ra, mivel 50Hz-es marad a PWM, és a kitöltési tényező max 127 lehet, ezért az ADC értékeket mielőtt OCR megkapja 2-vel osztom. Csak most nemtudom biztosan, hogy ehez az "ULKA szivattyuhoz" milyen frekijű PWM kell. A hozzászólás módosítva: Máj 4, 2015
Maradok a B tervnél, és kb 290Hz-es PWM-t csinálok, mert ha csak 50 Hz-est csinálok akkor a pompa vagy elkapja a pozitív részét a szinusznak, vagy nem és akkor egyáltalán nem megy.
Szia!
A pressed még mindig nem jó. A volatile nem helyettesíti a típust, mivel az egy módosító kulcsszó, ami lényegében annyit csinálsz, hogy jelzi a fordítónak, hogy a vele kapcsolatos dolgokat ne optimalizálja ki. Ez olyan hibákat okozhat, a te kódodban például (nem tudom mennyire okos ez a gcc), hogy főciklusod előtt a pressed értékét alaphelyzetbe állítottad nulla és utána sehol se kap új értéket a fordítód szerint (mert ő azt honnan tudja szegénykém, hogy te interruptban változtatod az értékét?), tehát a továbbiakban a pressed-et abban a környezetben úgy tekinti mint ha egy konstans 0 lenne. Ezért kiszedi az elágazást is, mert annak nincs értelme, hogy folyton megnézd, hogy a "0==0 ?" + ennek a feltételnek sose lesz else ága .
Ezért kell a változód volatile ként deklarálni, és akkor nem fogja piszkálni az optimalizációs része a fordítódnak.
Szerk: + ha az interruptban mindenképpen 1 re állítod a változót, akkor miért van elágazás? ![]() A hozzászólás módosítva: Máj 5, 2015
Idézet: Bizony nem, bár default-bol int lesz, ahogy a fuggvenyeknel, és szól is érte a gcc, hogy "type defaults to int". Persze, aki -Wall -Werror opciókkal fordít, annak ez rögtön ki is derül. „A volatile nem helyettesíti a típust,”
Igen a fordítóm kiirta, warningnak, hogy
Idézet: . Szóval azt akartam volna interrupt-al elérni, hogy a főciklusban állandóan adc szerint csinálja a PWM kitöltési tényezőjét, de ha megnyomom az interruptot, akkor a következő interrupt lenyomásáig 50% os kitöltési tényezővel menjen. Akkor a főciklus előtt ne nullázzam le a pressed értékét? „type defaults to int”
Csak gépelési hibának tűnik... leírt működés szerint OCR1A=127; lesz az.
Igen, mert OCR1A nem ORR sajnos elírtam.
Valaki átnézné ezt is? Atmega8 relé késleltetés, PD2-n GND-re bekapcsol az a funkció, hogyha PD5-on megvaltozik a kapcsolo allapota akkor delayal be és kikapcsol egy relét. Itt nem használhatnák NOT, vagyis ! jelet az első if-nél?
A hozzászólás módosítva: Máj 5, 2015
Üdv!
ATMega8-on WatchDog-ot használt már valaki? Adatlapját néztem, a beállításhoz kellő regiszterek meg is vannak, de nem tudom, hogy melyik bitet kéne mindig törölni/beállítani, hogy a házőrző újrakezdje a számolást. Melyik az a bit? A hozzászólás módosítva: Máj 5, 2015
Szia!
Elég trükkös, mert adatlapban nem tudom, hogy hol írják. A watchdog újraindítására egy külön asm parancs van: WDR. Esetleg az adatlapban található példakódból lehetett rájönni, ha jól emlékszem. 1., __asm__ __volatile__ ("wdr"); 2., #include <avr/wdt.h> és használód a wdt_reset()-et // ugyanazt csinálja mint a fenti kód
Igazából mester-szolga módban az TWI remekül megy.
Egyszer próbáltam multimesteres módot kialakítani Atmel IC-vel, de befürdés lett a vége. Azt kell, hogy mondjam, hogy a multimesteres mód AVR alatt csak papíron létezik. Annyi hardver hibába futottam bele, hogy letettem az egészről. |
Bejelentkezés
Hirdetés |