Poradie programovania mikrokontrolérov avr. programovanie mikrokontrolérov avr

Dobrý deň milí rádioamatéri!
Vítam vás na stránke ""

Čo je mikrokontrolér a prečo je potrebný. Pozrime sa na jeho definíciu:

- mikroobvod určený na ovládanie elektronických zariadení, alebo iným spôsobom - jednoduchý počítač (mikropočítač) schopný vykonávať jednoduché úlohy.

To znamená, že mikrokontrolér je v skutočnosti zariadenie, ktoré nám umožňuje realizovať naše nápady (aj bláznivé), ale, samozrejme, v rámci svojich možností. A čo je najdôležitejšie, realizáciu myšlienky nedosiahneme vytvorením sofistikovaných elektronických štruktúr, ale v podstate iba silou našej myšlienky (chceli by ste sa stať čarodejníkom?).
Najpopulárnejšie medzi rádioamatérmi sú dva typy mikrokontrolérov:
PIC- Technológia mikročipov
AVR- od Atmel

Chcel by som urobiť krátku odbočku a objasniť jednu zo svojich pozícií. Nebudem rozoberať prednosti toho či onoho typu mikrokontrolérov, toho či onoho softvéru a vo všeobecnosti všetko, čo s mikrokontrolérmi súvisí, niečo radiť a ešte viac vnucovať čitateľom. Všetko je to vec vkusu, osobných preferencií a vašich konečných cieľov pri učení sa mikrokontrolérov. No, keďže „nesmiernosť sa nedá obsiahnuť“, celé svoje ďalšie rozprávanie uvediem v súvislosti s mikrokontrolérmi AVR a nie veľmi bežným, ale mojím obľúbeným programom „Algorithm Builder“. Rôzne typy mikrokontrolérov, programov, samozrejme, majú rozdiely, ale majú aj veľa spoločného. A naučíme sa svet mikrokontrolérov tak, že neskôr sa získané poznatky dajú bez problémov aplikovať na PIC a akýkoľvek softvér. A ešte raz vám pripomeniem, že táto séria článkov je mojou snahou pomôcť tým, ktorí prvýkrát počuli o existencii mikrokontrolérov a chcú pochopiť, ako s nimi pracovať.

Čo sa potrebujete naučiť pracovať s mikrokontrolérmi? Vybral by som niekoľko, podľa môjho názoru, hlavných podmienok:
1. Túžba a vytrvalosť .
Všetko je tu veľmi jednoduché: existuje túžba - všetko bude fungovať. A túžba s vytrvalosťou je vo všeobecnosti super vec.
2. Znalosť zariadenia mikrokontroléra.
Hlboké znalosti tu nie sú dôležité (a možno vôbec nie), ale je potrebné vedieť, čo je „na palube“ mikrokontroléra. Len keď vieme, z čoho sa mikrokontrolér skladá, aké má zariadenia, ich možnosti, ako fungujú – len vtedy budeme môcť využiť možnosti mikrokontroléra naplno.
3. Znalosť programovacieho jazyka a riadiacich príkazov mikrokontroléra.
Ako bude mikrokontrolér fungovať, aké úlohy mu pridelíte a ako ich bude vykonávať, určuje program v ňom vložený – program, ktorý si pre mikrokontrolér sami zostavíte. A tomuto bodu sa budeme venovať podrobnejšie, aby sme zvážili problémy, ktoré môžu nastať v budúcnosti.

Program(v preklade toto slovo znamená „predpis“) - predbežný popis nadchádzajúcich udalostí alebo akcií.

Napríklad chceme, aby mikrokontrolér blikal LED. Jednoduchá úloha, ale aby mikrokontrolér túto úlohu splnil, musíme najprv krok za krokom opísať všetky činnosti mikrokontroléra, napísať program, ktorý musí vykonať, aby získal výsledok, ktorý potrebujeme - blikajúca LED dióda . Niečo také:
♦ Rozsvieťte LED:
- nakonfigurujte výstup, ku ktorému je LED pripojená, aby pracoval na výstupe informácií
- aplikujte na tento kolík logickú úroveň, ktorá vám umožní rozsvietiť LED
♦ Chvíľu počkajte:
- prejdite na podprogram, ktorý tvorí pauzu (ktorú je tiež potrebné „prežuť“)
- po dokončení podprogramu pauza sa vráťte do hlavného programu
♦ Vypnite LED:
- aplikujte logickú úroveň na výstup, zhasnite LED
a tak ďalej.
s termínom Program iný pojem je neoddeliteľne spojený - Algoritmus(ako vlk a zajac, Tom a Jerry).

Algoritmus- súbor pokynov, ktoré popisujú postup na dosiahnutie požadovaného výsledku.

Ak sme v programe najpodrobnejšie predpísať akcie mikrokontrolér, potom v algoritme sme určiť postup mikrokontrolér, na základe ktorého potom vytvoríme program. Podobne ako v príklade vyššie:
♦ Rozsvieťte LED
♦ Chvíľu počkajte
♦ Vypnite LED
a tak ďalej.
Touto cestou, algoritmus je predchodcom programu. A čím starostlivejšie a premyslenejšie je algoritmus vytvorený, tým jednoduchšie bude vytvorenie programu.

Celkovo je program pre mikrokontrolér sekvenciou akcií mikrokontroléra vo forme súboru príkazov a pokynov, ktoré musí vykonať, aby dosiahol naše ciele.

Príkazy pre mikrokontrolér vyzerajú ako množina jednotiek a núl:
00110101 011000100
tzv.- príkazové kódy, a príkazové kódy sú jazyk, ktorému mikrokontrolér rozumie. A aby sme preložili náš algoritmus z ruštiny do jazyka mikrokontroléra - do týchto množín núl a jednotiek existujú špeciálne programy.
Tieto programy nám umožňujú popísať poradie práce pre mikrokontrolér v pre nás viac či menej zrozumiteľnom jazyku a následne toto poradie preložiť do jazyka zrozumiteľného pre mikrokontrolér, výsledkom čoho je tzv. strojový kód- postupnosť príkazov a inštrukcií (samotné nuly a jednotky), ktorým rozumie iba mikrokontrolér. Text programu napísaného programátorom sa nazýva zdrojový kód. Program je preložený z programovacieho jazyka (zdrojový kód) do jazyka mikrokontroléra (strojový kód) prekladateľov. Prekladač prevedie text programu na strojové kódy, ktoré sa následne zapíšu do pamäte mikrokontroléra.
V takýchto programoch je poradie činnosti mikrokontroléra popísané špeciálnym jazykom - programovacím jazykom. Programovací jazyk sa líši od nášho ľudského jazyka. Ak je náš komunikačný jazyk primárne určený na výmenu informácií, potom:

Programovací jazyk - je to spôsob prenosu príkazov, inštrukcií, jasný návod na činnosť pre mikrokontrolér.

Existuje mnoho programovacích jazykov a možno ich rozdeliť do dvoch typov:
nízkoúrovňové programovacie jazyky
programovacie jazyky na vysokej úrovni
V čom je rozdiel. A líšia sa svojou blízkosťou k mikrokontroléru.
Na úsvite vzniku mikroprocesorovej technológie boli programy napísané v strojových kódoch, to znamená, že celý algoritmus práce bol postupne napísaný vo forme núl a jednotiek. Takto vyzeral program:

01000110
10010011
01010010

