Mikrokontrollerite programmeerimise järjekord avr. avr mikrokontrolleri programmeerimine

Tere päevast, kallid raadioamatöörid!
Tere tulemast saidile ""

Mis on mikrokontroller ja miks seda vaja on. Vaatame selle määratlust:

- elektroonikaseadmete juhtimiseks mõeldud mikroskeem või muul viisil - lihtne arvuti (mikroarvuti), mis on võimeline täitma lihtsaid ülesandeid.

See tähendab, et tegelikult on mikrokontroller seade, mis võimaldab meil oma ideid (isegi hullumeelseid) ellu viia, kuid loomulikult nende võimaluste piires. Ja mis kõige tähtsam, idee realiseerimine ei saavutata keerukate elektrooniliste struktuuride loomisega, vaid põhimõtteliselt ainult meie mõtte jõul (kas soovite saada võluriks?).
Raadioamatööride seas on kõige populaarsemad kahte tüüpi mikrokontrollerid:
PIC- Mikrokiibi tehnoloogia
AVR- Atmelilt

Tahaksin teha väikese kõrvalepõike ja täpsustada üht oma seisukohta. Ma ei hakka arutlema selle või selle tüüpi mikrokontrollerite, selle või selle tarkvara ja üldiselt kõige mikrokontrolleritega seonduva eeliste üle, et midagi nõu anda ja veelgi enam, lugejatele peale suruda. See kõik on maitse, isiklike eelistuste ja teie lõppeesmärkide küsimus mikrokontrollerite õppimisel. Noh, kuna "suurust ei saa omaks võtta", viin läbi kogu oma edasise jutustamise seoses AVR-i mikrokontrolleritega ja mitte väga levinud, kuid minu lemmikprogrammiga "Algoritmi koostaja". Erinevat tüüpi mikrokontrolleritel, programmidel on muidugi erinevusi, kuid neil on ka palju ühist. Ja õpime mikrokontrollerite maailma tundma nii, et hiljem saaks saadud teadmisi probleemideta rakendada PIC-ide ja mis tahes tarkvara jaoks. Ja tuletan veel kord meelde, et see artiklisari on minu katse aidata neid, kes esimest korda mikrokontrollerite olemasolust kuulsid ja tahavad aru saada, kuidas nendega töötada.

Mida on vaja mikrokontrolleritega töötamiseks õppida? Tooksin välja mõned minu arvates peamised tingimused:
1. Soov ja sihikindlus .
Siin on kõik väga lihtne: soov on - kõik saab korda. Ja visad tahtmine on üldiselt super asi.
2. Mikrokontrolleri seadme tundmine.
Sügavad teadmised pole siin olulised (ja võib-olla pole üldse vajalikud), kuid on vaja teada, mis on mikrokontrolleri pardal. Vaid teades, millest mikrokontroller koosneb, millised seadmed sellel on, nende võimalused, kuidas need töötavad – alles siis saame mikrokontrolleri võimalusi täiel määral kasutada.
3. Programmeerimiskeele ja mikrokontrolleri juhtimiskäskude tundmine.
Kuidas mikrokontroller töötab, milliseid ülesandeid sellele määrate ja kuidas see neid täidab, määrab sellesse manustatud programm - programm, mille te ise mikrokontrolleri jaoks koostate. Ja me peatume sellel punktil üksikasjalikumalt, et kaaluda probleeme, mis võivad tulevikus tekkida.

Programm(tõlkes tähendab see sõna "retsepti") - eelseisvate sündmuste või toimingute esialgne kirjeldus.

Näiteks tahame, et mikrokontroller vilguks LED-i. Lihtne ülesanne, kuid sellegipoolest, et mikrokontroller saaks selle ülesande täita, peame kõigepealt samm-sammult kirjeldama kõiki mikrokontrolleri toiminguid, kirjutama programmi, mida see peab täitma, et saada vajalikku tulemust - vilkuvat LED-i. . Midagi sellist:
♦ Süütage LED:
- seadistage väljund, millega LED on ühendatud, töötama teabe väljundiga
- rakendage sellele tihvtile loogilist taset, mis võimaldab teil LED-i valgustada
♦ Oodake veidi:
- minge alamprogrammi juurde, mis moodustab pausi (mida tuleb ka "närida")
- pärast pausi alamprogrammi lõpetamist pöörduge tagasi põhiprogrammi
♦ Lülitage LED välja:
- rakendage väljundile loogilist taset, kustub LED
jne.
terminiga Programm teine ​​termin on lahutamatult seotud - Algoritm(nagu hunt ja jänes, Tom ja Jerry).

Algoritm- juhiste komplekt, mis kirjeldab soovitud tulemuse saavutamise protseduuri.

Kui programmis oleme kõige üksikasjalikumalt tegevusi ette kirjutama mikrokontroller, siis algoritmis me määrata tegevussuund mikrokontroller, mille põhjal koostame siis programmi. Sarnaselt ülaltoodud näitele:
♦ Süütage LED
♦ Oodake veidi
♦ Lülitage LED välja
jne.
Seega Algoritm on programmi eelkäija. Ja mida hoolikamalt ja läbimõeldumalt algoritm luuakse, seda lihtsam on programmi koostada.

Kokkuvõttes on mikrokontrolleri programm mikrokontrolleri toimingute jada käskude ja juhiste komplekti kujul, mida see peab meie eesmärkide saavutamiseks täitma.

Mikrokontrolleri käsud näevad välja nagu ühtede ja nullide komplekt:
00110101 011000100
nn - käsukoodid, ja käsukoodid on keel, millest mikrokontroller aru saab. Ja selleks, et tõlkida meie algoritm vene keelest mikrokontrolleri keelde - nendesse nullide ja ühtede komplektidesse, on olemas spetsiaalsed programmid.
Need programmid võimaldavad kirjeldada mikrokontrolleri tööjärjekorda meile enam-vähem arusaadavas keeles ning seejärel tõlkida see järjekord mikrokontrollerile arusaadavasse keelde, mille tulemuseks on nn. masina kood- käskude ja juhiste jada (nullid ja ühed), millest mikrokontroller ainult aru saab. Programmeerija kirjutatud programmi teksti nimetatakse lähtekood. Programm tõlgitakse programmeerimiskeelest (lähtekoodist) mikrokontrolleri keelde (masinakood) tõlkijad. Tõlkija teisendab programmi teksti masinkoodideks, mis seejärel kirjutatakse mikrokontrolleri mällu.
Sellistes programmides kirjeldab mikrokontrolleri tööjärjekorda spetsiaalne keel - programmeerimiskeel. Programmeerimiskeel erineb meie inimkeelest. Kui meie suhtluskeel on eelkõige info vahetamiseks, siis:

Programmeerimiskeel - see on käskude, juhiste edastamise viis, selge tegevusjuhend mikrokontrolleri jaoks.

Programmeerimiskeeli on palju ja need võib jagada kahte tüüpi:
madala taseme programmeerimiskeeled
kõrgetasemelised programmeerimiskeeled
Mis vahe on. Ja need erinevad üksteisest mikrokontrolleri läheduse poolest.
Mikroprotsessortehnoloogia tekkimise koidikul kirjutati programmid masinkoodidesse, see tähendab, et kogu töö algoritm kirjutati järjestikku nullide ja ühtede kujul. Programm nägi välja selline:

01000110
10010011
01010010

