Kako napisati kodo za AVR, programirati mikrokontrolerje Atmel AVR v C. AVR programiranje

Shematski diagram programatorja vrat LPT je prikazan na sliki. Kot gonilnik vodila uporabite mikrovezje 74AC 244 ali 74HC244 (K1564AP5), 74LS244 (K555AP5) ali 74ALS244 (K1533AP5).

LED VD1 označuje način snemanja mikrokrmilnika,

LED VD2 - branje,

LED VD3 - prisotnost napajanja v vezju.

Vezje prevzame potrebno napetost za napajanje iz priključka ISP, tj. iz programabilne naprave. To vezje je preoblikovano programatorsko vezje STK200/300 (dodane LED diode za lažje upravljanje), zato je združljivo z vsemi programskimi programi za osebne računalnike, ki delujejo z vezjem STK200/300. Za delo s tem programatorjem uporabite program CVAVR

Programator lahko izdelamo na tiskanem vezju in ga namestimo v ohišje LPT konektorja, kot je prikazano na slikah:




Za delo s programatorjem je priročno uporabiti razširitev vrat LPT, ki jo je enostavno izdelati sami (na primer iz kabla Centronix za tiskalnik), glavna stvar je, da ne prizanesete vodnikov za tla (18- 25 priključnih nog) ali kupite. Kabel med programatorjem in programabilnim čipom ne sme presegati 20-30 cm.

Več kot enkrat ali dvakrat sem rekel, da je treba študij MK začeti z asemblerjem. Temu je bil namenjen cel tečaj na spletni strani (čeprav ni zelo dosleden, a ga postopoma počešem do ustreznega videza). Da, težko je, rezultat ne bo prvi dan, vendar se boste naučili razumeti, kaj se dogaja v vašem krmilniku. Vedeli boste, kako deluje, in ne boste kot opica kopirali virov drugih ljudi in poskušali razumeti, zakaj je nenadoma prenehal delovati. Poleg tega je za C veliko lažje ustvariti redneck kodo, ki bo prišla ven z vilami v najbolj neprimernem trenutku.

Na žalost si vsi želijo rezultate takoj. Zato sem se odločil, da grem v drugo smer - naredim vadnico o C-ju, vendar s prikazovanjem njegovega spodnjega perila. Dober programer za vdelavo vedno drži svoj kos strojne opreme tesno za vijak in ji ne dovoli, da bi brez dovoljenja naredil en korak. Torej najprej bo koda C, nato kaj je proizvedel prevajalnik in kako vse skupaj dejansko deluje :)

Po drugi strani pa je močna točka C-ja prenosljivost kode. Če seveda vse pravilno napišete. Ločevanje delovnih algoritmov in njihove strojne izvedbe v različne dele projekta. Nato bo za prenos algoritma na drug mikrokrmilnik dovolj, da prepišemo le vmesniški sloj, kjer so zapisani vsi klici strojne opreme, in pustimo vso delujočo kodo takšno, kot je. In seveda berljivost. Izvorna koda C je na prvi pogled lažje razumljiva (čeprav ... na primer, meni je vseeno, na kaj naj pokažem - ali C ali ASM :)), ampak, spet, če je vse pravilno napisano. Pozoren bom tudi na te točke.

Moja plošča za odpravljanje napak bo služila kot poskusna strojna oprema, na kateri bo nameščen levji delež vseh primerov.

Prvi C program za AVR

Izbira prevajalnika in nastavitev okolja
Obstaja veliko različnih prevajalnikov C za AVR:
Najprej to IAR AVR C- je skoraj zagotovo priznan kot najboljši prevajalnik za AVR, ker Sam krmilnik je nastal v tesnem sodelovanju med Atmelom in strokovnjaki iz IAR. Ampak za vse moraš plačati. In ta prevajalnik ni samo draga komercialna programska oprema, ampak ima tudi tako tono nastavitev, da se je treba kar precej potruditi, da jo preprosto prevedeš v njem. Z njim se res nisem spoprijateljil; projekt je propadal zaradi nenavadnih napak v fazi povezovanja (kasneje sem ugotovil, da je šlo za ukrivljen crack).

Drugi pride WinAVR GCC- močan optimizacijski prevajalnik. Popolnoma odprta koda, več platform, na splošno vse radosti življenja. Prav tako se popolnoma integrira v AVR Studio, kar vam omogoča odpravljanje napak kar tam, kar je prekleto priročno. Na splošno sem ga izbral.

Je tudi CodeVision AVR C je zelo priljubljen prevajalnik. Postala je priljubljena zaradi svoje preprostosti. V njem lahko dobite delujoč program v samo nekaj minutah - čarovnik za zagonsko kodo to močno olajša, tako da izniči standarde za inicializacijo vseh vrst stvari. Če sem iskren, sem nekako sumljiv glede tega - ko sem moral razstaviti program, ki ga je napisal ta prevajalnik, se je izkazalo, da gre za nekakšno zmešnjavo in ne za kodo. Ogromna količina nepotrebnih premikov in operacij, kar je povzročilo precejšnjo količino kode in počasno delovanje. Vendar pa je morda prišlo do napake v DNK osebe, ki je napisala originalno programsko opremo. Poleg tega hoče denar. Ne toliko kot IAR, vendar opazno. In v demo načinu vam omogoča pisanje največ 2kb kode.
Seveda obstaja crack, ampak če boš kradel, je milijon, v IAR smislu :)

Je tudi Slika Craft AVR C in MicroC iz mikroelektronike. Ni mi bilo treba uporabiti ne enega ne drugega, ampak... S.W.G. zelo pohvalno MicroPascal, pravijo, strašno priročno programsko okolje in knjižnice. Mislim, da MicroC ne bo nič slabši, vendar je tudi plačan.

Kot sem rekel, sem izbral WinAVR iz treh razlogov: je brezplačen, integrira se v AVR Studio in zanj je napisana le tona že pripravljene kode za vse priložnosti.

Torej prenesite namestitev WinAVR z AVR Studio. Nato je najprej nameščen studio, nato pa je WinAVR nameščen na vrhu in pritrjen na studio v obliki vtičnika. Močno priporočam namestitev WinAVR na kratko pot, nekaj takega kot C:\WinAVR, tako se boste izognili številnim težavam s potmi.

Ustvarjanje projekta
Torej, studio je nameščen, C je privit, čas je, da poskusimo nekaj programirati. Začnimo s preprostim, najbolj preprostim. Zaženite studio, tam izberite nov projekt kot prevajalnik AVR GCC in vnesite ime projekta.

Odpre se delovno polje s prazno datoteko *.c.

Zdaj ne bo škodilo, če konfigurirate prikaz poti v zaznamkih studia. Če želite to narediti, pojdite na:
Meni Orodja - Možnosti - Splošno - Zavihki datotek in na spustnem seznamu izberite "Samo ime datoteke". V nasprotnem primeru bo nemogoče delovati - zavihek bo vseboval celotno pot datoteke in na zaslonu ne bo več kot dveh ali treh zavihkov.