Je nepravdepodobné, že niekto bude schopný zistiť takú sadu kombinácií dvoch čísel a práca prvých programátorov bola veľmi namáhavá. Aby si programátori uľahčili život, začali vytvárať prvé programovacie jazyky. Čím je teda programovací jazyk bližšie k takejto množine núl a jednotiek, tým je „nízka úroveň“ a čím ďalej od nich, tým je „vyššia“.
Najbežnejšie programovacie jazyky pre mikrokontroléry:
- jazyk nízkej úrovne - assembler
– jazyk na vysokej úrovni – C (Ci)
Pozrime sa na príklad ich rozdielu (tieto príklady sú abstraktné).
Povedzme, že potrebujeme pridať dve čísla: 25 a 35.
V natívnom kóde môže tento príkaz vyzerať takto:
00000101 1101001
V jazyku nízkej úrovne:
PRIDAŤ Rd, Rr
V jazyku vysokej úrovne:
25+35
Rozdiel medzi jazykmi nízkej a vysokej úrovne je viditeľný voľným okom, komentáre, ako sa hovorí, sú zbytočné.
Poďme však hlbšie do týchto príkladov. Nebudeme analyzovať príklad strojového kódu, pretože je identický s príkladom v assembleri. Vo svojom jadre sú montážne pokyny rovnaké strojové kódy (príkazy), ktorým sú jednoducho priradené písmenové skratky, aby sa nestratili v nulách a jednotkách. Inštrukciou assemblera ADD Rd, Rr nastavíme mikrokontrolér tak, aby sčítal dve čísla, ktoré sa našli (a preto ich tam musíme najprv napísať) - prvé do Rd, druhé do Rr a umiestnime výsledok sčítania. v Rd. Ako vidíte, nastavili sme pre mikrokontrolér veľmi špecifickú úlohu: kde ho získať, čo s ním robiť a kam umiestniť výsledok. V tomto prípade pracujeme priamo s mikrokontrolérom.
Príkaz v jazyku vysokej úrovne: 25+35 , nám známy matematický zápis, ktorý lahodí našim očiam. Ale v tomto prípade nepracujeme priamo s mikrokontrolérom, jednoducho mu nastavíme úlohu sčítania dvoch čísel. Výsledok a postupnosť akcií bude v tomto prípade rovnaká ako pri vykonávaní príkazu assembler: najprv sa tieto dve čísla niekde zapíšu, potom sa spočítajú a výsledok sa niekde umiestni.
A tu je hlavný rozdiel medzi jazykmi na vysokej a nízkej úrovni. Ak v Assembleri riadime celý proces (či sa nám to páči alebo nie): vieme, kde sú tieto dve čísla napísané, a vieme, kde bude výsledok, potom v jazyku vysokej úrovne tento proces nekontrolujeme. Program sám rozhodne, kam predpíše čísla a kam umiestni výsledok. Vo väčšine prípadov to nepotrebujeme vedieť, pretože pre nás je hlavným výsledkom číslo 60 vo výstupe. Výsledkom je, že programy vo vyšších jazykoch sú čitateľnejšie, lahodia oku a majú menšiu veľkosť – nemusíme predsa „liezť do všetkých dier“ a maľovať každý krok mikrokontroléra, programu urobí to za nás neskôr, keď to skompiluje - preloží to do strojových kódov. Má to však aj negatívnu stránku. Dva identické algoritmy napísané v Assembleri a v C budú mať po konverzii na strojové kódy inú veľkosť: program napísaný v Assembleri bude o 20-40% kratší ako program napísaný v C - čert vie, ktorým smerom ide C dosiahnuť výsledok, ktorý potrebujeme. A sú prípady, keď sa nedôveruje vysokoúrovňovému jazyku a do programu C vložia kód napísaný v Assembleri.
Profesionálni programátori spravidla poznajú niekoľko programovacích jazykov (alebo pracujú v tíme, ktorý zahŕňa špecialistov v rôznych jazykoch), kreatívne kombinujú svoje funkcie a výhody v jednom programe. No my, amatéri, potrebujeme vedieť aspoň jeden jazyk (na začiatok) a treba začať (a o tom som pevne presvedčený a nikto ma nepresvedčí) od jazyka nízkej úrovne – Assembly.

No, myslím, a tu je nám všetko jasné - musíte sa naučiť programovací jazyk iným spôsobom - v žiadnom prípade.

Príkazy a pokyny na ovládanie mikrokontroléra.
Mikrokontroléry AVR majú viac ako 130 rôznych príkazov, ktoré im umožňujú realizovať všetky možnosti, ktoré sú s tým spojené. Ale hneď poviem, že len málo amatérov ich všetky pozná, nieto ich všetky používa. Väčšinou je v amatérskej praxi dostatok vedomostí a polovica tímov, alebo aj menej. Musíte sa však naučiť príkazy. Čím viac príkazov poznáte, tým sofistikovanejšie (v dobrom slova zmysle) a elegantnejšie programy budú.

Aritmetická logická jednotka a organizácia pamäte - programová pamäť, dátová pamäť, energeticky nezávislá pamäť



V tomto návode na avr som sa snažil popísať všetky najzákladnejšie veci pre začiatočníkov pri programovaní mikrokontrolérov. avr. Všetky príklady sú postavené na mikrokontroléri atmega8. To znamená, že na opakovanie všetkých lekcií budete potrebovať iba jeden MK. Ako emulátor elektronických obvodov sa používa Proteus - podľa môjho názoru najlepšia voľba pre začiatočníkov. Programy vo všetkých príkladoch sú napísané na kompilátore C pre avr CodeVision AVR. Prečo nie v nejakom assembleri? Pretože začiatočník je už nabitý informáciami a program, ktorý vynásobí dve čísla, zaberie v assembleri asi sto riadkov a v zložitých tučných projektoch používajú C. Kompilátor CodeVision AVR je nabrúsený pre mikrokontroléry atmel, má pohodlný generátor kódu, a dobré rozhranie a priamo z neho môže byť flashovaný mikrokontrolérom.

Tento návod ukáže a na jednoduchých príkladoch vysvetlí, ako:

  • Začnite programovať mikrokontroléry, kde začať, čo na to potrebujete.
  • Aké programy použiť na písanie firmvéru pre avr, na simuláciu a ladenie kódu na PC,
  • Aké periférne zariadenia sú vo vnútri MK, ako ich ovládať pomocou vášho programu
  • Ako zapísať hotový firmvér do mikrokontroléra a ako ho odladiť
  • Ako vytvoriť PCB pre vaše zariadenie
Aby ste mohli urobiť prvé kroky k programovaniu MK, potrebujete iba dva programy:
  • Proteus je program emulátora (môžete v ňom vyvinúť obvod bez použitia skutočného spájkovania a potom otestovať náš program na tomto obvode). Najprv spustíme všetky projekty v Proteuse a potom už môžeme spájkovať skutočné zariadenie.
  • CodeVisionAVR je kompilátor programovacieho jazyka C pre AVR. V ňom budeme vyvíjať programy pre mikrokontrolér a priamo z neho bude možné flashovať skutočný MK.
Po inštalácii Proteus ho spustite
Ponúka nám vidieť projekty, ktoré s ním idú, my slušne odmietame. Teraz v ňom vytvoríme najjednoduchší obvod. Ak to chcete urobiť, kliknite na ikonu vizuálne sa nič nestane. Teraz musíte kliknúť na malé písmeno R (vybrať z knižnice) na paneli zoznamu komponentov sa otvorí okno výberu komponentov
do poľa maska ​​zadáme názov komponentu, ktorý chceme nájsť v knižnici. Napríklad potrebujeme pridať mikrokontrolér mega8
v zozname výsledkov strčte na mega8 a stlačte tlačidlo OK. V zozname komponentov máme mikrokontrolér mega8
Do zoznamu komponentov teda pridáme ďalší rezistor zadaním slova do poľa masky res a LED viedol