On ebatõenäoline, et keegi suudab sellist kahe numbri kombinatsioonide komplekti välja mõelda ja esimeste programmeerijate töö oli väga vaevarikas. Et oma elu lihtsamaks muuta, hakkasid programmeerijad looma esimesi programmeerimiskeeli. Niisiis, mida lähemal on programmeerimiskeel sellisele nullide ja ühtede komplektile, seda „madalama tasemega” see on ja mida kaugemal neist, seda rohkem on „kõrge tase”.
Levinumad mikrokontrollerite programmeerimiskeeled:
- madalal tasemel keel - komplekteerija
– kõrgetasemeline keel – C (Ci)
Vaatame näidet nende erinevusest (need näited on abstraktsed).
Oletame, et peame liitma kaks numbrit: 25 ja 35.
Omakoodis võib see käsk välja näha järgmine:
00000101 1101001
Madala tasemega keeles:
ADD Rd, Rr
Kõrgetasemelises keeles:
25+35
Madala ja kõrgetasemeliste keelte erinevus on palja silmaga nähtav, kommentaarid, nagu öeldakse, on üleliigsed.
Kuid süvenegem nendesse näidetesse sügavamale. Masinkoodi näidet me ei analüüsi, kuna see on identne assembleris oleva näitega. Assembly juhised on põhiolemuselt samad masinkoodid (käsud), millele on lihtsalt määratud tähtede lühendid, et mitte eksida nullide ja ühtede vahele. Kasutades käsku ADD Rd, Rr assembler, panime mikrokontrolleri liitma kaks leitud numbrit (ja selleks peame need esmalt sinna kirjutama) – esimese Rd-sse, teise Rr-i ja lisama liitmise tulemuse Rd. Nagu näete, seadsime mikrokontrollerile väga konkreetse ülesande: kust seda saada, mida sellega teha ja kuhu tulemus panna. Sel juhul töötame otse mikrokontrolleriga.
Kõrgetasemelise keele käsk: 25+35 , meile tuttav, silmailu pakkuv matemaatiline tähistus. Kuid sel juhul ei tööta me otse mikrokontrolleriga, vaid paneme talle lihtsalt ülesandeks liita kaks numbrit. Tulemus ja toimingute jada on sel juhul samad, mis assemblerkäsu täitmisel: kõigepealt kirjutatakse need kaks numbrit kuhugi, seejärel liidetakse ja tulemus paigutatakse kuhugi.
Ja siin peitub peamine erinevus kõrgetasemeliste ja madalate keelte vahel. Kui Assembleris juhime kogu protsessi (meeldib see meile või mitte): me teame, kus need kaks numbrit on kirjutatud, ja teame, kus on tulemus, siis kõrgkeeles me protsessi ei juhi. Programm ise otsustab, kuhu numbrid ette kirjutada ja kuhu tulemus asetada. Enamikul juhtudel ei pea me seda teadma, sest meie jaoks on peamine tulemus väljundis number 60. Tänu sellele on kõrgetasemelistes keeltes programmid loetavamad, silmale meeldivamad ja väiksema suurusega – lõppude lõpuks ei pea me “kõikidesse aukudesse ronima” ja värvima iga mikrokontrolleri sammu, programmi teeb seda hiljem meie eest, kui ta seda kompileerib – tõlgib selle masinkoodideks. Kuid sellel on ka varjukülg. Kaks identset algoritmi, mis on kirjutatud assembleris ja C-s, on pärast nende masinkoodideks teisendamist erineva suurusega: assembleris kirjutatud programm on 20-40% lühem kui C-ga kirjutatud programm – kurat teab, kuhu C suundub. saavutame soovitud tulemuse. Ja on juhtumeid, kui kõrgetasemelist keelt ei usaldata ja C-programmi sisestavad nad Assembleris kirjutatud koodi.
Professionaalsed programmeerijad valdavad reeglina mitut programmeerimiskeelt (või töötavad meeskonnas, kuhu kuuluvad eri keelte spetsialistid), ühendades nende omadused ja eelised loovalt ühes programmis. Noh, meie, amatöörid, peame oskama vähemalt ühte keelt (alustuseks) ja alustama (ja ma olen selles kindlalt veendunud ja keegi ei veena mind) madala tasemega keelest - assambleest.

Noh, ma arvan, ja siin on meile kõik selge - peate õppima programmeerimiskeelt, teistmoodi - mitte mingil juhul.

Käsud ja juhised mikrokontrolleri juhtimiseks.
AVR-i mikrokontrolleritel on rohkem kui 130 erinevat käsku, mis võimaldavad realiseerida kõiki sellega kaasnevaid võimalusi. Kuid ütlen kohe, et vähesed amatöörid teavad neid kõiki, rääkimata nende kõigi kasutamisest. Tavaliselt on amatöörpraktikas piisavalt teadmisi ja pooled võistkonnad või isegi vähem. Aga sa pead õppima käske. Mida rohkem käske teate, seda keerukamad (selle sõna heas mõttes) ja elegantsemad on programmid.

Aritmeetiline loogikaüksus ja mälukorraldus – programmimälu, andmemälu, püsimälu



Selles avr-i õpetuses püüdsin kirjeldada kõiki kõige elementaarsemaid asju algajatele mikrokontrollerite programmeerimiseks. avr. Kõik näited on üles ehitatud mikrokontrollerile atmega8. See tähendab, et kõigi õppetundide kordamiseks vajate ainult ühte MK-d. Elektroonilise vooluahela emulaatorina kasutatakse Proteust - minu arvates parim valik algajatele. Kõikide näidete programmid on kirjutatud avr CodeVision AVR C-kompilaatoris. Miks mitte mõnes assembleris? Kuna algaja on juba infoga laetud ja kahte arvu korrutav programm võtab assembleris umbes sada rida ning nad kasutavad keerulistes paksus projektis C. CodeVision AVR kompilaator on teritatud atmeli mikrokontrolleritele, omab mugavat koodigeneraatorit, a. hea liides ja otse sellest saab mikrokontrolleri abil vilkuda.

See õpetus näitab ja selgitab lihtsate näidetega, kuidas:

  • Alustage mikrokontrollerite programmeerimist, kust alustada, mida selleks vaja on.
  • Milliseid programme kasutada avr-i püsivara kirjutamiseks, arvutis koodi simuleerimiseks ja silumiseks,
  • Millised välisseadmed on MK-s, kuidas neid oma programmi abil juhtida
  • Kuidas kirjutada valmis püsivara mikrokontrollerisse ja kuidas seda siluda
  • Kuidas teha oma seadmele PCB
Esimeste sammude tegemiseks MK programmeerimise suunas on teil vaja ainult kahte programmi:
  • Proteus on emulaatorprogramm (saate selles vooluringi välja töötada ilma tõelist jootmist kasutamata ja seejärel meie programmi sellel vooluringil testida). Kõigepealt käivitame kõik projektid Proteuses ja siis saame juba päris seadme jootma.
  • CodeVisionAVR on C-programmeerimiskeele kompilaator AVR-i jaoks. Selles töötame välja programmid mikrokontrolleri jaoks ja sealt saab otse vilgutada tõelist MK-d.