Nastavitev projekta
Na splošno velja, da je klasična izdelava make datoteke, v kateri so opisane vse odvisnosti. In verjetno je tako. Toda zame, ki sem odraščal na popolnoma integriranih IDE-jih, kot je uVision oz AVR Studio ta pristop je globoko tuj. Zato bom naredil po svoje, vse s pomočjo studia.

Pritisnite gumb z orodjem.


To so nastavitve za vaš projekt oziroma nastavitve za samodejno generiranje make datoteke. Na prvi strani morate samo vnesti frekvenco, na kateri bo deloval vaš MK. To je odvisno od bitov varovalke, zato predpostavljamo, da je naša frekvenca 8000000Hz.
Bodite pozorni tudi na optimizacijsko vrstico. Zdaj je tu -Os - to je optimizacija velikosti. Zaenkrat pustite tako, kot je, nato pa se lahko poskusite igrati s tem parametrom. -O0 sploh ni optimizacija.

Naslednji korak je konfiguracija poti. Najprej dodajte svoj projektni imenik tja - tja boste dodali knjižnice tretjih oseb. Na seznamu bo prikazana pot ».\«.

Datoteka Make je bila ustvarjena, lahko si jo ogledate v privzeti mapi v vašem projektu, samo poglejte z očmi in poglejte, kaj je tam.


To je vse za zdaj. Povsod kliknite V redu in pojdite na vir.

Oblikovanje problema
Prazen list papirja je vabljiv za izvedbo kakšne zvite ideje, saj banalno utripanje diode ne deluje več. Takoj primemo bika za roge in vzpostavimo povezavo z računalnikom – to je prva stvar, ki jo naredim.

Delovalo bo takole:
Ko na COM vrata prispe ena (koda 0x31), dioda zasveti, ko pride ničla (koda 0x30) pa ugasne. Poleg tega bo vse narejeno na prekinitvah, naloga v ozadju pa bo utripanje druge diode. Enostavno in smiselno.

Sestavljanje vezja
Pretvorniški modul USB-USART moramo povezati z zatiči USART mikrokontrolerja. Če želite to narediti, vzemite mostiček iz dveh žic in ga navzkrižno položite na zatiče. To pomeni, da priključimo Rx krmilnika na Tx pretvornika in Tx pretvornika na Rx krmilnika.

Na koncu je to diagram:


Ne razmišljam o povezovanju preostalih pinov, napajanja, ponastavitve, to je standardno

Pisanje kode

Naj takoj rezerviram, da se ne bom posebej poglabljal v opis samega jezika C. Za to obstaja preprosto ogromna količina materiala, začenši s klasičnim "programskim jezikom C" iz K&R in konča z različnimi priročniki.

Eno takšno metodo sem našel v svoji zalogi; nekoč sem jo uporabil za študij tega jezika. Vse je kratko, jasno in jedrnato. Postopoma ga sestavljam in vlečem na svojo spletno stran.

Res je, da vsa poglavja še niso prenesena, a mislim, da ne bo dolgo.

Malo verjetno je, da ga bom lahko bolje opisal, zato bom iz tečaja usposabljanja namesto podrobne razlage tankosti preprosto zagotovil neposredne povezave do posameznih strani tega priročnika.

Dodajanje knjižnic.
Najprej dodamo potrebne knjižnice in glave z definicijami. Konec koncev je C univerzalen jezik in mu moramo razložiti, da delamo posebej z AVR, zato napišite vrstico v izvorno kodo:

1 #vključi

#vključi

Ta datoteka se nahaja v mapi WinAVR in vsebuje opis vseh registrov in vrat krmilnika. Poleg tega je vse tam zvito, z vezavo na določen krmilnik, ki ga prevajalnik prenaša prek narediti datoteka v parametru MCU in na podlagi te spremenljivke je z vašim projektom povezana datoteka glave z opisom naslovov vseh vrat in registrov za ta določen krmilnik. Vau! Brez tega je tudi mogoče, vendar potem ne boste mogli uporabljati simboličnih imen registrov, kot sta SREG ali UDR, in si boste morali zapomniti naslov vsakega, kot je "0xC1", kar bo povzročilo glavobol.

Sama ekipa #vključi<имя файла> vam omogoča, da svojemu projektu dodate vsebino katere koli besedilne datoteke, na primer datoteko z opisom funkcij ali del druge kode. In da bi lahko direktiva našla to datoteko, smo določili pot do našega projekta (imenik WinAVR je tam že privzeto registriran).

Glavna funkcija.
Program C je v celoti sestavljen iz funkcij. Lahko jih ugnezdimo in kličemo drug od drugega v poljubnem vrstnem redu in na različne načine. Vsaka funkcija ima tri zahtevane parametre:

  • Povratna vrednost je npr. greh(x) vrne vrednost sinusa x. Kot pri matematiki, skratka.
  • Preneseni parametri so enaki X.
  • Funkcijsko telo.

Vse prenesene in vrnjene vrednosti morajo biti določene vrste, odvisno od podatkov.

Vsak program C mora vsebovati funkcijo glavni kot vstopna točka v glavni program, sicer sploh ni C :). Po prisotnosti glavnega v izvorni kodi nekoga drugega iz milijona datotek lahko razumete, da je to glavni del programa, kjer se vse začne. Torej vprašajmo:

1 2 3 4 5 int main(void) ( return 0 ; )

int main(void) ( vrni 0; )

To je to, prvi najpreprostejši program je napisan, ni važno, da nič ne naredi, šele začeli smo.

Ugotovimo, kaj smo naredili.
int To je podatkovni tip, ki ga vrne glavna funkcija.

Seveda v mikrokontrolerju glavni načeloma ni mogoče vrniti ničesar in v teoriji bi moralo biti praznina glavni (praznina), vendar je GCC prvotno zasnovan za osebni računalnik in tam lahko program po zaključku vrne vrednost operacijskemu sistemu. Zato GCC naprej praznina glavni (praznina) prisega na Opozorilo.

To ni napaka, delovalo bo, vendar ne maram opozoril.

praznina to je vrsta podatkov, ki jih v tem primeru posredujemo funkciji glavni tudi ne more sprejeti ničesar od zunaj, torej praznina- lutka. Škrbina se uporablja, ko ni treba ničesar pošiljati ali vračati.

Tukaj so { } zavit oklepaj je programski blok, v tem primeru telo funkcije glavni, se bo koda nahajala tam.

vrnitev- to je vrnjena vrednost, ki jo bo glavna funkcija vrnila po zaključku, ker imamo int, torej število, potem moramo vrniti število. Čeprav to še vedno nima smisla, ker... na mikrokrmilniku ne moremo iti nikamor od glavnega. Vrnem nič. Ker je vseeno. Toda prevajalnik je običajno pameten in za ta primer ne ustvari kode.
Čeprav, če je sprevržen, potem iz glavni Lahko greste na MK - na primer, padete v razdelek zagonskega nalagalnika in ga izvedete, vendar bo to zahtevalo nizko raven poigravanja z vdelano programsko opremo, da bi popravili prehodne naslove. Spodaj se boste sami prepričali in razumeli, kako to storiti. Za kaj? To je drugo vprašanje, v 99,999% primerov to ni potrebno :)