Ak chcete umiestniť diely do diagramu, kliknite na diel, potom kliknite na pole diagramu, vyberte umiestnenie komponentu a znova kliknite. Ak chcete do obvodu naľavo pridať uzemnenie alebo spoločné mínus, kliknite na „Terminal“ a vyberte možnosť Uzemnenie. Sčítaním všetkých komponentov a ich spojením teda dostaneme taký jednoduchý obvod
Všetko, teraz je naša prvá schéma pripravená! Ale možno sa pýtate, čo môže robiť? Ale nič. Nič, pretože na to, aby mikrokontrolér fungoval, je potrebné preň napísať program. Program je zoznam inštrukcií, ktoré mikrokontrolér vykoná. Mikrokontrolér potrebujeme na inštaláciu na nohu PC0 logická 0 (0 voltov) a logická 1 (5 voltov).

Napísanie programu pre mikrokontrolér

Program napíšeme v jazyku C pomocou kompilátora CodeVisionAVR. Po spustení CV sa nás pýta, čo chceme vytvoriť: Zdroj alebo Projekt Vyberieme to posledné a stlačíme tlačidlo OK. Ďalej budeme požiadaní o spustenie CVAVR CodeWizard (toto je neoceniteľný nástroj pre začiatočníkov, pretože dokáže vygenerovať hlavnú kostru programu) vyberte si Áno
Sprievodca začína aktívnou záložkou Čip, tu si môžeme vybrať model nášho MK - to je mega8, a frekvenciu, na ktorej bude MK fungovať (mega8 je štandardne nastavený na 1 megahertz), takže všetko nastavíme tak, ako je znázornené na snímka obrazovky vyššie. Prejdite na kartu Porty
Mikrokontrolér atmega8 má 3 porty: Port C, Port D, Port B. Každý port má 8 pinov. Piny portu môžu byť v dvoch stavoch:
  • VÝCHOD
Pomocou registra DDRx.y môžeme pin nastaviť ako vstupný alebo výstupný. Ak v
  • DDRx.y = 0 - výstup funguje ako VSTUP
  • DDRx.y = 1 pin funguje VÝCHOD
Keď je pin nakonfigurovaný ako výstup, môžeme ho nastaviť na logickú 1 (+5 voltov) a logickú 0 (0 voltov). Robí sa to zápisom do registra PORTx.y. Ďalej sa budeme podrobne zaoberať vstupno-výstupnými portami. A teraz nastavíme všetko tak, ako je znázornené na snímke obrazovky, a kliknite na Súbor->Generovať, Uložiť a ukončiť. Ďalej nám CodeWizard ponúkne uloženie projektu, my ho uložíme a pozrieme sa na kód:

#include //knižnica na vytváranie časových oneskorení void main(void) ( PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x01; // vytvorenie výstupu nohy PC0 PORTD=0x00; DDRD=0x00; // Inicializácia časovača/počítadla 0 OHX ; OCR1BL=0x00; // Inicializácia časovača/počítadla 2 ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // Inicializácia externých prerušení MCUCR=0x00; // Časovač(y)/Počítadlá ) Inicializácia prerušení TIMSK=0x00; // Inicializácia analógového komparátora ACSR=0x80; SFIOR=0x00; zatiaľ čo (1) ( ); )


Všetko sa vám tu môže zdať strašidelné a neznáme, ale v skutočnosti to tak nie je. Kód sa dá zjednodušiť vyhodením inicializácie periférií MK, ktoré nepoužívame. Po zjednodušení to vyzerá takto:

#include //knižnica pre prácu s mikrokontrolérom mega8 #include //knižnica na vytváranie časových oneskorení void main(void) ( DDRC=0x01; /* urobte z úseku PC0 výstupný záznam 0x01, ktorý sa vám môže zdať neznámy, a toto je len číslo 1 v šestnástkovej sústave, tento riadok bude ekvivalentný 0b00000001 v binárnom, potom budem písať presne takto. */ while (1) ( ); )


Všetko je v poriadku. Aby ale LEDka blikala, musíme zmeniť logickú úroveň na nohe PC0. Ak to chcete urobiť, pridajte do hlavnej slučky niekoľko riadkov:

#include //knižnica pre prácu s mikrokontrolérom mega8 #include //knižnica na vytváranie časových oneskorení void main(void) ( DDRC=0x01; /* urobte z úseku PC0 výstupný záznam 0x01, ktorý sa vám môže zdať neznámy, a toto je len číslo 1 v šestnástkovej sústave, tento riadok bude ekvivalentný 0b00000001 binárne, potom budem písať presne takto.*/ while (1)//hlavná programová slučka (// zátvorka operátora hlavnej programovej slučky otvorí PORTC.0=1; //nastaví port C 1 na pin 0 delay_ms(500); //urobí oneskorenie o 500 milisekúnd PORTC.0=0; // nastaví port C 0 na pin 0 delay_ms(500); // urobí oneskorenie 500 milisekúnd );// zatvorí zátvorku operátora hlavnej programovej slučky)


Všetko, teraz je kód pripravený. Kliknutím na ikonu Build all Project files skompilujeme (preložíme do inštrukcií procesora MK) náš program. V priečinku Exe, ktorý sa nachádza v našom projekte, by sa mal objaviť súbor s príponou hex, toto je náš súbor firmvéru pre MK. Ak chcete nahrať náš firmvér do virtuálneho mikrokontroléra v Proteuse, musíte dvakrát kliknúť na obrázok mikrokontroléra v Proteuse. Zobrazí sa okno ako toto
kliknite na ikonu priečinka v poli Program File, vyberte hex - súbor nášho firmvéru a stlačte tlačidlo OK. Teraz môžeme spustiť simuláciu nášho obvodu. Ak to chcete urobiť, kliknite na tlačidlo "Prehrať" v ľavom dolnom rohu okna Proteus.

Viac ako raz alebo dvakrát som povedal, že štúdium MK by malo začať assemblerom. Tomu bol venovaný celý kurz na stránke (nie je síce veľmi dôsledný, ale postupne to vyčesávam do adekvátneho vzhľadu). Áno, je to ťažké, výsledok nebude hneď v prvý deň, ale naučíte sa rozumieť tomu, čo sa deje vo vašom ovládači. Budete vedieť, ako to funguje, a nebudete kopírovať zdroje iných ľudí ako opice a snažiť sa pochopiť, prečo to zrazu prestalo fungovať. Okrem toho je pre C oveľa jednoduchšie pomotať sa s kódom robotníka, ktorý sa vyvalí vidlami v tú najnevhodnejšiu chvíľu.

Bohužiaľ, každý chce výsledky okamžite. Preto som sa rozhodol ísť inou cestou – spraviť návod na C, ale s ukážkou jeho spodnej bielizne. Dobrý programátor embedderov vždy pevne drží svoj kus železa za škvarku, čím mu zabráni urobiť jediný krok bez povolenia. Čo teda bude najskôr C kód, potom čo zrodil kompilátor a ako to celé funguje v skutočnosti :)

Na druhej strane, silnou stránkou C je prenosnosť kódu. Ak, samozrejme, napísať všetko správne. Rozdelenie pracovných algoritmov a ich železných implementácií do rôznych častí projektu. Potom, aby bolo možné preniesť algoritmus na iný MK, bude stačiť prepísať iba vrstvu rozhrania, kde je zapísaný všetok prístup k hardvéru, a nechať všetok pracovný kód tak, ako je. A, samozrejme, čitateľnosť. Zdrojový kód Sish je na prvý pohľad zrozumiteľnejší (aj keď .. napríklad mi je jedno, na čo mám kliknúť - aspoň si, aspoň asm :)), ale opäť, ak je všetko napísané správne. Budem venovať pozornosť aj týmto bodom.