Pärast Proteuse installimist käivitage see
Ta pakub meile, et näeme temaga kaasas käivaid projekte, me keeldume viisakalt. Nüüd loome selles kõige lihtsama vooluringi. Selleks klõpsake ikooni visuaalselt, et midagi ei juhtu. Nüüd peate klõpsama väikesel tähel R (vali raamatukogust) komponentide loendi paneelil avaneb komponentide valimise aken
sisestage maski väljale komponendi nimi, mida soovime teegist leida. Näiteks peame lisama mega8 mikrokontrolleri
tulemuste loendis torka mega8 peale ja vajuta nuppu Okei. Meil on komponentide loendis mega8 mikrokontroller
Seega lisame komponentide loendisse veel ühe takisti, sisestades maski väljale sõna res ja LED juhitud

Osade paigutamiseks diagrammile klõpsake detailil, seejärel klõpsake diagrammi väljal, valige komponendi asukoht ja klõpsake uuesti. Vasakpoolsele vooluringile maanduse või ühise miinuse lisamiseks klõpsake "Terminal" ja valige Ground. Seega, lisades kõik komponendid ja ühendades need, saame sellise lihtsa vooluringi
Kõik, nüüd on meie esimene skeem valmis! Aga te võite küsida, mida ta teha saab? Aga ei midagi. Mitte midagi, sest selleks, et mikrokontroller töötaks, on vaja sellele programm kirjutada. Programm on juhiste loend, mida mikrokontroller täidab. Vajame mikrokontrollerit jalale paigaldamiseks PC0 loogika 0 (0 volti) ja loogika 1 (5 volti).

Programmi kirjutamine mikrokontrollerile

Kirjutame programmi C-keeles CodeVisionAVR kompilaatori abil. Pärast CV käivitamist küsib see meilt, mida me tahame luua: allikat või projekti Valime viimase ja vajutame nuppu OK. Järgmisena palutakse meil käivitada CVAVR CodeWizard (see on algaja jaoks hindamatu tööriist, kuna see võib luua programmi peamise skeleti) vali Jah
Viisard käivitub, kui vahekaart Chip on aktiivne, siin saame valida oma MK mudeli - see on mega8, ja sageduse, millega MK töötab (vaikimisi on mega8 seatud 1 megahertsile), nii et määrame kõik nii, nagu näidatud ülaltoodud ekraanipilt. Minge vahekaardile Ports
Atmega8 mikrokontrolleril on 3 porti: Port C, Port D, Port B. Igal pordil on 8 kontakti. Pordi tihvtid võivad olla kahes olekus:
  • Väljund
DDRx.y registri abil saame määrata viigu sisendiks või väljundiks. Kui sisse
  • DDRx.y = 0 - väljund töötab nagu SISSEPÄÄS
  • DDRx.y = 1 pin töötab VÄLJUND
Kui viik on konfigureeritud väljundina, saame selle seada loogikale 1 (+5 volti) ja loogikale 0 (0 volti). Seda tehakse PORTx.y registrisse kirjutades. Järgmisena käsitletakse üksikasjalikult sisend-väljundporte. Ja nüüd seadsime kõik nii, nagu on näidatud ekraanipildil, ja klõpsake nuppu Fail-> Loo, salvesta ja välju. Järgmisena pakub CodeWizard meile projekti salvestamist, salvestame selle ja vaatame koodi:

#kaasa //teek ajaviivituste loomiseks void main(void) ( PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x01; // tee PC0 jala väljundiks PORTD=0x00; DDRD=0x00; // Timer/Counter 0 lähtestamine TCCR0=0x00; TCNT0=0x00; // Taimer/loendur 1 lähtestamine TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0xCR00; OCR1L=0xCR01A00; OxAL01AHx; ; OCR1BL=0x00; // Taimer/loendur 2 lähtestamine ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // Välise katkestuse lähtestamine MCUCR=0x00; // Taimer(id)/loendur(id) ) Katkestuse(te) lähtestamine TIMSK=0x00; // Analoogkomparaatori lähtestamine ACSR=0x80; SFIOR=0x00; samas (1) ( ); )


Kõik siin võib teile tunduda hirmutav ja harjumatu, kuid tegelikult pole kõik nii. Koodi saab lihtsustada, visates välja nende MK välisseadmete lähtestamise, mida me ei kasuta. Pärast lihtsustamist näeb see välja järgmine:

#kaasa //teek mikrokontrolleriga töötamiseks mega8 #include //teek ajaviivituste loomiseks void main(void) ( DDRC=0x01; /* muudab PC0 jala väljundkirje 0x01 tunduda võõras ja see on vaid number 1 kuueteistkümnendsüsteemis, see rida võrdub 0b00000001 kahendarvuna, siis ma kirjutan täpselt nii. */ samas (1) ( ); )


Asjad on hästi. Kuid selleks, et LED vilkuks, peame muutma PC0 jala loogikataset. Selleks lisage põhitsüklile paar rida:

#kaasa //teek mikrokontrolleriga töötamiseks mega8 #include //teek ajaviivituste loomiseks void main(void) ( DDRC=0x01; /* muudab PC0 jala väljundkirje 0x01 tunduda võõras ja see on vaid number 1 kuueteistkümnendsüsteemis, see rida võrdub 0b00000001 binaarses, siis ma kirjutan täpselt nii.*/ while (1)//peaprogrammi tsükkel (// põhiprogrammi tsükli operaatori sulg avab PORTC.0=1; //sead pordi C 1 pin 0 delay_ms(500); //tee viivitus 500 millisekundiga PORTC.0=0; // määra port C 0 viiteks 0 delay_ms(500); // viivitus 500 millisekundit );// sulge operaatori sulg põhiprogrammi tsüklist )


Kõik, nüüd on kood valmis. Klõpsame ikooni Ehita kõik projektifailid, et oma programm kompileerida (tõlgida MK-protsessori juhistesse). Meie projektis asuvas kaustas Exe peaks ilmuma hex-laiendiga fail, see on meie MK püsivara fail. Meie püsivara Proteuse virtuaalsesse mikrokontrollerisse söötmiseks peate topeltklõpsama Proteuse mikrokontrolleri pilti. Ilmub selline aken
klõpsake väljal Program File kausta ikooni, valige hex - meie püsivara fail ja vajutage nuppu OK. Nüüd saame käivitada oma vooluringi simulatsiooni. Selleks klõpsake Proteuse akna vasakus alanurgas nuppu "Esita".

Olen rohkem kui korra-paar öelnud, et MK õpe peaks algama assemblerist. Sellele oli pühendatud terve saidi kursus (ehkki see pole eriti järjepidev, kuid järk-järgult kammistan selle adekvaatse väljanägemiseni). Jah, see on raske, tulemust ei tule esimesel päeval, aga sa õpid aru saama, mis sinu kontrolleris toimub. Saate teada, kuidas see töötab, ja mitte kopeerida teiste inimeste allikaid nagu ahv ja püüda mõista, miks see järsku lakkas töötamast. Lisaks on C-l palju lihtsam jamada rednecki koodiga, mis kõige ebasobivamal hetkel pikisilmi välja tuleb.

Kahjuks tahavad kõik kohe tulemusi. Seetõttu otsustasin minna teist teed – teha õpetus C-st, kuid koos tema aluspesu demonstreerimisega. Hea põimija programmeerija hoiab oma rauatükki alati kõvasti kõrne juurest kinni, takistades tal loata ühtki sammu astuda. Mis saab siis kõigepealt C-koodiks, siis milleks kompilaator sünnitas ja kuidas see kõik tegelikkuses töötab :)