Uspelo nam je in šli naprej. Dodajmo spremenljivko, res je ne potrebujemo in brez nje nima smisla uvajati spremenljivk, se pa učimo. Če so spremenljivke dodane znotraj telesa funkcije, potem so lokalne in obstajajo samo v tej funkciji. Ko zapustite funkcijo, se te spremenljivke izbrišejo, pomnilnik RAM pa se dodeli za pomembnejše potrebe. .

1 2 3 4 5 6 int main(void) (unsigned char i; return 0;)

int main(void) (unsigned char i; return 0; )

nepodpisan pomeni nepodpisano. Dejstvo je, da je v binarni predstavitvi najpomembnejši bit dodeljen znaku, kar pomeni, da se število +127/-128 prilega enemu bajtu (char), če pa znak zavržemo, se prilega od 0 do 255. Običajno znak ni potreben. torej nepodpisan.
jaz je samo ime spremenljivke. Nič več.

Zdaj moramo inicializirati vrata in UART. Seveda lahko vzamete in povežete knjižnico ter pokličete nekakšen UartInit(9600); potem pa ne boste vedeli, kaj se je v resnici zgodilo.

Naredimo to:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main(void) (unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider) ; UBRRH = HI(bauddivider) ; UCSRA = 0; UCSRB = 1<< RXEN| 1 << TXEN| 1 << RXCIE| 0 << TXCIE; UCSRC = 1 << URSEL| 1 << UCSZ0| 1 << UCSZ1; }