Ako experimentálny kus železa, na ktorom bude umiestnený leví podiel všetkých príkladov, bude moja ladiaca doska.

Prvý program C pre AVR

Výber kompilátora a inštalácia prostredia
Existuje veľa rôznych kompilátorov C pre AVR:
V prvom rade toto IAR AVR C- takmer jednoznačne uznávaný ako najlepší kompilátor pre AVR, tk. samotný ovládač vznikol v úzkej spolupráci Atmelu a špecialistov z IAR. Za všetko však treba platiť. A tento kompilátor nie je len drahý komerčný softvér, ale má aj takú plejádu nastavení, že ho v ňom musíte len pracne skompilovať. Naozaj som s ním nemal priateľstvo, projekt zhnil kvôli zvláštnym chybám vo fáze spájania (neskôr som zistil, že to bola krivá trhlina).

Ide druhý WinAVR GCC je výkonný optimalizačný kompilátor. Plný open source, multiplatformový, vo všeobecnosti všetky radosti života. Dokonale sa tiež integruje do AVR Studio, čo vám umožní ladiť priamo tam, čo je pekelne pohodlné. Vo všeobecnosti som si to vybral.

Tiež majú CodeVision AVR C je veľmi populárny kompilátor. Stala sa populárnou vďaka svojej jednoduchosti. Pracovný program v ňom získate za pár minút – veľkou mierou k tomu prispieva sprievodca štartovacím kódom, ktorý razí štandardy pre inicializáciu akýchkoľvek uartov. Aby som bol úprimný, nejako sa k nemu správam podozrievavo - raz som musel rozobrať program napísaný týmto kompilátorom, objavila sa nejaká kaša a nie kód. Strašné množstvo zbytočných gest a operácií, čo malo za následok pomerne veľké množstvo kódu a pomalý výkon. Možno však došlo k chybe v DNA pôvodného zapisovača firmvéru. Navyše chce peniaze. Nie toľko ako IAR, ale znateľné. A v demo režime vám umožňuje napísať maximálne 2 kb kódu.
Samozrejme je tam crack, ale ak kradneš, tak milión, v zmysle IAR :)

Je tu tiež Image Craft AVR C a MicroC z mikroelektroniky. Ani jedno som nemusel použiť, ale... SWG veľmi chválim mikropascal, hovoria, strašne pohodlné programovacie prostredie a knižnice. Myslím, že MicroC nebude o nič horší, ale aj platený.

Ako som povedal, vybral som si WinAVR z troch dôvodov: zadarmo, integruje sa do AVR Studio a na každú príležitosť je preň napísaný len pár pripravených kódov.

Stiahnite si WinAVR s a AVR Studio. Ďalej sa najprv nainštaluje štúdio, potom sa zhora zroluje WinAVR a prichytí sa k štúdiu vo forme zásuvného modulu. Dôrazne odporúčam umiestniť WinAVR na krátku cestu, niečo ako C:\WinAVR, čím sa vyhnete mnohým problémom s cestami.

Tvorba projektu
Štúdio je teda nachystané, C naskrutkované, je čas skúsiť niečo naprogramovať. Začnime tým jednoduchým, najjednoduchším. Spustite štúdio, vyberte tam nový projekt ako kompilátor AVR GCC a zadajte názov projektu.

Pracovný priestor sa otvorí s prázdnym súborom *.c.

Teraz nezaškodí nakonfigurovať zobrazenie ciest v záložkách štúdia. Ak to chcete urobiť, prejdite na:
Ponuka Nástroje - Možnosti - Všeobecné - Karty súborov a z rozbaľovacieho zoznamu vyberte možnosť "Iba názov súboru". V opačnom prípade nebude možné pracovať - ​​karta bude obsahovať úplnú cestu k súboru a na obrazovke nebudú viac ako dve alebo tri karty.

Nastavenie projektu
Vo všeobecnosti sa za klasické považuje vytvorenie súboru make, v ktorom by boli popísané všetky závislosti. A toto je asi správne. Ale pre mňa, ktorý vyrastal s plne integrovanými IDE, ako uVision alebo Štúdio AVR tento prístup je hlboko cudzí. Preto to urobím po svojom, všetkými prostriedkami štúdia.

Kliknite na tlačidlo ozubeného kolieska.


Toto sú nastavenia pre váš projekt, alebo skôr nastavenia pre automatické generovanie súboru make. Na prvej stránke stačí zadať frekvenciu, v akej bude váš MK fungovať. Závisí to od bitov poistky, takže predpokladáme, že frekvencia je 8 000 000 Hz.
Venujte pozornosť aj optimalizačnej línii. Teraz je tu -Os je optimalizácia veľkosti. Zatiaľ to nechajte tak, potom sa môžete skúsiť pohrať s týmto parametrom. -O0 nie je vôbec žiadna optimalizácia.

Ďalším krokom je nastavenie ciest. V prvom rade si tam pridajte adresár svojho projektu – dáte tam knižnice tretích strán. V zozname sa zobrazí cesta „.\“.

Vytvorí sa súbor make, môžete si ho pozrieť v predvolenom priečinku vo vašom projekte, stačí sa pozrieť, čo tam je.


To je zatiaľ všetko. Kliknite na tlačidlo OK všade a prejdite na zdroj.

Formulácia problému
Prázdna tabuľka je lákavá na stelesnenie nejakého prefíkaného nápadu, pretože banálne blikanie diódy už nevkladá. Okamžite vezmime býka za rohy a implementujme spojenie s počítačom - to je prvá vec, ktorú robím.

Bude to fungovať takto:
Keď príde jednotka na COM port (kód 0x31), zapneme diódu a keď príde nula (kód 0x30), zhasneme ju. Navyše sa všetko bude robiť na prerušeniach a úlohou na pozadí bude blikanie ďalšej diódy. Jednoduché a zmysluplné.

Zostavenie schémy
Potrebujeme pripojiť modul prevodníka USB-USART na piny USART mikrokontroléra. Aby sme to urobili, vezmeme prepojku dvoch drôtov a nasadíme ich na kolíky krížom. To znamená, že spojíme Rx regulátora s Tx prevodníka a Tx prevodníka s Rx regulátora.

Nakoniec sa ukazuje, že toto je schéma:


Zapojenie zvyšných výstupov, napájanie, reset neuvažujem, to je štandard

Napíšeme kód

Okamžite urobím rezerváciu, že sa nebudem konkrétne venovať popisu samotného jazyka C. Na to je jednoducho obrovské množstvo materiálu, od klasického „programovacieho jazyka C“ od K&R až po rôzne príručky.

Jedna taká metóda sa našla v mojej skrýši, raz som pomocou nej študoval tento jazyk. Všetko je krátke, jasné a k veci. Postupne ho zadávam a presúvam na svoju stránku.

Je pravda, že tam ešte nie sú presunuté všetky kapitoly, ale myslím, že to nie je na dlho.

Je nepravdepodobné, že to opíšem lepšie, preto zo školiaceho kurzu namiesto podrobného vysvetlenia zložitosti Cish jednoducho uvediem priame odkazy na jednotlivé stránky tohto návodu.

Pridávanie knižníc.
V prvom rade pridávame potrebné knižnice a hlavičky s definíciami. C je predsa univerzálny jazyk a treba vysvetliť, že pracujeme s AVR, takže do zdrojového kódu zadajte riadok:

1 #include

#include