Teisest küljest on C tugevaim külg koodi kaasaskantavus. Kui muidugi kõik õigesti kirjutada. Tööalgoritmide ja nende raudsete teostuste eraldamine projekti erinevatesse osadesse. Seejärel piisab algoritmi teisele MK-le ülekandmiseks ainult liidesekihi ümberkirjutamisest, kuhu on kirjutatud kogu juurdepääs riistvarale, ja jätta kogu töökood nii, nagu see on. Ja muidugi loetavus. Sishi lähtekoodi on ühe pilguga lihtsam mõista (kuigi .. näiteks mind ei huvita, mida peale nipsata - vähemalt si, vähemalt asm :)), aga jällegi, kui kõik on õigesti kirjutatud. Pööran ka nendele punktidele tähelepanu.

Eksperimentaalse rauatükina, millele lõviosa kõigist näidetest pannakse, saab minu silumisplaat.

Esimene C-programm AVR-i jaoks

Kompilaatori valimine ja keskkonna installimine
AVR-i jaoks on palju erinevaid C-kompilaatoreid:
Esiteks see IAR AVR C- peaaegu ühemõtteliselt tunnistatud parimaks AVR-i kompilaatoriks, tk. kontroller ise loodi Atmeli ja IAR-i spetsialistide tihedas koostöös. Aga kõige eest tuleb maksta. Ja see kompilaator pole mitte ainult kallis kommertstarkvara, vaid sellel on ka nii palju seadeid, et selle kompileerimiseks peate lihtsalt vaeva nägema. Mul polnud temaga tõesti sõprust, projekt mädanes kummaliste vigade tõttu linkimise etapis (hiljem sain teada, et see oli kõver pragu).

Teine läheb WinAVR GCC on võimas optimeeriv kompilaator. Täielikult avatud lähtekoodiga, platvormideülene, üldiselt kõik elurõõmud. See integreerub suurepäraselt ka AVR Studiosse, võimaldades teil seal siluda, mis on põrgulikult mugav. Üldiselt valisin selle.

Samuti on CodeVision AVR C on väga populaarne kompilaator. See sai populaarseks oma lihtsuse tõttu. Sellesse saate mõne minutiga töötava programmi - käivitamiskoodi viisard aitab sellele palju kaasa, tembeldades mis tahes uartide lähtestamise standardid. Ausalt öeldes suhtun ma temasse kuidagi kahtlustavalt - ükskord pidin selle kompilaatori kirjutatud programmi lahti võtma, tuli välja mingi puder ja mitte kood. Kohutav hulk tarbetuid žeste ja toiminguid, mille tulemuseks oli üsna suur hulk koodi ja aeglane jõudlus. Võib-olla oli aga viga algse püsivara kirjutaja DNA-s. Lisaks tahab ta raha. Mitte nii palju kui IAR, kuid märgatav. Ja demorežiimis võimaldab see kirjutada mitte rohkem kui 2 kb koodi.
Muidugi on mõra, aga kui varastada, siis IAR mõttes miljon :)

On olemas ka Image Craft AVR C ja MicroC mikroelektroonikast. Pole pidanud kumbagi kasutama, aga... SWG väga palju kiidusõnu mikropaskal, nad ütlevad, et kohutavalt mugav programmeerimiskeskkond ja raamatukogud. Ma arvan, et MicroC pole halvem, vaid ka tasuline.

Nagu ma ütlesin, valisin WinAVR kolmel põhjusel: tasuta, integreerub see AVR Studiosse ja selle jaoks on kirjutatud vaid hunnik valmiskoodi igaks juhuks.

Nii et laadige alla WinAVR koos ja AVR Studioga. Järgmisena installitakse esmalt stuudio, seejärel rullub ülalt üles WinAVR ja klammerdub pistikprogrammi kujul stuudio külge. Soovitan tungivalt panna WinAVR lühikesele teele, näiteks C:\WinAVR, nii väldite palju probleeme teedega.

Projekti loomine
Niisiis, stuudio on üles seatud, C kruvitud, on aeg proovida midagi programmeerida. Alustame lihtsast, kõige lihtsamast. Käivitage stuudio, valige seal AVR GCC kompilaatoriks uus projekt ja sisestage projekti nimi.

Tööala avaneb tühja *.c-failiga.

Nüüd ei tee haiget stuudio järjehoidjates teede kuvamise konfigureerimine. Selleks minge aadressile:
Menüü Tööriistad - Valikud - Üldine - Failikaardid ja valige ripploendist "Ainult failinimi". Vastasel juhul on see võimatu töötada - vahekaart sisaldab faili täielikku teed ja ekraanil pole rohkem kui kaks või kolm vahekaarti.

Projekti seadistamine
Üldiselt peetakse klassikaliseks make-faili loomist, milles kirjeldatakse kõiki sõltuvusi. Ja see on ilmselt õige. Aga minu jaoks, kes kasvasin üles täielikult integreeritud IDE-dega nagu uVision või AVR stuudio see lähenemine on sügavalt võõras. Seetõttu teen seda omal moel, stuudio kõigi vahenditega.

Klõpsake hammasratta nuppu.


Need on teie projekti sätted või pigem make-faili automaatse genereerimise sätted. Esimesel lehel peate lihtsalt sisestama sageduse, millega teie MK töötab. See oleneb kaitsmebitidest, seega eeldame, et sagedus on 8000000Hz.
Pöörake tähelepanu ka optimeerimisjoonele. Nüüd on olemas -Os on suuruse optimeerimine. Jätke see praegu nii, siis võite proovida selle parameetriga mängida. -O0 pole optimeerimine üldse.

Järgmine samm on teede seadistamine. Kõigepealt lisage sinna oma projekti kataloog – paned sinna kolmandate osapoolte teegid. Loendis kuvatakse tee ".\".

Make fail on loodud, saate seda vaadata oma projekti vaikekaustas, lihtsalt vaadake, mis seal on.


Praeguseks kõik. Klõpsake kõikjal OK ja minge allika juurde.

Probleemi sõnastamine
Puhas leht ahvatleb kehastama mingit kavalat ideed, kuna dioodi banaalne vilkumine enam ei lülitu sisse. Võtame kohe härjal sarvist ja rakendame ühenduse arvutiga – see on esimene asi, mida ma teen.

See töötab järgmiselt:
Kui seade saabub COM-porti (kood 0x31), lülitame dioodi sisse ja nulli saabumisel (kood 0x30) kustutame selle. Pealegi tehakse kõike katkestuste korral ja taustaülesandeks on teise dioodi vilkumine. Lihtne ja sisukas.

Skeemi kokkupanek
Peame ühendama USB-USART muunduri mooduli mikrokontrolleri USART tihvtidega. Selleks võtame kahest juhtmest koosneva hüppaja ja paneme need tihvtide külge risti. See tähendab, et ühendame kontrolleri Rx-i konverteri Tx-ga ja muunduri Tx-i kontrolleri Rx-ga.

Selgub, et lõpuks on see skeem:


Ma ei kaalu ülejäänud väljundite ühendamist, toiteallikat, lähtestamist, see on standardne

Kirjutame koodi

Ma teen kohe reservatsiooni, et ma ei süvene konkreetselt C-keele enda kirjeldusse. Selleks on lihtsalt kolossaalne kogus materjali, mis ulatub klassikalisest "C programmeerimiskeelest" alates K&R-st kuni erinevate käsiraamatuteni välja.