int main(void) (unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO(bauddivider); UBRRH = HI(bauddivider);<

Strašljivo? Pravzaprav obstaja le pet zadnjih vrstic prave kode. Vse, to #definiraj je predprocesorski makro jezik. Skoraj enake stvari kot v Assembly, vendar je sintaksa nekoliko drugačna.

Olajšali vam bodo rutinske operacije izračunavanja potrebnih koeficientov. V prvi vrstici rečemo, da namesto tega XTAL lahko varno zamenjate 8000000, in L- navedba tipa, pri čemer je long urna frekvenca procesorja. Enako baudrate— frekvenca prenosa podatkov prek UART.

bauddividerže bolj zapleteno, namesto njega bo zamenjan izraz, izračunan po formuli iz prejšnjih dveh.
No in L.O. in HI Nizki in visoki bajti bodo vzeti iz tega rezultata, ker Očitno se morda ne prilega enemu bajtu. IN HI X (vhodni parameter makra) se premakne osemkrat v desno, zaradi česar ostane samo najpomembnejši bajt. In v L.O. naredimo bitni IN s številko 00FF, posledično bo ostal samo spodnji bajt.

Torej je vse, kar je narejeno, podobno #definiraj lahko varno zavržete, potrebne številke pa izračunate na kalkulatorju in jih takoj vnesete v vrstice UBBRL = …. in UBBRH = …..

Lahko. Ampak! To storite POPOLNOMA NEMOGOČE!

Delovalo bo tako ali tako, vendar boste imeli t.i magične številke- vrednote, vzete neznano od kod in nejasno zakaj, in če čez nekaj let odprete tak projekt, bo prekleto težko razumeti, kaj so te vrednosti. Tudi zdaj, če hočeš spremeniti hitrost, ali spremeniti frekvenco kvarca, bo treba vse znova izračunati, ampak si spremenil par številk v kodi in to je to. Na splošno, če ne želite, da vas označijo za kodirnika, naredite kodo tako, da bo lahko berljiva, razumljiva in enostavna za spreminjanje.

Potem je vse preprosto:
Vsi ti “UBRRL in Co” so konfiguracijski registri UART oddajnika, s pomočjo katerega bomo komunicirali s svetom. In zdaj smo jim dodelili zahtevane vrednosti, jih nastavili na želeno hitrost in način.

Vrsta snemanja 1< Pomeni naslednje: vzemite 1 in ga postavite na mesto RXEN v bajtu. RXEN to je 4. bit registra UCSRB, Torej 1< tvori binarno število 00010000, TXEN- to je 3. bit in 1< bo dal 00001000. En sam "|" bitno je ALI, torej 00010000 | 00001000 = 00011000. Na enak način se nastavijo preostali potrebni konfiguracijski biti in dodajo splošni kopici. Posledično se zbrana številka zabeleži v UCSRB. Več podrobnosti je opisanih v podatkovnem listu na MK v razdelku USART. Naj nas torej ne zamotijo ​​tehnične podrobnosti.

Končano, čas je, da vidimo, kaj se je zgodilo. Kliknite prevedi in zaženite emulacijo (Ctrl+F7).

Odpravljanje napak
Vrstile so se najrazličnejše vrstice napredka, studio se je spremenil in blizu vhoda v glavno funkcijo se je pojavila rumena puščica. Tukaj se trenutno izvaja procesor in simulacija je začasno ustavljena.

Dejstvo je, da je bilo na začetku pravzaprav na liniji UBRRL = LO(bauddivider); Navsezadnje to, kar imamo v definiciji, ni koda, ampak le predhodni izračuni, zato je simulator nekoliko dolgočasen. Zdaj pa je spoznal, da je prvo navodilo opravljeno in če splezaš na drevo V/I pogled, v razdelek USART in tam poglejte bajt UBBRL, videli boste, da je vrednost že tam! 0x33.

Naredite še korak naprej. Oglejte si, kako se spreminja vsebina drugega registra. Torej pojdite skozi vse, bodite pozorni na dejstvo, da so vsi označeni biti nastavljeni, kot sem vam povedal, in so nastavljeni hkrati za celoten bajt. Dlje od Vrnitve ne bo šlo - programa je konec.

Otvoritev
Zdaj ponastavite simulacijo na nič. Kliknite tam Ponastavi (Shift+F5). Odprite razstavljen seznam, zdaj boste videli, kaj se dejansko dogaja v krmilniku. Pogled -> Disassembler. In ne YYYAAA!!! Sestavljalec!!! GROZA!!! IN JE NUJNO. Da kasneje, ko gre kaj narobe, ne boš neumen v kodi in ne postavljaš neumnih vprašanj na forumih, ampak se takoj poglobiš v drobovje in vidiš, kje si se zataknil. Tam ni nič strašnega.

Najprej bodo vrhovi iz serije:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +00000000: 940C002A JMP 0x0000002A Skok +00000002: 940C0034 JMP 0x00000034 Skok +00000004: 940C0034 JMP 0x00000034 Skok +00000006: 940C0034 JMP 0x00000034 Skok +00000008: 940C0034 JMP 0x00000034 Skok +0000000A: 940C0034 JMP 0x00000034 Skok +0000000C: 940C0034 JMP 0x00000034 Skok + 0000000E: 940C0034 JMP 0x000034 Skok +0000010: 940c0034 JMP 0x00000034 Skok +000012: 940c0034 JMP 0x00000034 Skok +00000014: 940c0034 JMP 0x0 0000034 Skok +00000016: 940C003 4 JMP 0x00000034 Skok +00000018: 940c0034 JMP 0x00000034 Skok +0000001a: 940c0034 JMP 0x00000034 Skok + 0000001c : 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00000022: 940C0034 J MP 0x00000 034 Skok +00000024: 940C0034 JMP 0x00000034 Skok +00000026: 940C0034 JMP 0x00000034 Skok +00000028: 940C0034 JMP 0x00000034 Skok

00000000: 940C002A JMP 0x00002A Skok +00000002: 940C0034 JMP 0x00000034 Skok +00000004: 940C0034 JMP 0x000034 SKOK +00000006: 940C0034 JMP 0x 000034 Jump +000008: 940C0034 JMP 0x00000034 Jump +0000000a: 940c0034 JMP 0x00000034 Jump +0000000C: 940c0034 JMP 0x00000034 Jump +0000000EE : 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00000014: 940C0034 JMP 0x00000 034 Skok +00000016: 940C0034 JMP 0x00000034 Skok +00000018: 940C0034 JMP 0x00000034 Skok +0000001A: 940C0034 JMP 0x00000034 Skok +0000001C : 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00000022: 940C0034 JMP 0x00000 03 4 Skok +00000024: 940C0034 JMP 0x00000034 Skok +00000026: 940C0034 JMP 0x00000034 Skok +00000028: 940C0034 JMP 0x00000034 Skok

To je tabela prekinitvenih vektorjev. K temu se bomo vrnili kasneje, za zdaj pa samo poglejte in se spomnite, da obstaja. Prvi stolpec je naslov bliskovne celice, v kateri se nahaja ukaz, drugi je koda ukaza, tretji je mnemonika ukaza, isto navodilo za sestavljanje, tretji so operandi ukaza. No, samodejni komentar.
Torej, če pogledate, obstajajo neprekinjeni prehodi. In koda ukaza JMP je štiribajtna, vsebuje naslov skoka, zapisan nazaj - nizki bajt na nizkem naslovu in kodo ukaza skoka 940C

0000002B: BE1F OUT 0x3F,R1 Out to I/O location

Snemanje te ničle na naslov 0x3F Če pogledate stolpec I/O view, boste videli, da je naslov 0x3F naslov registra SREG - registra zastavic krmilnika. Tisti. ponastavimo SREG za izvajanje programa pod ničelnimi pogoji.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Naloži takoj +0000002D: E0D4 LDI R29,0x04 Naloži takoj +0000002E: BFDE OUT 0x3E,R29 Out to I/O location +0000002F: BFCD OUT 0x3D,R28 Out to I/O location

0000002C: E5CF LDI R28,0x5F Naloži takoj +0000002D: E0D4 LDI R29,0x04 Naloži takoj +0000002E: BFDE OUT 0x3E,R29 Out to I/O location +0000002F: BFCD OUT 0x3D,R28 Out to I/O location

To je nalaganje kazalca sklada. Ne morete neposredno nalagati v V/I registre, samo prek vmesnega registra. Zato najprej LDI do vmesnega, nato pa od tam OUT do I/O. Kasneje vam bom povedal tudi več o skladu. Za zdaj vedite, da je to območje dinamičnega pomnilnika, ki visi na koncu RAM-a in shranjuje naslove in vmesne spremenljivke. Zdaj smo navedli, od kod se bo začel naš sklad.

00000032: 940C0041 JMP 0x00000041 Skok

Skoči na sam konec programa in tam imamo prepoved prekinitev in tesno zanko samega sebe:

1 2 +00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relativni skok

00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relativni skok

To je v primeru nepredvidenih okoliščin, kot je izstop iz glavne funkcije. Krmilnik je mogoče odstraniti iz takšne zanke s ponastavitvijo strojne opreme ali, bolj verjetno, s ponastavitvijo psa čuvaja. No, ali pa, kot sem rekel zgoraj, popravimo to v hex urejevalniku in oddirjamo, kamor nam srce poželi. Upoštevajte tudi, da obstajata dve vrsti prehodov: JMP in RJMP; prvi je neposredni prehod na naslov. Zavzema štiri bajte in lahko neposredno skače skozi celotno območje pomnilnika. Druga vrsta prehoda je RJMP - relativni. Njegov ukaz traja dva bajta, vendar se premakne s trenutnega položaja (naslova) 1024 korakov naprej ali nazaj. In njegovi parametri kažejo odmik od trenutne točke. Uporablja se pogosteje, ker pri izpiranju zavzame polovico prostora in redko so potrebni dolgi prehodi.

1 +00000034: 940C0000 JMP 0x00000000 Skok

00000034: 940C0000 JMP 0x00000000 Skok

In to je skok na sam začetek kode. Nekakšen ponovni zagon. Tukaj lahko preverite, ali vsi vektorji skačejo. Zaključek iz tega je, da če zdaj omogočite prekinitve (privzeto so onemogočene) in se vaša prekinitev pojavi, vendar ni upravljalnika, potem bo prišlo do ponastavitve programske opreme - program bo vrnjen nazaj na sam začetek.

Glavna funkcija. Vse je podobno, ni vam treba niti opisovati. Samo poglejte že izračunano število, ki se vpisuje v registre. Predprocesor prevajalnika je neverjeten!!! Torej brez "čarobnih" številk!

1 2 3 4 5 6 7 8 9 10 11 12 <

00000036: E383 LDI R24,0x33 Naloži takoj +00000037: B989 OUT 0x09,R24 Izhod na V/I lokacijo 15: UBRRH = HI(bauddivider); +00000038: BC10 OUT 0x20,R1 Izhod na V/I lokacijo 16: UCSRA = 0; +00000039: B81B OUT 0x0B,R1 Out to I/O location 17: UCSRB = 1<

In tukaj je napaka:

1 2 3 +0000003E: E080 LDI R24.0x00 Naloži takoj +0000003F: E090 LDI R25.0x00 Naloži takoj +00000040: 9508 RET Vrnitev podprograma

0000003E: E080 LDI R24.0x00 Naloži takoj +0000003F: E090 LDI R25.0x00 Naloži takoj +00000040: 9508 RET Vrnitev podprograma

Vprašanje je, zakaj prevajalnik dodaja takšne vrhove? In to ni nič drugega kot Return 0, funkcijo smo definirali kot int main(void) in tako smo zapravili še štiri bajte za nič :) In če naredite void main(void), bo ostal samo RET, vendar se bo pojavilo opozorilo , da naša glavna funkcija ne vrne ničesar. Na splošno naredite, kot želite :)

Težko? Očitno ne. Kliknite na izvajanje korak za korakom v načinu disassemblerja in si oglejte, kako procesor izvaja posamezna navodila, kaj se zgodi z registri. Kako poteka premikanje skozi ukaze in končno zanko?

Nadaljevanje čez par dni...

Offtop:
Aleksej78 Ustvaril sem vtičnik za Firefox, ki olajša krmarjenje po mojem spletnem mestu in forumu.
Razprava in prenos,