Tento súbor sa nachádza v priečinku WinAVR a obsahuje popis všetkých registrov a portov radiča. A tam je všetko zložité s odkazom na konkrétny ovládač, ktorý prenáša kompilátor urobiť súbor v parametri MCU a na základe tejto premennej sa k vášmu projektu pripojí hlavičkový súbor s popisom adries všetkých portov a registrov pre tento konkrétny ovládač. Ako! Bez toho môžete tiež, ale potom nebudete môcť používať symbolické názvy registrov ako SREG alebo UDR a budete si musieť zapamätať adresu každého z nich ako "0xC1", a to vám láme hlavu.

Presne ten istý tím #include<имя файла> umožňuje pridať do projektu obsah ľubovoľného textového súboru, napríklad súbor s popisom funkcií alebo kus iného kódu. A aby smernica mohla nájsť tento súbor, uviedli sme cesty k nášmu projektu (adresár WinAVR je tam už štandardne zaregistrovaný).

hlavná funkcia.
C program je o funkciách. Môžu byť vnorené a volané jeden od druhého v akomkoľvek poradí a mnohými rôznymi spôsobmi. Každá funkcia má tri požadované parametre:

  • Návratová hodnota, napr. hriech(x) vráti hodnotu sínusu x. Ako skrátka v matematike.
  • Prenesené parametre, rovnaké x.
  • Funkčné telo.

Všetky odovzdané a vrátené hodnoty musia byť určitého typu v závislosti od údajov.

Každý program v jazyku C musí obsahovať funkciu hlavné ako vstupný bod do hlavného programu, inak to vôbec nie je C :). Prítomnosťou hlavného v zdroji milióna súborov niekoho iného môžete pochopiť, že toto je hlavná časť programu, odkiaľ všetko začína. Tu nastavíme:

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

int main(void) ( return 0; )

To je všetko, prvý najjednoduchší program bol napísaný, nevadí, že nič nerobí, len sme začali.

Pozrime sa, čo sme urobili.
int je dátový typ, ktorý vracia hlavná funkcia.

Samozrejme, v mikrokontroléri hlavné v zásade sa nedá nič vrátiť a teoreticky by to tak malo byť void main (void), ale GCC je pôvodne zaostrené na PC a tam program po dokončení dokáže vrátiť hodnotu do operačného systému. Preto GCC zapnuté void main (void) prisahá pri Varovaní.

To nie je chyba, bude to fungovať, ale nemám rád upozornenia.

neplatné v tomto prípade ide o typ údajov, ktoré funkcii odovzdávame hlavné tiež nemôže prijať nič zvonku, básnik neplatné- prázdny. Pahýľ sa používa, keď nie je potrebné nič odovzdať alebo vrátiť.

Tu sú tieto { } zložené zátvorky je programový blok, v tomto prípade telo funkcie hlavné, kód sa tam bude nachádzať.

vrátiť- toto je návratová hodnota, ktorú nám po dokončení dá hlavná funkcia, keďže máme int, teda číslo, tak musíme vrátiť číslo. Aj keď to stále nedáva zmysel, pretože. na mikrokontroléri z hlavného, ​​môžeme ísť len nikam. vraciam null. Pre nefig. A kompilátor je zvyčajne chytrý a negeneruje kód pre tento prípad.
Hoci, ak zvrátené, tak z hlavné môžete prejsť na MK - napríklad vypadnúť do sekcie bootloader a spustiť ho, ale tu už budete potrebovať nízkoúrovňový výber firmvéru, aby ste opravili prechodové adresy. Nižšie uvidíte a pochopíte, ako to urobiť. Za čo? To je ďalšia otázka, v 99,999% prípadov to nie je potrebné :)

Hotovo, ide sa ďalej. Pridajme premennú, v skutočnosti ju nepotrebujeme a nemali by sme bez nej zavádzať premenné, ale učíme sa. Ak sú premenné pridané do tela funkcie, potom sú lokálne a existujú iba v tejto funkcii. Keď opustíte funkciu, tieto premenné sa vymažú a pamäť RAM sa pridelí dôležitejším potrebám. .

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

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

nepodpísané znamená nepodpísaný. Faktom je, že v binárnej reprezentácii je najvýznamnejší bit priradený znamienku, čo znamená, že číslo +127/-128 sa zmestí do jedného bajtu (char), ale ak sa znamienko zahodí, zmestí sa od 0 do 255. Zvyčajne znak nie je potrebný. Takže to nepodpísané.
i je len názov premennej. Nikdy viac.

Teraz musíme inicializovať porty a UART. Samozrejme, môžete si vziať a pripojiť knižnicu a zavolať nejaký druh UartInit (9600); ale potom nebudes vediet co sa vlastne stalo.

Robíme toto:

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(prenosová hranica) ; UBRRH = HI(prenosová jednotka) ; 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 (deliteľ prenosovej rýchlosti); UBRRH = HI (deliteľ prenosovej rýchlosti); UCSRA = 0; UCSRB = 1<

desivé? V skutočnosti existuje len päť posledných riadkov skutočného kódu. Všetko, to #definovať je to makrojazyk preprocesora. Takmer rovnaké vrcholy ako v Assembleri, ale syntax je trochu iná.

Uľahčia vám bežné operácie pri výpočte požadovaných koeficientov. V prvom riadku hovoríme, že namiesto XTAL môžete bezpečne nahradiť 8000000 a L- označenie typu, hovorí sa, že long je hodinová frekvencia procesora. To isté prenosová rýchlosť- frekvencia prenosu dát cez UART.

prenosový delič už zložitejšie, namiesto neho sa nahradí výraz vypočítaný vzorcom z predchádzajúcich dvoch.
No a LO a AHOJ z tohto výsledku sa zoberú nízke a vysoké bajty, pretože zjavne sa nezmestí do jedného bajtu. AT AHOJ x sa posunie (vstupný parameter makra) osemkrát doprava, v dôsledku toho z neho zostane len vysoký bajt. A v LO robíme bitové AND s číslom 00FF, pričom ako výsledok ponecháme iba nízky bajt.

Takže všetko, čo sa robí, je ako #definovať pokojne to môžete vyhodiť a na kalkulačke si vypočítať potrebné čísla a hneď ich zadať do riadkov UBBRL = .... a UBBRH=…..

Môcť. Ale! To urobiť PRÍSNE NEMOŽNÉ!

Bude to fungovať tak a tak, ale budete mať tzv magické čísla- hodnoty prevzaté odnikiaľ a nie je jasné prečo, a ak takýto projekt otvoríte za pár rokov, potom bude sakra ťažké pochopiť, aké sú tieto hodnoty. A teraz, ak chcete zmeniť rýchlosť, alebo zmeniť frekvenciu kremeňa a budete musieť všetko prepočítať, tak ste zmenili pár čísel v kóde a je to. Vo všeobecnosti, ak nechcete, aby vás považovali za zlého kódera, urobte kód tak, aby bol ľahko čitateľný, zrozumiteľný a ľahko upraviteľný.

Potom je všetko jednoduché:
Všetky tieto "UBRLL and Co" sú konfiguračné registre vysielača UART, s ktorým budeme komunikovať so svetom. A teraz sme im priradili potrebné hodnoty, nastavili ich na požadovanú rýchlosť a požadovaný režim.

Zobraziť záznam 1< Znamená nasledovné: vezmite 1 a vložte ho na svoje miesto RXEN v byte. RXEN toto je 4. bit registra UCSRB, takže 1< tvorí binárne číslo 00010000, TXEN je 3. bit a 1< dá 00001000. Jediné "|" je to bitové ALEBO, teda 00010000 | 00001000 = 00011000. Rovnakým spôsobom sa nastavia zostávajúce potrebné konfiguračné bity a pridajú sa do spoločnej haldy. Výsledkom je, že zhromaždené číslo sa zapíše do UCSRB. Bližšie je to popísané v datasheete na MK v sekcii USART. Nenechajte sa preto rozptyľovať technickými detailmi.