Üks selline meetod leiti minu varuks, kunagi õppisin seda keelt selle abil. Kõik on lühike, selge ja asjakohane. Ma kirjutan selle järk-järgult üles ja lohistan selle oma saidile.

Tõsi, kõiki peatükke pole sinna veel viidud, aga ma arvan, et mitte kauaks.

On ebatõenäoline, et ma seda paremini kirjeldan, seetõttu annan koolituse käigus Cishi keerukuse üksikasjaliku selgituse asemel lihtsalt otselingid selle juhendi üksikutele lehtedele.

Teekide lisamine.
Kõigepealt lisame vajalikud teegid ja päised koos definitsioonidega. Lõppude lõpuks on C universaalne keel ja tuleb selgitada, et töötame AVR-iga, nii et sisestage lähtekoodi rida:

1 #kaasa

#kaasa

See fail asub kaustas WinAVR ja see sisaldab kontrolleri kõigi registrite ja portide kirjeldust. Ja kõik on seal keeruline, viidates konkreetsele kontrollerile, mille kompilaator edastab tegema fail parameetris MCU ja selle muutuja põhjal ühendatakse teie projektiga päisefail kõigi selle kontrolleri portide ja registrite aadresside kirjeldusega. Kuidas! Ilma selleta saate ka, kuid siis ei saa te kasutada sümboolseid registrinimesid, nagu SREG või UDR, ja peate meeles pidama igaühe aadressi, näiteks "0xC1", ja see murrab teie pead.

Täpselt sama meeskond #kaasa<имя файла> võimaldab lisada projekti mis tahes tekstifaili sisu, näiteks funktsioonide kirjeldusega faili või muu koodijupi. Ja selleks, et direktiiv selle faili üles leiaks, märkisime oma projekti teed (WinAVR-i kataloog on seal juba vaikimisi registreeritud).

põhifunktsioon.
C-programmis on kõik funktsioonid. Neid saab pesastada ja üksteiselt kutsuda mis tahes järjekorras ja mitmel erineval viisil. Igal funktsioonil on kolm nõutavat parameetrit:

  • Tagastusväärtus, näiteks sin(x) tagastab x siinuse väärtuse. Nagu matemaatikas, lühidalt.
  • Ülekantud parameetrid, sama x.
  • Funktsiooni keha.

Kõik edastatud ja tagastatud väärtused peavad olenevalt andmetest olema teatud tüüpi.

Iga C programm peab sisaldama funktsiooni peamine põhiprogrammi sisenemispunktina, muidu pole see üldse C :). Peamise olemasolul kellegi teise miljoni faili allikas saate aru, et see on programmi põhiosa, millest kõik algab. Siin paneme paika:

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

int main(void) ( return 0; )

See on kõik, esimene lihtsam programm on kirjutatud, pole oluline, et see midagi ei tee, me oleme alles alustanud.

Vaatame, mis me tegime.
int on andmetüüp, mille põhifunktsioon tagastab.

Muidugi mikrokontrolleris peamine põhimõtteliselt ei saa midagi tagastada ja teoreetiliselt peaks ka olema tühine põhi(tühine), kuid GCC on algselt teritatud arvutis ja seal saab programm pärast valmimist selle väärtuse operatsioonisüsteemile tagastada. Seega GCC sisse tühine põhi(tühine) vannub Hoiatus.

See pole viga, see töötab, aga mulle ei meeldi hoiatused.

tühine seda tüüpi andmeid me antud juhul funktsioonile edastame peamine ei suuda ka midagi vastu võtta väljastpoolt, poeet tühine- tühi. Tükki kasutatakse siis, kui midagi pole vaja edasi anda ega tagastada.

Siin on need { } curly brackets on programmiplokk, antud juhul funktsiooni keha peamine, asub kood seal.

tagasi- see on tagastatav väärtus, mille põhifunktsioon lõpetamisel annab, kuna meil on int, see tähendab arv, siis peame numbri tagastama. Kuigi sellel pole ikkagi mõtet, sest. peamisest mikrokontrolleris ei saa me ainult kuhugi minna. Ma tagastan null. Nefig jaoks. Ja kompilaator on tavaliselt tark ega genereeri selleks puhuks koodi.
Kuigi, kui perversne, siis alates peamine võite minna MK-sse - näiteks kukkuda alglaaduri sektsiooni ja seda käivitada, kuid siin on üleminekuaadresside parandamiseks vaja juba püsivara madalal tasemel valimist. Allpool näete ja saate aru, kuidas seda teha. Milleks? See on nüüd teine ​​küsimus, 99,999% juhtudest pole see vajalik :)

Tehtud, edasi. Lisame muutuja, meil pole seda tegelikult vaja ja ilma selleta ei tohiks muutujaid kasutusele võtta, aga me õpime. Kui muutujad lisatakse funktsiooni kehasse, siis on need lokaalsed ja eksisteerivad ainult selles funktsioonis. Funktsioonist väljumisel need muutujad kustutatakse ja RAM-mälu antakse olulisematele vajadustele. .

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

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

allkirjastamata tähendab allkirjastamata. Fakt on see, et binaarses esituses omistatakse märgile kõige olulisem bitt, mis tähendab, et arv +127/-128 mahub ühte baiti (char), kuid märgi ärajätmisel mahub see 0 kuni 255. Tavaliselt pole märki vaja. Nii et allkirjastamata.
i on lihtsalt muutuja nimi. Mitte rohkem.

Nüüd peame lähtestama pordid ja UART. Muidugi võite võtta ja ühendada raamatukogu ja helistada mingisugusele UartInitile (9600); aga siis sa ei tea, mis tegelikult juhtus.

Teeme seda:

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 baudidivider (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider) ; UBRRH = HI(baudjagaja) ; 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 boodikiirus 9600L #define boodijagaja (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO (baudjagaja); UBRRH = HI (baudijagaja); UCSRA = 0; UCSRB = 1<

Hirmutav? Tegelikult on reaalses koodis ainult viis viimast rida. Kõik, see #määratle see on eelprotsessori makrokeel. Peaaegu samad tipud, mis Assembleris, kuid süntaks on mõnevõrra erinev.

Need hõlbustavad teie rutiinseid toiminguid vajalike koefitsientide arvutamiseks. Esimeses reas ütleme selle asemel XTAL võite turvaliselt asendada 8000000 ja L- tüübinäit, nad ütlevad, et pikk on protsessori taktsagedus. Sama baudikiirus- andmeedastuse sagedus UART-i kaudu.

boodijagaja juba keerulisem, selle asemel asendatakse kahe eelmise valemiga arvutatud avaldis.
No ja LO ja TERE sellest tulemusest võetakse madalad ja kõrged baidid, sest ilmselgelt ei mahu see ühte baiti. AT TERE x nihutatakse (makro sisendparameeter) kaheksa korda paremale, mille tulemusena jääb sellest alles vaid kõrgem bait. Ja sisse LO teeme bitipõhise AND arvuga 00FF, jättes tulemuseks ainult madala baidi.

Nii et kõik tehtu on nagu #määratle võite selle ohutult minema visata ja arvutada kalkulaatoris vajalikud numbrid ning sisestada need kohe ridadele UBBRL = .... ja UBBRH=…..

Saab. Aga! Tee seda RANGELT VÕIMATU!