Nekako sem se takoj počutil prisiljenega svetovati glede izbire programskega okolja za krmilnike AVR. Samo ne meči vame copat. še malo sem :)

Obstaja veliko programskih jezikov za mikrokontrolerje. Tudi programskih okolij je kar nekaj in jih je nekorektno primerjati med seboj. Ni najboljših programskih jezikov. To pomeni, da boste morali izbrati jezik in programsko okolje, ki vam najbolj ustreza.

Če ste trenutno pred izbiro, kaj začeti delati, potem je tukaj nekaj priporočil za vas.

Prejšnje izkušnje s programiranjem. Ne zanemarite svojih prejšnjih programerskih izkušenj. Tudi če bi bil BASIC. Tudi če je bilo že dolgo nazaj v šoli. Programiranje je kot vožnja s kolesom – ko začneš, se hitro spomniš vsega, kar si pozabil. Začnite z OSNOVNIM - obvladajte ga - kasneje boste lažje izbrali nekaj primernejšega za vaše namene.

Pomoč iz okolja. Ali vaši prijatelji pišejo v Pascalu? Težava je za vas rešena - pišite v Pascalu! Vedno vam bodo pomagali z nasveti, vam dali knjižnice in vam dali pripravljene projekte za študij. Na splošno vas bodo z veseljem sprejeli v svojo skupnost. Če storite nasprotno, boste dobili nasprotni rezultat. Prijatelji industrije CIS vas bodo kljuvali, če se boste odločili za študij Assemblerja. Ne pričakujte pomoči.

Dobra knjiga o programiranju AVR bo zelo pomagalo. Žal jih je zelo malo. Če naletite na knjigo in se vam zdi, da je vse razloženo na zelo dostopen način, jo poskusite. Ne priporočam učenja iz e-knjig; v skrajnem primeru jih natisnite. Preklapljanje med okoljem in besedilom knjižne datoteke je zelo neprijetno. Veliko bolj prijetno je prebrati knjigo in jo preizkusiti takoj, ne da bi vas motilo preklapljanje; poleg tega si lahko na robovih naredite opombe in zapišete ideje, ki se porajajo.

Programsko okolje je preprostejše.Če je za vaš jezik na voljo več programskih okolij, ne odlašajte, izberite tistega, ki je preprostejše. Naj bo manj funkcionalen. Naj sestavi strašno napihnjeno kodo. Glavna stvar je, da začnete delati. Ko se počutite udobno v preprostem okolju, se lahko preprosto premaknete v naprednejše in »pravilno« okolje. In ne poslušajte tistih, ki pravijo, da boste izgubili več časa - motijo ​​se. Osnovnošolcem se ne nalaga, da berejo "Vojno in mir", dobijo enostavnejše knjige - s slikami.

Knjižnice. Razpoložljivost knjižnic je sporna za učenje jezikov. Seveda bodo pozneje zelo olajšale življenje, vendar so knjižnice »črnih skrinjic« sprva nerazumljive in ne prispevajo k razumevanju jezika. Po drugi strani olajšajo branje programov in začetniku omogočajo sestavljanje zapletenih programov brez večjega truda. Torej, ne obremenjujte se preveč z njihovo prisotnostjo. Vsaj na začetku.

Učinkovita koda. Izbira programskega okolja za učenje programiranja samo na podlagi tega, kako učinkovita je koda, ki jo prevaja, je slaba ideja. Glavno, da se počutiš prijetno, ko se začneš učiti – kaj bo iz tega nastalo, je deseta stvar. Seveda lahko na tem delate pozneje.

Čarovniki. Vsako napravo na čipu je treba konfigurirati z uporabo vrat. Postopek je precej dolgočasen in potrebni so podatkovni listi. Poleg tega obstajajo nianse, ki jih začetniku ni enostavno razumeti. Zato je zelo zaželeno imeti čarovnike v okolju. Vyzards so samodejni sprejemniki za SPI, I2C, USART itd. Več naprav kot je podprtih, bolje je. Vi nastavite potrebne periferne parametre, čarovnik pa sam ustvari kodo, ki bo podala podane parametre. Zelo olajša življenje.


Splošna priporočila takšno - programiranje v začetni fazi mora biti čim bolj preprosto (tudi primitivno). Programsko okolje mora biti enostavno za učenje (saj morate najprej obvladati programiranje in ne izgubljati časa z igranjem z nastavitvami). Po možnosti rusificiran. V pomoč bi bil tudi ruski priročnik in vzorčni programi. Zaželena je zmožnost utripanja kristala iz okolja. Potem, ko obvladate osnove programiranja, lahko preidete na bolj zapletene lupine.


Še zadnje priporočilo: delajte s pravim kristalom. Ne bojte se ga zažgati. Pridobite praktične izkušnje. Delo z emulatorji (npr. Proteus), čeprav vas bo osvobodilo ubadanja s spajkalnikom, vam nikoli ne bo moglo prinesti tistega zadovoljstva, kot ga boste deležni ob delujočem programu in prvem utripanju LED! Razumevanje, da ste z lastnimi rokami naredili resnično delujoč diagram, vam daje samozavest in spodbudo za nadaljevanje!

(Obiskano 7.377 krat, 1 obisk danes)

Odločil sem se, da napišem kratek uvodni članek za tiste, ki so se prvič lotili programiranja mikrokontrolerjev in jezika C še niso poznali. Ne bomo se spuščali v podrobnosti, malo bomo govorili o vsem, da bomo dobili splošno predstavo o delu s CodeVisionAVR.

Podrobnejše informacije najdete v angleščini v uporabniškem priročniku CodeVision, priporočam pa tudi spletno mesto http://somecode.ru z video lekcijami o C za mikrokontrolerje in knjigo »Kako programirati v C« avtorja Deitela, to je začela se je edina dobra knjiga, ki sem jo sam uporabljal.

Začnimo z dejstvom, da ne glede na dejanja, ki jih izvajamo, se na koncu vse zmanjša na vdelano programsko opremo mikrokrmilnika. Sam postopek vdelane programske opreme poteka na naslednji način: z uporabo določenega programa se izbere datoteka vdelane programske opreme, izberejo se parametri, pritisne gumb in neposredno utripa vdelana programska oprema, ki je v bistvu kopija. Tako kot kopirate glasbo ali dokumente iz računalnika na bliskovni pogon, je fizika postopka enaka.

Sama vdelana programska oprema ima končnico .hex in je niz ukazov, v obliki enic in ničel, ki je razumljiv mikrokontrolerju. Kje lahko dobim firmware? Lahko ga prenesete s spletnih mest o elektroniki ali pa ga napišete sami. Lahko ga napišete v posebnih programih, imenovanih razvojno okolje. Meni najbolj znana so AVR Studio, IAR, CodeVision, WinAVR ... Nemogoče je reči, katero od teh okolij je boljše ali slabše, vsako svoje. Lahko rečemo, da se ti programi razlikujejo predvsem po priročnosti, programskem jeziku in ceni. Na tem mestu je upoštevan samo CodeVision.