Hotovo, je čas vidieť, čo sa stane. Kliknite na kompiláciu a spustite emuláciu (Ctrl+F7).

Ladenie
Prebehli najrôznejšie postupové lišty, štúdio sa zmenilo a pri vchode do hlavnej funkcie sa objavila žltá šípka. Tu je momentálne procesor a simulácia je pozastavená.

Faktom je, že spočiatku to v skutočnosti bolo na riadku UBRRL = LO(bauddivider); Koniec koncov, to, čo definujeme, nie je kód, ale iba predbežné výpočty, takže simulátor je trochu nudný. Ale teraz si uvedomil, že prvý pokyn bol splnený a ak vylezieš na strom Zobrazenie I/O, do sekcie USART a pozri sa tam na bajt UBBRL, uvidíš, že tam už je nejaká hodnota! 0x33.

Urobte ešte jeden krok. Pozrite sa, ako sa zmení obsah iného registra. Prejdite si ich teda všetky, dávajte pozor na to, že všetky zadané bity sú nastavené tak, ako som vám povedal, a sú nastavené súčasne pre celý bajt. Veci nepôjdu ďalej ako Návrat – program sa skončil.

Otvorenie
Teraz resetujte simuláciu na nulu. Kliknite tam Obnoviť (Shift+F5). Otvorte rozobraný zoznam, teraz uvidíte, čo sa v ovládači skutočne deje. Zobraziť -> Disassembler. A nie YYAAAA!!! Assembler!!! STRAŠNÉ!!! ALE MUSÍTE. Aby ste neskôr, keď sa niečo pokazí, nezhlúpli v kóde a nepýtali sa na fórach chabé otázky, ale okamžite sa pustili do drobov a pozreli sa, kde máte zástrčku. Nie je tam nič strašné.

Najprv budú topy zo série:

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 Jump +00000002: 940C0034 JMP 0x00000034 Jump +00000004: 940C0034 JMP 0x00000034 Jump +00000006: 940C0034 JMP 0x00000034 Jump +00000008: 940C0034 JMP 0x00000034 Jump +0000000A: 940C0034 JMP 0x00000034 Jump +0000000C: 940C0034 JMP 0x00000034 Jump + 0000000E: 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00000014: 940C0034 JMP 0x00000034 Jump +00000016: 940C0034 JMP 0x00000034 Jump +00000018: 940C0034 JMP 0x00000034 Jump +0000001A: 940C0034 JMP 0x00000034 Jump +0000001C : 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00000022: 940C0034 JMP 0x00000034 Jump +00000024: 940C0034 JMP 0x00000034 Jump +00000026: 940C0034 JMP 0x00000034 Jump +00000028: 940C0034 JMP 0x00000034 Jump

00000000: 940C002A JMP 0x0000002A Jump +00000002: 940C0034 JMP 0x00000034 Jump +00000004: 940C0034 JMP 0x00000034 Jump +00000006: 940C0034 JMP 0x00000034 Jump +00000008: 940C0034 JMP 0x00000034 Jump +0000000A: 940C0034 JMP 0x00000034 Jump +0000000C: 940C0034 JMP 0x00000034 Jump +0000000E : 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00000014: 940C0034 JMP 0x00000034 Jump +00000016: 940C0034 JMP 0x00000034 Jump +00000018: 940C0034 JMP 0x00000034 Jump +0000001A: 940C0034 JMP 0x00000034 Jump +0000001C: 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00000022: 940C0034 JMP 0x00000034 Jump +00000024: 940C0034 JMP 0x00000034 Jump +00000026: 940C0034 JMP 0x00000034 Jump +00000028: 940C0034 JMP 0x00000034 Jump

Toto je tabuľka vektorov prerušení. Vrátime sa k tomu neskôr, zatiaľ sa len pozrite a zapamätajte si, že tam je. Prvý stĺpec je adresa flash bunky, v ktorej sa príkaz nachádza, druhý je kód príkazu, tretí mnemotechnická pomôcka príkazu, rovnaká inštrukcia assembleru, tretí operandy príkazu. A automatický komentár.
Takže, ak sa pozriete, potom existujú nepretržité prechody. A príkazový kód JMP má štyri bajty, obsahuje spätne zapísanú adresu skoku - nízky bajt na nízkej adrese a kód príkazu skoku 940C

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

Zapíšte túto nulu na adresu 0x3F. Ak sa pozriete do stĺpca zobrazenia I/O, uvidíte, že adresa 0x3F je adresa registra SREG - príznakového registra kontroléra. Tie. resetujeme SREG, aby sa program spustil pri nulových podmienkach.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Okamžité načítanie +0000002D: E0D4 LDI R29,0x04 Okamžité načítanie +0000002E: BFDE OUT 0x3E,R29 Out to I/O umiestnenie +0000002F: BFCD OUT2,00x umiestnenie BFCD IR29

0000002C: E5CF LDI R28,0x5F Okamžité načítanie +0000002D: E0D4 LDI R29,0x04 Okamžité načítanie +0000002E: BFDE OUT 0x3E,R29 Out to I/O umiestnenie +0000002F: BFCD OUT22F umiestnenie BFCD IR29,0x04

Načítava sa ukazovateľ zásobníka. Registre nemôžete načítať priamo do I/O, iba cez prechodný register. Preto najprv LDI do stredného a potom odtiaľ OUT do I / O. Tiež vám poviem viac o stohu. Medzitým vedzte, že toto je taká dynamická pamäťová oblasť, ktorá visí na konci RAM a ukladá do seba adresy a medzipremenné. Teraz sme naznačili, odkiaľ bude zásobník začínať.

00000032: 940C0041 JMP 0x00000041 Skok

Skok na saaaaamy koniec programu a tam máme prerušenia vypnuté a pevne sa cyklujúce:

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

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

Je to v prípade nepredvídaných okolností, ako je napríklad odchod z hlavnej funkcie. Regulátor môže byť z takejto slučky vyvedený buď hardvérovým resetom, alebo pravdepodobnejšie resetom z watchdogu. No, alebo, ako som povedal vyššie, opravte tieto miesta v hex editore a jazdite, kam chceme. Všimnite si tiež, že existujú dva typy skokov JMP a RJMP, prvý je priamy skok na adresu. Zaberá štyri bajty a dokáže urobiť priamy skok cez celú oblasť pamäte. Druhý typ prechodu – RJMP – je relatívny. Jeho príkaz trvá dva bajty, ale z aktuálnej pozície (adresy) skočí o 1024 krokov dopredu alebo dozadu. A jeho parametre označujú posun od aktuálneho bodu. Používa sa častejšie, tk. zaberá polovicu miesta v blesku a dlhé prechody sú potrebné len zriedka.

1 +00000034: 940C0000 JMP 0x00000000 Skok

00000034: 940C0000 JMP 0x00000000 Skok

A toto je skok na úplný začiatok kódu. Akýsi reštart. Tu môžete skontrolovať, či všetky vektory preskakujú. Z tohto záveru - ak teraz povolíte prerušenia (v predvolenom nastavení sú vypnuté) a máte prerušenie, ale neexistuje žiadna obsluha, dôjde k resetu softvéru - program sa hodí na úplný začiatok.

hlavná funkcia. Všetko je rovnaké, nedá sa to ani opísať. Pozrite sa do registrov, kde je zadané už vypočítané číslo. Preprocesor kompilátora skaly!!! Takže žiadne „magické“ čísla!

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