See toimib nii ja naa, aga sul on nö maagilised numbrid- väärtused on võetud tühjast kohast ja pole selge, miks, ja kui avate sellise projekti paari aasta pärast, siis on kuradima raske aru saada, mis need väärtused on. Ja nüüd, kui soovite muuta kiirust või muuta kvartsi sagedust ja peate kõik ümber arvutama, muutsite koodis paar numbrit ja kõik. Üldiselt, kui sa ei taha, et sind peetakse halvaks kodeerijaks, siis tee kood nii, et see oleks kergesti loetav, arusaadav ja kergesti muudetav.

Siis on kõik lihtne:
Kõik need "UBRLL ja Co" on UART-saatja konfiguratsiooniregistrid, millega me maailmaga suhtleme. Ja nüüd oleme neile määranud vajalikud väärtused, määrates need soovitud kiirusele ja soovitud režiimile.

Kuva kirje 1< Tähendab järgmist: võtke 1 ja asetage see oma kohale RXEN baidis. RXEN see on registri 4. bitt UCSRB, nii 1< moodustab kahendarvu 00010000, TXEN on 3. bitt ja 1< annab 00001000. Üksik "|" see on bitti VÕI, seega 00010000 | 00001000 = 00011000. Samamoodi määratakse ülejäänud vajalikud konfiguratsioonibitid ja lisatakse need ühisesse hunnikusse. Selle tulemusena kirjutatakse kogutud number UCSRB-sse. Seda on üksikasjalikumalt kirjeldatud MK andmelehel USART jaotises. Nii et ärge laske end tehnilistest üksikasjadest segada.

Tehtud, aeg näha, mis juhtub. Klõpsake kompileerimisel ja alustage emuleerimist (Ctrl+F7).

Silumine
Läbi jooksid kõikvõimalikud edenemisribad, stuudio muutus ja põhifunktsiooni sissepääsu lähedale ilmus kollane nool. See on koht, kus protsessor praegu on ja simulatsioon on peatatud.

Fakt on see, et alguses oli see tegelikult real UBRRL = LO (bauddivider); Lõppude lõpuks pole see, mis meil definitsioonis on, kood, vaid lihtsalt esialgsed arvutused, nii et simulaator on veidi nüri. Nüüd aga sai ta aru, et esimene õpetus sai täidetud ja kui puu otsa ronida I/O vaade, USART sektsiooni ja vaadake seal UBBRL baiti, näete, et seal on juba väärtus! 0x33.

Astuge veel üks samm. Vaata, kuidas mõne teise registri sisu muutub. Nii et minge need kõik läbi ja pöörake tähelepanu asjaolule, et kõik määratud bitid on seatud nii, nagu ma teile ütlesin, ja need määratakse kogu baidi jaoks üheaegselt. Tagasitulekust kaugemale asjad ei jõua – programm on läbi.

Avamine
Nüüd lähtestage simulatsioon nulli. Klõpsake seal Lähtesta (tõstuklahv+F5). Avage lahti võetud loend, nüüd näete, mis kontrolleris tegelikult toimub. Vaade -> Disassembler. Ja mitte YYAAAA!!! Kokkupanija!!! KOHUTAV!!! AGA SA PEAD. Et hiljem, kui midagi viltu läheb, ei läheks sa koodis lolliks ega esitaks foorumites lonkavamaid küsimusi, vaid läheksid kohe sisse ja vaataksid, kus sul pistik on. Midagi kohutavat seal pole.

Kõigepealt tulevad sarja topid:

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

See on katkestusvektori tabel. Naaseme selle juurde hiljem, praegu, lihtsalt vaadake ja pidage meeles, et see on seal. Esimene veerg on välklambi aadress, milles käsk asub, teine ​​on käsukood, kolmas käsumnemoonika, sama assembleri käsk, kolmandad käsu operandid. Oh, ja automaatne kommentaar.
Seega, kui vaadata, siis on pidevaid üleminekuid. Ja JMP käsukood on neli baiti, see sisaldab tagurpidi kirjutatud hüppeaadressi - madalat baiti madalal aadressil ja hüppekäsu koodi 940C

0000002B: BE1F OUT 0x3F, R1 väljund sisendi/väljundi asukohta

Kirjutage see null aadressile 0x3F. Kui vaatate I / O vaate veergu, näete, et aadress 0x3F on SREG registri aadress - kontrolleri lipuregistri. Need. lähtestasime SREG-i, et käivitada programm nulltingimustel.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Laadige kohe +0000002D: E0D4 LDI R29,0x04 Laadige kohe +0000002E: BFDE OUT 0x3E,R29 Välja sisend-väljundi asukohta +0000002OUTR0x3 kuni I/O asukoht

0000002C: E5CF LDI R28,0x5F Laadimine kohe +0000002D: E0D4 LDI R29,0x04 Laadimine kohe +0000002E: BFDE OUT 0x3E,R29 Välja sisend/väljund asukohta +0000002OUTR0x3 kuni I/O asukoht

See laadib virnakursori. Registreid ei saa otse I / O-sse laadida, ainult vaheregistri kaudu. Seetõttu suunake esmalt LDI-d vahepealsesse ja seejärel VÄLJAS I/O-sse. Räägin teile ka virnast lähemalt. Seniks teadke, et see on selline dünaamiline mäluala, see ripub RAM-i otsas ja salvestab aadressid ja vahemuutujad endasse. Nüüd oleme näidanud, kust virn algab.

00000032: 940C0041 JMP 0x00000041 hüpe

Hüpe programmi saaaaamy lõppu ja seal on katkestused keelatud ja tihedalt enda peal silmused:

1 2 +00000041: 94F8 CLI globaalse katkestuse keelamine +00000042: CFFF RJMP PC-0x0000 suhteline hüpe

00000041: 94F8 CLI globaalse katkestuse keelamine +00000042: CFFF RJMP PC-0x0000 suhteline hüpe

Seda ettenägematute asjaolude korral, näiteks põhifunktsioonist lahkumisel. Kontrolleri saab sellisest ahelast välja tuua kas riistvara lähtestamise või tõenäolisemalt valvekoera lähtestamise teel. Noh, või, nagu ma eespool ütlesin, parandage need kohad hex-redaktoris ja sõitke, kuhu tahame. Pange tähele ka seda, et on kahte tüüpi hüppeid JMP ja RJMP, millest esimene on otsehüpe aadressile. See võtab enda alla neli baiti ja suudab otse hüpata üle kogu mäluala. Teist tüüpi üleminekud – RJMP – on suhtelised. Tema käsk võtab kaks baiti, kuid ta hüppab praegusest asukohast (aadressilt) 1024 sammu edasi või tagasi. Ja selle parameetrid näitavad nihet praegusest punktist. Kasutatakse sagedamini, tk. võtab välklambis poole vähem ruumi ja pikki üleminekuid on harva vaja.

1 +00000034: 940C0000 JMP 0x00000000 hüpe

00000034: 940C0000 JMP 0x00000000 hüpe

Ja see on hüpe koodi algusesse. Omamoodi taaskäivitus. Siin saate kontrollida, kas kõik vektorid hüppavad. Sellest järeldusest - kui nüüd lubad katkestused (vaikimisi on need keelatud) ja sul on katkestus, aga töötlejat pole, siis toimub tarkvara lähtestamine - programm visatakse päris algusesse.

põhifunktsioon. Kõik on sama, seda ei saa isegi kirjeldada. Vaata lihtsalt registritesse sisestatakse juba arvutatud arv. Kompilaatori eelprotsessori kivimid!!! Nii et ei mingeid "maagilisi" numbreid!

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