Razvrstili smo okolje, zdaj pa poglejmo postopek pisanja vdelane programske opreme. V CodeVisionu morate najprej ustvariti projekt. Ustvarite ga lahko s čarovnikom za kodo ali pa ga izpraznite. V vsakem primeru morate izbrati vrsto uporabljenega mikrokrmilnika in navesti njegovo frekvenco. Pri uporabi čarovnika boste morali izbrati začetne nastavitve in ustvariti izvorno kodo z nastavitvami. Nato se prikaže okno, v katerem lahko uredite to kodo. Čeprav lahko svojo izvorno kodo napišete v Beležnico in jo nato priložite projektu v nastavitvah.

Datoteka z izvorno kodo je nabor ukazov v programskem jeziku, naloga CodeVisiona je prevesti te ukaze v binarno kodo, vaša naloga je napisati to izvorno kodo. CodeVision razume jezik C, datoteke izvorne kode imajo končnico ".c". Toda CodeVision ima nekaj konstruktov, ki se ne uporabljajo v C, zato ga mnogi programerji ne marajo, uporabljeni jezik pa se imenuje C-like. Vendar vas to ne ovira pri pisanju resnih projektov. Veliko primerov, generator kode in velik nabor knjižnic dajejo CodeVision veliko prednost. Edina pomanjkljivost je, da je plačan, čeprav obstajajo brezplačne različice z omejitvijo kode.

Izvorna koda mora vsebovati glavo z vrsto uporabljenega mikrokontrolerja in glavno funkcijo. Uporablja se na primer ATtiny13

#vključi void main(void) ( ) ;

#vključi void main(void) ();

Pred glavno funkcijo lahko povežete potrebne knjižnice, deklarirate globalne spremenljivke, konstante in nastavitve. Knjižnica je ločena datoteka, običajno s pripono ».h«, ki že vsebuje vnaprej napisano kodo. V nekaterih projektih morda potrebujemo to kodo, v drugih pa je ne potrebujemo. Na primer, v enem projektu uporabljamo LCD zaslone, v drugem pa ne. Knjižnico za delo z LCD zaslonom “alcd.h” lahko povežete takole:

#vključi #vključi void main(void) ( ) ;

#vključi #vključi void main(void) ();

Spremenljivke so področja pomnilnika, v katere je mogoče postaviti določene vrednosti. Če na primer seštejete dve števili, morate rezultat nekam shraniti, da ga boste lahko uporabili v prihodnosti. Najprej morate deklarirati spremenljivko, tj. dodeli pomnilnik za to, na primer:
int i=0;
tiste. deklarirali smo spremenljivko i in vanjo postavili vrednost 0, int je tip spremenljivke, ali preprosteje, pomeni velikost dodeljenega pomnilnika. Vsak tip spremenljivke lahko shrani samo določen obseg vrednosti. Na primer, int je mogoče zapisati kot števila od -32768 do 32767. Če morate uporabiti števila z ulomkom, je treba spremenljivko deklarirati kot float; za znake uporabite tip char.

bit, _Bit 0 ali 1 char od -128 do 127 unsigned char od 0 do 255 int od -32768 do 32767 unsigned int od 0 do 65535 long int od -2147483648 do 2147483647 unsigned long int od 0 do 4294967295 float od ±1. 1 75e- 38 do ±3,402e38

Znotraj glavne funkcije se glavni program že izvaja. Po izvedbi funkcije se program ustavi, zato naredijo neskončno zanko while, ki stalno ponavlja isti program.

void main(void) ( medtem ko (1) ( ) ; ) ;

void main(void) ( medtem ko (1) ( ); );

Komentar lahko napišete v kateri koli del izvorne kode; to na noben način ne bo vplivalo na delovanje programa, vendar bo pomagalo narediti opombe o napisani kodi. Vrstico lahko zakomentirate z dvema poševnima črtama //nakar bo prevajalnik prezrl celotno vrstico ali več vrstic /**/, na primer:

/*Osnovne matematične operacije:*/ int i= 0; //deklarirajte spremenljivko i in ji dodelite vrednost 0//Seštevanje: i = 2 + 2 ; //Odštevanje: i = 2 - 2 ; //po izvedbi tega izraza bo spremenljivka i enaka 0//Množenje: i = 2 * 2 ; //po izvedbi tega izraza bo spremenljivka i enaka 4//Deljenje: i = 2 / 2 ; //po izvedbi tega izraza bo spremenljivka i enaka 1

/*Osnovne matematične operacije:*/ int i=0; //deklariraj spremenljivko i in ji dodeli vrednost 0 //Seštevanje: i = 2+2; //po izvedbi tega izraza bo spremenljivka i enaka 4 //Odštevanje: i = 2-2; //po izvedbi tega izraza bo spremenljivka i enaka 0 //Množenje: i = 2*2; //po izvedbi tega izraza bo spremenljivka i enaka 4 //Deljenje: i = 2/2; //po izvedbi tega izraza bo spremenljivka i enaka 1

Pogosto mora program preiti iz enega dela kode v drugega, odvisno od pogojev za to obstajajo pogojne operacije if(), na primer:

if(i>3) //če je i večji od 3, potem i dodeli vrednost 0 ( i=0; ) /*če je i manjši od 3, potem pojdi na kodo, ki sledi telesu pogoja, tj. za oklepaji ()*/

Tudi if se lahko uporablja v povezavi z else – drugače

če jaz<3) //если i меньше 3, то присвоить i значение 0 { i=0; } else { i=5; //иначе, т.е. если i больше 3, присвоить значение 5 }

Obstaja tudi primerjalni operator “==”, ki ga ne smemo zamenjevati z “=” assign. Obratna operacija ni enaka "!=", recimo

if(i==3)//če je i 3, i dodeli vrednost 0 ( i=0; ) if(i!=5) //če i ni 5, i dodeli vrednost 0 ( i=0; )

Pojdimo k bolj zapletenim stvarem – funkcijam. Recimo, da imate določen del kode, ki se večkrat ponovi. Poleg tega je ta koda precej velika. Neprijetno ga je pisati vsakič. Na primer, v programu, ki nekako spremeni spremenljivko i, se ob pritisku gumba 0 in 3 vrat D izvede ista koda, ki glede na vrednost spremenljivke i vklopi noge vrat B.

void main(void) ( če (PIND.0== 0) //preverite, ali je gumb na PD0 pritisnjen(če (i== 0) //če i==0 omogoči PB0( PORTB.0= 1 ; ) če (i== 5 ) // če i==5 omogoči PB1( PORTB.1= 1 ; ) ) … če (PIND.3== 0 ) // storite isto, ko preverite gumb PD3( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) ) )

void main(void) ( if(PIND.0==0) //preverite ali je gumb na PD0 pritisnjen ( if(i==0) //if i==0 vklopite PB0 ( PORTB.0=1; ) if( i==5) // if i==5 vklopi PB1 ( PORTB.1=1; ) ) ... if(PIND.3==0) // naredi isto stvar pri preverjanju gumba PD3 ( if(i==0 ) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) )

Na splošno koda ni zelo velika, vendar bi lahko bila večkrat večja, zato bi bilo veliko bolj priročno ustvariti svojo lastno funkcijo.
Na primer:

void i_check() ( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) )

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) )