00000036: E383 LDI R24,0x33 Okamžité načítanie +00000037: B989 OUT 0x09,R24 Out to I/O umiestnenie 15: UBRRH = HI(bauddivider); +00000038: BC10 OUT 0x20,R1 Out to I/O umiestnenie 16: UCSRA = 0; +00000039: B81B OUT 0x0B,R1 Výstup na I/O umiestnenie 17: UCSRB = 1<

A tu je zásek:

1 2 3 +0000003E: E080 LDI R24,0x00 Okamžité načítanie +0000003F: E090 LDI R25,0x00 Okamžité načítanie +00000040: 9508 Návrat podprogramu RET

0000003E: E080 LDI R24,0x00 Okamžité načítanie +0000003F: E090 LDI R25,0x00 Okamžité načítanie +00000040: 9508 Návrat podprogramu RET

Otázkou je, prečo kompilátor pridáva takéto vrcholy? A toto nie je nič iné ako Return 0, potom sme definovali funkciu ako int main (void), takže sme posrali ďalšie štyri bajty, nechápem čo :) A ak urobíte void main (void), zostane len RET, ale objaví sa varovanie, že vraj naša hlavná funkcia nič nevracia. Vo všeobecnosti rob, čo chceš :)

ťažké? Zdá sa, že nie. Kliknite na spustenie krok za krokom v režime disassemblera a uvidíte, ako procesor vykonáva jednotlivé inštrukcie, čo sa deje s registrami. Ako prebieha pohyb po príkazoch a záverečné zacyklenie.

Pokračovanie o pár dní...

Offtop:
Alexej78 Vytvoril som plugin pre firefox, ktorý uľahčuje navigáciu na mojej stránke a fóre.
Diskusia a stiahnutie,

Existujú rôzne programovacie jazyky pre mikrokontroléry AVR, ale assembler a C sú možno najvhodnejšie, pretože tieto jazyky poskytujú najlepšiu implementáciu všetkých potrebných schopností na ovládanie hardvéru mikrokontroléra.

Assembler je nízkoúrovňový programovací jazyk, ktorý využíva sadu priamych inštrukcií mikrokontroléra. Vytvorenie programu v tomto jazyku si vyžaduje dobrú znalosť príkazového systému programovateľného čipu a dostatok času na vývoj programu. Assembler stráca na C z hľadiska rýchlosti a pohodlia vývoja programu, ale má viditeľné výhody vo veľkosti konečného spustiteľného kódu, a teda v rýchlosti jeho vykonávania.

C vám umožňuje vytvárať programy s oveľa väčším komfortom a poskytuje vývojárom všetky výhody jazyka na vysokej úrovni.
Ešte raz treba poznamenať, že architektúra a príkazový systém AVR bol vytvorený za priamej účasti vývojárov kompilátora C a zohľadňuje vlastnosti tohto jazyka. Kompilácia zdrojového kódu napísaného v C je rýchla a vytvára kompaktný a efektívny kód.

Hlavné výhody jazyka C oproti assembleru sú: vysoká rýchlosť vývoja programu; všestrannosť, ktorá nevyžaduje dôkladné štúdium architektúry mikrokontroléra; lepšia dokumentovateľnosť a čitateľnosť algoritmu; dostupnosť knižníc funkcií; podpora výpočtov s pohyblivou rádovou čiarkou.

Jazyk C harmonicky spája možnosti nízkoúrovňového programovania s vlastnosťami vysokoúrovňového jazyka. Nízkoúrovňová programovacia schopnosť uľahčuje ovládanie priamo na hardvéri a vlastnosti vysokoúrovňového jazyka umožňujú vytvárať ľahko čitateľný a modifikovateľný programový kód. Okrem toho takmer všetky kompilátory C majú schopnosť používať vložky assembleru na písanie kritických častí programu z hľadiska času vykonávania a zdrojov.

Jedným slovom, C je najvhodnejší jazyk pre začiatočníkov, aby sa zoznámili s mikrokontrolérmi AVR, ako aj pre serióznych vývojárov.

Kompilátory sa používajú na konverziu zdrojového kódu programu do súboru firmvéru mikrokontroléra.

Atmel poskytuje výkonný kompilátor assembleru, ktorý je súčasťou vývojového prostredia Atmel Studio na báze Windows. Spolu s kompilátorom obsahuje vývojové prostredie debugger a emulátor.
Atmel Studio je úplne zadarmo a dostupné na webovej stránke Atmel.

V súčasnosti existuje pomerne veľa kompilátorov C pre AVR. Najvýkonnejším z nich je kompilátor IAR Systems zo Štokholmu. Práve jej zamestnanci sa v polovici 90. rokov podieľali na vývoji veliteľského systému AVR. IAR C Compiler má rozsiahle možnosti optimalizácie kódu a prichádza ako súčasť integrovaného vývojového prostredia IAR Embedded Workbench (EWB), ktoré zahŕňa aj kompilátor assembleru, linker, správcu projektov a knižníc a debugger. Cena plnej verzie balíka je 2820 EUR. Na stránke spoločnosti si môžete stiahnuť bezplatnú skúšobnú verziu na 30 dní alebo neobmedzenú verziu s limitom veľkosti kódu 4 KB.

Americká spoločnosť Image Craft z Palo Alto v Kalifornii vyrába kompilátor pre jazyk C, ktorý si získal pomerne veľkú popularitu. JumpStart C pre AVR má prijateľnú optimalizáciu kódu a nie je príliš drahý (od 50 do 499 USD v závislosti od verzie). Demo verzia JumpStart C pre AVR je plne funkčná po dobu 45 dní.

Nemenej obľubu si získal rumunský Code Vision AVR C Compiler, cena plnej verzie tohto kompilátora je pomerne nízka a dosahuje 150 EUR. Kompilátor je dodávaný s integrovaným vývojovým prostredím, ktoré okrem štandardných funkcií obsahuje pomerne zaujímavú funkciu – CodeWizardAVR Automatic Program Generator. Prítomnosť sériového terminálu vo vývojovom prostredí umožňuje ladenie programov pomocou sériového portu mikrokontroléra. Vývojári si môžu stiahnuť bezplatnú skúšobnú verziu s limitom veľkosti kódu 4 KB a zakázaným ukladaním vygenerovaného zdrojového kódu C.

MikroElektronika so sídlom v srbskom meste Belehrad vyrába celú rodinu kompilátorov pre mikrokontroléry AVR. Kompilátor C s názvom mikroC PRO pre AVR stojí 249 dolárov. V ponuke sú aj mikroBasic a mikroPascal za rovnakú cenu. Na stránke vývojára sú ukážky s limitom veľkosti kódu 4096 bajtov. Výhodou tejto rodiny kompilátorov je jednotná platforma a jednotná ideológia, ktorá dokáže zabezpečiť jednoduchý prechod nielen medzi jazykmi, ale aj medzi mikrokontrolérmi (existujú verzie kompilátorov pre PIC, STM32, 8051 ...).

Integrované vývojové prostredie sa stalo skutočne ikonickým. Obsahuje výkonné kompilátory jazyka C a assembler, programátor AVRDUDE, debugger, simulátor a mnoho ďalších podporných programov a pomôcok. WinAVR sa dokonale integruje s vývojovým prostredím Atmel AVR Studio. Assembler je vo vstupnom kóde identický s assemblerom AVR Studio. Kompilátory jazyka C a assembler majú schopnosť vytvárať ladiace súbory vo formáte COFF, čo vám umožňuje používať nielen vstavané nástroje, ale aj používať výkonný simulátor AVR Studio. Ďalším dôležitým plusom je, že WinAVR je distribuovaný bezplatne bez obmedzení (výrobcovia podporujú GNU General Public License).