00000036: E383 LDI R24,0x33 Laadige kohe +00000037: B989 OUT 0x09,R24 Out I/O asukohta 15: UBRRH = HI (baudjagaja); +00000038: BC10 OUT 0x20,R1 Out I/O asukohta 16: UCSRA = 0; +00000039: B81B VÄLJUND 0x0B, R1 väljund I/O asukohta 17: UCSRB = 1<

Ja siin on jamb:

1 2 3 +0000003E: E080 LDI R24,0x00 Laadimine kohe +0000003F: E090 LDI R25,0x00 Laadimine kohe +00000040: 9508 RET Alamprogrammi tagastus

0000003E: E080 LDI R24,0x00 Laadimine kohe +0000003F: E090 LDI R25,0x00 Laadimine kohe +00000040: 9508 RET Alamprogrammi tagastamine

Küsimus on selles, et miks koostaja selliseid tippe lisab? Ja see pole midagi muud kui Return 0, siis defineerisime funktsiooni int main (void), nii et me persitasime veel neli baiti, ei saa aru, mida :) Ja kui teete void main (void), siis jääb ainult RET, kuid ilmub hoiatus, et meie põhifunktsioon ei anna midagi tagasi. Üldiselt tee mis tahad :)

Keeruline? Tundub, et ei ole. Klõpsake disassembleri režiimis samm-sammult täitmist ja vaadake, kuidas protsessor täidab üksikuid juhiseid, mis juhtub registritega. Kuidas käib liikumine läbi käskude ja lõpuloopimise.

Jätkub paari päeva pärast...

Väljaspool:
Aleksei78 Tegin firefoxi jaoks pistikprogrammi, mis muudab saidil ja foorumis navigeerimise lihtsamaks.
Arutelu ja allalaadimine,

AVR-i mikrokontrollerite jaoks on erinevaid programmeerimiskeeli, kuid assembler ja C on võib-olla kõige sobivamad, kuna need keeled pakuvad kõigi mikrokontrolleri riistvara juhtimiseks vajalike võimaluste parimat rakendamist.

Assembler on madala tasemega programmeerimiskeel, mis kasutab mikrokontrolleri otsest käsukomplekti. Selles keeles programmi loomine eeldab programmeeritava kiibi käsusüsteemi head tundmist ja piisavalt aega programmi arendamiseks. Assembler kaotab programmi arendamise kiiruse ja mugavuse osas C-le, kuid sellel on märkimisväärsed eelised lõpliku käivitatava koodi suuruses ja vastavalt ka selle täitmise kiiruses.

C võimaldab luua programme palju suurema mugavusega, andes arendajale kõik kõrgetasemelise keele eelised.
Tuleb veel kord märkida, et AVR-i arhitektuur ja käsusüsteem loodi C-kompilaatori arendajate otsesel osalusel ning see võtab arvesse selle keele omadusi. C-keeles kirjutatud lähtekoodi kompileerimine on kiire ja loob kompaktse ja tõhusa koodi.

C peamised eelised assembleri ees on: programmide arendamise suur kiirus; mitmekülgsus, mis ei nõua mikrokontrolleri arhitektuuri põhjalikku uurimist; algoritmi parem dokumenteeritavus ja loetavus; funktsiooniteekide kättesaadavus; ujukomaarvutuste tugi.

C-keel ühendab harmooniliselt madala taseme programmeerimise võimalused kõrgetasemelise keele omadustega. Madala taseme programmeerimisvõimalus teeb lihtsaks otse riistvaraga töötamise ning kõrgetasemelised keeleomadused võimaldavad luua kergesti loetavat ja muudetavat programmikoodi. Lisaks on peaaegu kõigil C-kompilaatoritel võimalus kasutada komplekteerija lisasid, et kirjutada programmi kriitilisi osasid täitmise aja ja ressursside osas.

Ühesõnaga C on kõige mugavam keel nii algajale AVR-i mikrokontrolleritega tutvumiseks kui ka tõsisematele arendajatele.

Kompilaatoreid kasutatakse programmi lähtekoodi teisendamiseks mikrokontrolleri püsivara failiks.

Atmel pakub võimsat koostajakompilaatorit, mis on kaasas Windowsi-põhise Atmel Studio arenduskeskkonnaga. Koos kompilaatoriga sisaldab arenduskeskkond silurit ja emulaatorit.
Atmel Studio on täiesti tasuta ja saadaval Atmeli veebisaidilt.

Praegu on AVR-i jaoks üsna palju C-kompilaatoreid. Neist võimsaim on Stockholmist pärit IAR Systemsi koostaja. Just tema töötajad osalesid 90ndate keskel AVR-i juhtimissüsteemi väljatöötamises. IAR C Compileril on ulatuslikud koodi optimeerimisvõimalused ja see on osa integreeritud arenduskeskkonnast IAR Embedded Workbench (EWB), mis sisaldab ka koostajakompilaatorit, linkijat, projekti- ja teegihaldurit ning silurit. Paketi täisversiooni hind on 2820 EUR. Ettevõtte veebisaidilt saate alla laadida tasuta hindamisversiooni 30 päevaks või piiramatu versiooni koodi suuruse piiranguga 4 KB.

Ameerika ettevõte Image Craft Californiast Palo Altost toodab C-keele kompilaatorit, mis on kogunud üsna laialdast populaarsust. AVR-i JumpStart C-l on vastuvõetav koodi optimeerimine ja see pole liiga kallis (50–499 dollarit, olenevalt versioonist). JumpStart C demoversioon AVR-ile töötab täielikult 45 päeva.

Mitte vähem populaarsust võitis Rumeenia Code Vision AVR C Compiler, selle kompilaatori täisversiooni hind on suhteliselt madal ja ulatub 150 euroni. Kompilaatoriga on kaasas integreeritud arenduskeskkond, mis sisaldab lisaks tavapärastele funktsioonidele ka üsna huvitavat funktsiooni – CodeWizardAVR Automatic Program Generator. Jadaterminali olemasolu arenduskeskkonnas võimaldab programmide silumist kasutades mikrokontrolleri jadaporti. Arendajad saavad alla laadida tasuta hindamisversiooni koodi suuruse piiranguga 4 KB ja genereeritud C-lähtekoodi salvestamise keelamisega.

Serbia linnas Belgradis asuv MikroElektronika toodab tervet perekonda AVR-i mikrokontrollerite kompilaatoreid. C-kompilaator nimega mikroC PRO AVR-i jaoks maksab 249 dollarit. Sama hinnaga on ka mikroBasic ja mikroPascal. Arendaja saidil on demosid, mille koodi suuruse limiit on 4096 baiti. Selle kompilaatorite perekonna eeliseks on ühtne platvorm ja ühtne ideoloogia, mis võimaldab lihtsat üleminekut mitte ainult keelte, vaid ka mikrokontrollerite vahel (on kompilaatoriversioonid PIC, STM32, 8051 ... jaoks).

Integreeritud arenduskeskkond on muutunud tõeliselt ikooniks. See sisaldab võimsaid C- ja assemblerkompilaatoreid, AVRDUDE programmeerijat, silurit, simulaatorit ja paljusid teisi toetavaid programme ja utiliite. WinAVR integreerub suurepäraselt Atmeli AVR Studio arenduskeskkonnaga. Monteerija on sisendkoodilt identne AVR Studio monteerijaga. C- ja assemblerkompilaatoritel on võimalus luua silumisfaile COFF-vormingus, mis võimaldab lisaks sisseehitatud tööriistadele kasutada ka võimsat AVR Studio simulaatorit. Teine oluline pluss on see, et WinAVR-i levitatakse tasuta ja piiranguteta (tootjad toetavad GNU üldist avalikku litsentsi).