void pomeni, da funkcija ne vrne ničesar, več o tem spodaj i_check() - to je ime naše funkcije, lahko jo imenujete kakor želite, jaz sem jo imenoval točno tako - preverite i. Zdaj lahko ponovno napišemo kodo:

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) void main(void) ( if(PIND.0==0 ) //preveri, ali je gumb na PD0 pritisnjen ( i_check(); ) ... if(PIND.3==0) ( i_check(); ) )

Ko koda doseže vrstico i_check(); potem bo skočil v funkcijo in izvedel kodo znotraj. Strinjam se, koda je bolj kompaktna in jasnejša, tj. funkcije pomagajo nadomestiti isto kodo, samo eno vrstico. Upoštevajte, da je funkcija deklarirana zunaj glavne kode, tj. pred glavno funkcijo. Lahko rečete, zakaj to potrebujem, vendar boste med preučevanjem lekcij pogosto naleteli na funkcije, na primer brisanje LCD zaslona lcd_clear() - funkcija ne sprejema nobenih parametrov in ne vrne ničesar, vendar počisti zaslon. Včasih se ta funkcija uporablja skoraj v vsaki drugi vrstici, zato so prihranki kode očitni.

Videti je veliko bolj zanimivo uporabljati funkcijo, ko sprejema vrednosti, na primer, obstaja spremenljivka c in obstaja vsota funkcij, ki sprejme dve vrednosti tipa int. Ko glavni program izvede to funkcijo, bodo argumenti že v oklepajih, tako da bo "a" postal enak dve, "b" pa bo postal enak 1. Funkcija se bo izvedla in "c" bo postal enak 3 .

int c= 0; void sum(int a, int b) ( c= a+ b; ) void main(void ) (sum(2, 1) ; )

int c=0; void sum(int a, int b) ( c=a+b; ) void main(void) (sum(2,1); )

Ena najpogostejših podobnih funkcij je premikanje kazalca na LCD zaslonu lcd_gotoxy(0,0); ki mimogrede sprejema tudi argumente - koordinate x in y.

Druga možnost uporabe funkcije, ko ta vrne vrednost, zdaj ne bo več prazna, izboljšajmo prejšnji primer funkcije za seštevanje dveh števil:

int c= 0; int sum(int a, int b) ( return a+ b; ) void main(void) ( c= sum(2, 1) ; )

int c=0; int sum(int a, int b) ( return a+b; ) void main(void) ( с=sum(2,1); )

Rezultat bo enak kot zadnjič c=3, vendar upoštevajte, da spremenljivki "c" dodelimo vrednost funkcije, ki ni več void, ampak vrne vsoto dveh števil tipa int. Na ta način nismo vezani na specifično spremenljivko "c", kar dodaja fleksibilnost pri uporabi funkcij. Preprost primer takšne funkcije je branje podatkov ADC, funkcija vrne izmerjeno vrednost result=read_adc();. Končajmo s funkcijami.

Zdaj pa preidimo na nize. Matrika je povezana spremenljivka. Na primer, če imate sinusno tabelo z več točkami, ne boste ustvarili spremenljivk int sinus1=0; int sinus2=1; itd. Za to se uporablja niz. Ustvarite lahko na primer niz treh elementov, kot je ta:
int sinus=(0,1,5);
Skupno število elementov polja je navedeno v oglatih oklepajih. Vrednost tretjega elementa lahko spremenljivki "c" dodelite takole:
с=sinus;
Upoštevajte, da se številčenje elementov polja začne od nič, tj. "c" bo postal enak pet. Ta niz nima sinusnega elementa!!!
Posameznemu elementu lahko dodelite vrednost takole:
sinus=10;

Morda ste že opazili, da CodeVision nima nizovnih spremenljivk. Tisti. ne morete ustvariti spremenljivega niza hello=”hello”; Če želite to narediti, boste morali ustvariti niz posameznih znakov.

lcd_putchar(pozdravljeni); lcd_putchar(pozdravljeni); lcd_putchar(pozdravljeni);

itd.
Izkazalo se je precej okorno, tu na pomoč pridejo cikli.
Na primer zanka while

medtem ko(PINB.0!=0) ( )

Dokler ne pritisnete gumba, ne storite ničesar - zaženite prazno zanko.

Druga možnost je zanka for

int i; za (i= 0; i< 6 ; i++ ) { lcd_putchar(hello[ i] ) ; }

int i; za(i=0;i<6;i++) { lcd_putchar(hello[i]); }

Pomen je popolnoma enak kot pri medtem, dodana sta samo začetni pogoj i=0 in pogoj, ki se izvede vsak cikel i++. Koda znotraj zanke je čim bolj poenostavljena.

Ko napišete svoj program, se izvorna koda prevede in če ni napak, boste v mapo projekta prejeli želeno strojno programsko opremo. Zdaj lahko utripate mikrokontroler in uživate v delovanju naprave.

Ne smete takoj poskušati uporabiti zank, nizov in funkcij v svoji vdelani programski opremi. Vaša glavna naloga je, da vdelana programska oprema deluje, zato to storite tako, kot vam je lažje in ne bodite pozorni na velikost kode. Prišel bo čas, ko boste želeli ne samo napisati delujočo kodo, ampak jo napisati lepo in kompaktno. Takrat se bo mogoče podati v divjino jezika C. Za tiste, ki želite obvladati vse, še enkrat priporočam knjigo "Kako programirati v C", veliko je primerov in nalog. Namestite Visual Studio, ustvarite konzolno aplikacijo win32 in tam vadite po mili volji.


V tem tečaju usposabljanja za avr sem poskušal opisati vse osnove za začetnike pri programiranju mikrokrmilnikov avr. Vsi primeri so zgrajeni na mikrokrmilniku atmega8. To pomeni, da boste za ponovitev vseh lekcij potrebovali samo en MK. Proteus se uporablja kot emulator elektronskih vezij - po mojem mnenju najboljša možnost za začetnike. Programi v vseh primerih so napisani v prevajalniku C za avr CodeVision AVR. Zakaj ne v kakšnem asemblerju? Kajti začetnik je že nabit z informacijami in program, ki pomnoži dve števili, v asemblerju vzame približno sto vrstic, v kompleksnih, drznih projektih pa uporabljajo C. Prevajalnik CodeVision AVR je prilagojen za mikrokrmilnike atmel, ima priročen generator kode, ima priročen generator programske kode, ima programsko opremo, ki se uporablja za mikrokrmilnike atmel. dober vmesnik in neposredno iz Z njim lahko bliskate mikrokrmilnik.

Ta tečaj usposabljanja bo s preprostimi primeri pojasnil in pokazal, kako:

  • Začnite programirati mikrokontrolerje, kje začeti, kaj potrebujete za to.
  • Katere programe uporabiti za pisanje vdelane programske opreme za avr, za simulacijo in razhroščevanje kode na osebnem računalniku,
  • Katere periferne naprave so znotraj MK, kako jih nadzorovati s svojim programom
  • Kako napisati dokončano vdelano programsko opremo v mikrokrmilnik in kako jo odpraviti
  • Kako narediti PCB za svojo napravo
Če želite narediti prve korake k programiranju MK, boste potrebovali le dva programa:
  • Proteus je emulatorski program (v njem lahko razvijete vezje brez uporabe pravega spajkanja in nato preizkusite naš program na tem vezju). Vse projekte bomo najprej zagnali v Proteusu, nato pa lahko spajkamo pravo napravo.
  • CodeVisionAVR je prevajalnik programskega jezika C za AVR. V njem bomo razvijali programe za mikrokrmilnik, neposredno iz njega pa bo mogoče bliskati pravi MK.
Ko namestite Proteus, ga zaženite
Povabi nas, da si ogledamo projekte, ki prihajajo z njim, vljudno zavrnemo. Zdaj pa ustvarimo najpreprostejše vezje v njem. Če želite to narediti, kliknite ikono in vizualno se nič ne zgodi. Zdaj morate klikniti malo črko P (izberi iz knjižnice) v plošči s seznamom komponent se odpre okno za izbiro komponent
v polje maska ​​vpišemo ime komponente, ki jo želimo najti v knjižnici. Na primer, dodati moramo mikrokrmilnik mega8
na seznamu rezultatov pokažite na mega8 in pritisnite gumb v redu. Mikrokrmilnik mega8 se pojavi na našem seznamu komponent
Tako dodamo še en upor na seznam komponent z vpisom besede maska ​​v polje res in LED LED

Če želite dele postaviti na diagram, kliknite del, nato kliknite polje diagrama, izberite lokacijo komponente in znova kliknite. Če želite diagramu na levi dodati ozemljitev ali splošni negativ, kliknite »Terminal« in izberite Ozemljitev. Tako z dodajanjem vseh komponent in njihovim povezovanjem dobimo to preprosto vezje
To je to, zdaj je naša prva shema pripravljena! Toda morda se vprašate, kaj lahko stori? nič. Nič, saj je za delovanje mikrokontrolerja treba napisati program zanj. Program je seznam ukazov, ki jih bo mikrokrmilnik izvajal. Potrebujemo, da je mikrokrmilnik nameščen na nogi PC0 logična 0 (0 voltov) in logična 1 (5 voltov).

Pisanje programa za mikrokontroler

Program bomo napisali v jeziku C s pomočjo prevajalnika CodeVisionAVR. Po zagonu CV-ja nas vpraša, kaj želimo ustvariti: Vir ali Projekt Izberemo slednjo in kliknemo V redu. Nato bomo pozvani, da zaženemo čarovnika CVAVR CodeWizard (to je neprecenljivo orodje za začetnika, saj lahko ustvari glavno okostje programa) izberite ja
Čarovnik se začne z aktivnim zavihkom Chip, tukaj lahko izberemo model našega MK - to je mega8, in frekvenco, na kateri bo MK deloval (privzeto je mega8 nastavljen na frekvenco 1 megahertz), tako da nastavimo vse, kot je prikazano na zgornjem posnetku zaslona. Pojdite na zavihek Vrata
Mikrokrmilnik atmega8 ima 3 vrata: vrata C, vrata D, vrata B. Vsaka vrata imajo 8 pinov. Pristaniške noge so lahko v dveh stanjih:
  • Izhod
Z uporabo registra DDRx.y lahko nastavimo, da bo pin vhod ali izhod. Če v
  • DDRx.y = 0 - izhod deluje kot VHOD
  • DDRx.y = 1 zatič deluje IZHOD
Ko je pin konfiguriran kot izhod, ga lahko nastavimo na logično 1 (+5 voltov) in logično 0 (0 voltov). To storite tako, da zapišete v register PORTx.y. Nato bomo podrobneje govorili o V/I vratih. Zdaj nastavimo vse, kot je prikazano na posnetku zaslona, ​​in kliknemo Datoteka->Ustvari, shrani in zapusti. Nato nas bo CodeWizard pozval, da shranimo projekt, shranimo ga in pogledamo kodo:

#vključi //knjižnica za ustvarjanje časovnih zamikov void main(void) ( PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x01; // naredi PC0 pin za izhod PORTD=0x00; DDRD=0x00; // Časovnik/števec 0 inicializacija TCCR1A=0x00; OCR1BL=0x00; inicializacija časovnika/števca 2=0x00; Inicializacija prekinitve TIMSK=0x00; // Inicializacija analognega primerjalnika ACSR=0x80;


Morda se vam vse tukaj zdi strašljivo in neznano, a v resnici vse ni tako. Kodo lahko poenostavimo tako, da odpravimo inicializacijo MK perifernih naprav, ki jih ne uporabljamo. Po poenostavitvi je videti takole:

#vključi //knjižnica za delo z mikrokontrolerjem mega8 #include //knjižnica za ustvarjanje časovnih zakasnitev void main(void) ( DDRC=0x01; /* naredi pin PC0 kot izhod Vnos 0x01 se vam morda zdi nepoznan in to je samo številka 1 v šestnajstiški obliki, ta vrstica bo enakovredna na 0b00000001 v dvojiški obliki, potem bom napisal takole.*/ medtem ko (1) ( )


Vse je vredu. Da pa LED utripa, moramo spremeniti logični nivo na zatiču PC0. Če želite to narediti, morate v glavno zanko dodati več vrstic:

#vključi //knjižnica za delo z mikrokontrolerjem mega8 #include //knjižnica za ustvarjanje časovnih zakasnitev void main(void) ( DDRC=0x01; /* naredi pin PC0 izhod. Vnos 0x01 se vam morda zdi nepoznan in to je samo številka 1 v šestnajstiški obliki, ta vrstica bo enakovredna na 0b00000001 v dvojiški obliki, potem bom zapisal točno tako.*/ medtem ko (1) // glavna zanka programa (// odpre operatorski oklepaj glavne zanke programa PORTC.0=1; / / nastavite pin 0 delay_ms(500); // naredite zakasnitev 500 milisekund PORTC.0=0; //nastavite pin 0 delay_ms(500); // naredite zakasnitev 500 milisekund) ;//zapre operatorski oklepaj glavne programske zanke)


To je to, koda je zdaj pripravljena. Kliknite ikono Build all Project files, da prevedete (prevedete v navodila procesorja MK) naš program. V mapi Exe, ki se nahaja v našem projektu, se mora pojaviti datoteka s pripono hex, to je naša datoteka vdelane programske opreme za MK. Če želite našo vdelano programsko opremo vnesti v virtualni mikrokrmilnik v Proteusu, morate dvoklikniti sliko mikrokrmilnika v Proteusu. Pojavilo se bo takšno okno
Kliknite ikono mape v polju Program File, izberite šestnajstiško datoteko naše vdelane programske opreme in kliknite OK. Zdaj lahko izvedemo simulacijo našega vezja. Če želite to narediti, kliknite gumb "Predvajaj" v spodnjem levem kotu okna Proteus.


Deliti