Stručne povedané, WinAVR je ideálnou voľbou pre tých, ktorí začínajú ovládať mikrokontroléry AVR. Práve toto vývojové prostredie je v tomto kurze považované za hlavné.

Bitové operácie sú založené na logických operáciách, ktorým sme sa už venovali vyššie. Hrajú kľúčovú úlohu pri programovaní mikrokontrolérov AVR a iných typov. Takmer žiadny program sa nezaobíde bez použitia bitových operácií. Doteraz sme sa im zámerne vyhýbali, aby sme uľahčili učenie programovania MK.

Vo všetkých predchádzajúcich článkoch sme naprogramovali iba I/O porty a nepoužili sme ďalšie vstavané uzly, ako sú časovače, analógovo-digitálne prevodníky, prerušenia a ďalšie interné zariadenia, bez ktorých MK stráca všetku svoju energiu.

Pred prechodom na zvládnutie vstavaných zariadení MK sa musíte naučiť ovládať alebo kontrolovať jednotlivé bity registrov AVR MK. Predtým sme vykonávali kontrolu alebo nastavovali bity celého registra naraz. Pozrime sa, aký je rozdiel, a potom pokračujte ďalej.

Bitové operácie

Najčastejšie sme ho používali pri programovaní mikrokontrolérov AVR, pretože je prehľadnejší v porovnaní s programátormi MK a je pre začínajúcich programátorov dobre zrozumiteľný. Napríklad potrebujeme nastaviť iba 3. bit portu D. Na to, ako už vieme, môžeme použiť nasledujúci binárny kód:

PORTD = 0b00001000;

Týmto príkazom však nastavíme 3. bit na jednotku a všetky ostatné (0, 1, 2, 4, 5, 6 a 7.) vynulujeme. A teraz si predstavme situáciu, že 6. a 7. číslica sú použité ako ADC vstupy a v tomto čase prichádza signál z nejakého zariadenia na zodpovedajúce výstupy MK a tieto signály resetujeme príkazom vyššie. Výsledkom je, že mikrokontrolér ich nevidí a verí, že signály neprišli. Preto by sme namiesto takéhoto príkazu mali použiť iný, ktorý by nastavil iba 3. bit na jednotku, pričom by neovplyvnil ostatné bity. Na tento účel sa zvyčajne používa nasledujúca bitová operácia:

PORT |= (1<<3);

Nižšie podrobne rozoberieme jeho syntax. A teraz ďalší príklad. Povedzme, že potrebujeme skontrolovať stav 3. bitu registra PIND, čím skontrolujeme stav tlačidla. Ak sa tento bit vynuluje, tak vieme, že je stlačené tlačidlo a následne sa vykoná príkazový kód, ktorý zodpovedá stavu stlačeného tlačidla. Predtým by sme použili nasledujúci zápis:

if (pind == 0b00000000)

(akýkoľvek kód)

Pomocou nej však nekontrolujeme ani jeden, - 3., ale všetky bity registra PIND naraz. Preto, aj keď sa stlačí tlačidlo a požadovaný bit sa vynuluje, ale v tom čase je prijatý signál na akomkoľvek inom pine D portu, zodpovedajúci bit sa nastaví na jednotku a podmienka v zátvorkách bude nepravdivá. V dôsledku toho sa kód v zložených zátvorkách nevykoná ani po stlačení tlačidla. Preto na kontrolu stavu jednotlivého 3. bitu registra PIND by sa mala použiť bitová operácia:

ak (~PIND & (1<<3))

(akýkoľvek kód)

Pre prácu s jednotlivými bitmi mikrokontroléra má vo svojom arzenáli programovací jazyk C, pomocou ktorého môžete meniť alebo kontrolovať stav jedného alebo viacerých jednotlivých bitov naraz.

Nastavenie jedného bitu

Na nastavenie jedného bitu, ako je port D, sa používa bitová operácia OR. To sme použili na začiatku článku.

PORTD = 0b00011100; // pôvodná hodnota

PORTD = PORTD | (jeden<<0); применяем побитовую ИЛИ

PORT |= (1<<0); // сокращенная форма записи

PORTD == 0b00011101; // výsledok

Tento príkaz nastaví bit na nulu a zvyšok ponechá nezmenený.

Napríklad nastavíme 6. bit portu D.

PORTD = 0b00011100; // počiatočný stav portu

PORT |= (1<<6); //

PORTD == 0b01011100; // výsledok

Ak chcete zapísať jeden až niekoľko samostatných bitov naraz, napríklad nula, šiesty a siedmy port B platí nasledujúci zápis.

PORTB = 0b00011100; // pôvodná hodnota

PORTB |= (1<<0) | (1<<6) | (1<<7); //

PORTB == 0b1011101; // výsledok

Nulovanie (nulovanie) jednotlivých bitov

Na resetovanie jedného bitu sa naraz použijú tri predtým diskutované príkazy: .

Vynulujme 3. bit registra PORTC a zvyšok necháme nezmenený.

PORTC = 0b00011100;

PORTC &= ~(1<<3);

PORTC == 0b00010100;

Vykonajte podobné akcie pre 2. a 4. číslicu:

PORTC = 0b00111110;

PORTC &= ~((1<<2) | (1<<4));

PORTC == 0b00101010;

Prepínanie rytmu

Okrem nastavenia a resetovania sa používa aj užitočný príkaz, ktorý prepne jeden bit do opačného stavu: jedna na nulu a naopak. Táto logická operácia je široko používaná pri konštrukcii rôznych svetelných efektov, ako je napríklad novoročná girlanda. Zoberme si príklad PORTA

PORTA = 0b00011111;

PORTA ^= (1<<2);

PORTA == 0b00011011;

Zmeňte stav nula, druhého a šiesteho bitu:

PORTA = 0b00011111;

PORTA ^= (1<<0) | (1<<2) | (1<<6);

PORTA == 0b01011010;

Kontrola stavu jednotlivého bitu. Pripomínam, že kontrola (na rozdiel od zápisu) I/O portu sa vykonáva načítaním údajov z registra PIN.

Najbežnejší test sa vykonáva jedným z dvoch príkazov cyklu: if a while. S týmito operátormi sme sa už oboznámili skôr.

Kontrola vybitia na prítomnosť logickej nuly (reset) s ak

if (0==(PIND & (1<<3)))

Ak sa vymaže tretí bit portu D, vykoná sa Code1. V opačnom prípade sa vykoná Code2.

Podobné akcie sa vykonávajú s a v tejto forme záznamu:

ak (~PIND & (1<<3))

Kontrola výboja na prítomnosť logickej jednotky (nastavenia) s ak

if (0 != (PIND & (1<<3)))

ak (PIND & (1<<3))

Vyššie uvedené dve slučky fungujú podobne, ale kvôli flexibilite programovacieho jazyka C môžu byť napísané inak. Operácia != znamená nerovná sa. Ak je nastavený tretí bit PD I/O portu (jeden), vykoná sa Code1, ak nie, Code2.

Čaká sa na trochu reset s zatiaľ čo

zatiaľ čo (PIND & (1<<5))

Kód1 sa bude vykonávať, pokiaľ je nastavený 5. bit registra PIND. Resetovaním sa spustí vykonávanie Code2.

Čaká sa na nastavenie bitu zatiaľ čo

Tu vám syntax jazyka C umožňuje písať kód dvoma najbežnejšími spôsobmi. V praxi sa používajú oba typy záznamu.