Kokkuvõtteks võib öelda, et WinAVR on ideaalne valik neile, kes hakkavad AVR-i mikrokontrollereid valdama. Just seda arenduskeskkonda peetakse selle kursuse peamiseks.

Bitipõhised toimingud põhinevad loogilistel operatsioonidel, mida oleme juba varem käsitlenud. Nad mängivad võtmerolli AVR-i mikrokontrollerite ja muude tüüpide programmeerimisel. Peaaegu ükski programm ei saa hakkama ilma bitipõhiste toiminguteta. Siiani oleme neid teadlikult vältinud, et MK-programmeerimise õppimine oleks lihtsam.

Kõigis eelmistes artiklites programmeerisime ainult I / O porte ega kasutanud täiendavaid sisseehitatud sõlme, nagu taimerid, analoog-digitaalmuundurid, katkestused ja muud sisemised seadmed, ilma milleta MK kaotab kogu oma võimsuse.

Enne sisseehitatud MK-seadmete valdamise juurde asumist peate õppima, kuidas juhtida või kontrollida AVR MK registrite üksikuid bitte. Varem tegime kontrolli või määrasime kogu registri bitid korraga. Vaatame, mis vahe on, ja jätkame siis edasi.

Bitipõhised toimingud

Kõige sagedamini kasutasime seda AVR-i mikrokontrollerite programmeerimisel, kuna see on algajate MK-programmeerijatega võrreldes selgem ja on neile hästi arusaadav. Näiteks peame määrama ainult pordi D 3. biti. Nagu me juba teame, saame selleks kasutada järgmist kahendkoodi:

PORTD = 0b00001000;

Selle käsuga seame aga 3. biti ühele ja kõik ülejäänud (0, 1, 2, 4, 5, 6 ja 7.) nullime. Ja nüüd kujutame ette olukorda, et 6. ja 7. numbrit kasutatakse ADC sisenditena ja sel ajal saabub mõne seadme signaal MK vastavatesse väljunditesse ja lähtestame need signaalid ülaltoodud käsu abil. Selle tulemusena mikrokontroller neid ei näe ja usub, et signaale ei tulnud. Seetõttu peaksime sellise käsu asemel kasutama mõnda teist, mis määraks ainult 3. biti ühele, samas ülejäänud bitte ei mõjuta. Selleks kasutatakse tavaliselt järgmist bitipõhist toimingut:

PORT |= (1<<3);

Allpool analüüsime selle süntaksit üksikasjalikult. Ja nüüd veel üks näide. Oletame, et peame kontrollima PIND-registri 3. biti olekut, kontrollides seeläbi nupu olekut. Kui see bitt nullida, siis teame, et nuppu vajutatakse ja seejärel käivitatakse käsukood, mis vastab vajutatud nupu olekule. Varem oleksime kasutanud järgmist tähistust:

if (pind == 0b00000000)

(mis tahes kood)

Kuid selle abil kontrollime mitte ühte, 3-ndat, vaid kõiki PIND-registri bitte korraga. Seetõttu, isegi kui nuppu vajutatakse ja soovitud bitt lähtestatakse, kuid sel ajal võetakse signaal vastu mis tahes muu pordi D pin, seatakse vastav bitt ühele ja sulgudes olev tingimus on vale. Selle tulemusena ei käivitata lokkis sulgudes olevat koodi isegi nupu vajutamisel. Seetõttu tuleks PIND-registri üksiku 3. biti oleku kontrollimiseks kasutada bitipõhist toimingut:

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

(mis tahes kood)

Üksikute mikrokontrolleri bittidega töötamiseks on C-programmeerimiskeele arsenalis, millega saab korraga muuta või kontrollida ühe või mitme üksiku biti olekut.

Ühe biti seadistamine

Ühe biti, näiteks pordi D, määramiseks kasutatakse bitipõhist VÕI-toimingut. Seda me kasutasime artikli alguses.

PORTD = 0b00011100; // algväärtus

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

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

PORTD == 0b00011101; // tulemus

See käsk seab biti nulli ja jätab ülejäänud muutmata.

Näiteks määrame pordi D 6. biti.

PORTD = 0b00011100; // esialgne pordi olek

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

PORTD == 0b01011100; // tulemus

Ühe kuni mitme eraldi biti kirjutamiseks korraga, näiteks null, kuues ja seitsmes port B kehtib järgmine märge.

PORTB = 0b00011100; // algväärtus

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

PORTB == 0b1011101; // tulemus

Üksikute bittide lähtestamine (nullimine).

Ühe biti lähtestamiseks kasutatakse korraga kolme eelnevalt käsitletud käsku: .

Lähtestame PORTC registri 3. biti ja ülejäänud jätame muutmata.

PORTC = 0b00011100;

PORTC &= ~(1<<3);

PORTC == 0b00010100;

Teeme sarnased toimingud 2. ja 4. numbriga:

PORTC = 0b00111110;

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

PORTC == 0b00101010;

Liidi vahetamine

Lisaks seadistamisele ja lähtestamisele kasutatakse ka kasulikku käsku, mis lülitab ühe biti vastupidisesse olekusse: üks nulli ja vastupidi. Seda loogilist toimingut kasutatakse laialdaselt erinevate valgusefektide, näiteks uusaasta vaniku, ehitamisel. Mõelge PORTA näitele

PORTA = 0b00011111;

PORTA ^= (1<<2);

PORTA == 0b00011011;

Muutke nulli, teise ja kuuenda biti olekut:

PORTA = 0b00011111;

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

PORTA == 0b01011010;

Üksiku biti oleku kontrollimine. Tuletan meelde, et I/O-pordi kontrollimine (erinevalt kirjutamisest) toimub PIN-registrist andmete lugemise teel.

Kõige tavalisem test viiakse läbi ühe kahest tsüklilausest: if ja while. Oleme nende operaatoritega juba varem tuttavad.

Tühjenemise kontrollimine loogilise nulli olemasolu suhtes (lähtestamine) koos kui

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

Kui pordi D kolmas bitt tühjendatakse, käivitatakse Code1. Vastasel juhul käivitatakse Code2.

Sarnased toimingud tehakse sellise salvestusega ja sellisel kujul:

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

Tühjenemise kontrollimine loogilise üksuse olemasolu (seadistus) abil kui

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

if (PIND & (1<<3))

Ülaltoodud kaks tsüklit töötavad sarnaselt, kuid C programmeerimiskeele paindlikkuse tõttu saab neid kirjutada erinevalt. Tehe != tähendab mitte võrdne. Kui PD I/O pordi kolmas bitt on määratud (üks), siis käivitatakse Code1, kui mitte, siis Code2.

Ootan natuke lähtestamist samas

while (PIND & (1<<5))

Code1 käivitatakse seni, kuni PIND-registri 5. bitt on seatud. Selle lähtestamine hakkab käivitama Code2.

Ootab biti seadistamist samas

Siin võimaldab C-keele süntaks kirjutada koodi kahel kõige tavalisemal viisil. Praktikas kasutatakse mõlemat tüüpi salvestust.