Kā uzrakstīt kodu AVR, programmējot Atmel AVR mikrokontrollerus C. AVR programmēšana

LPT porta programmētāja shematiskā diagramma ir parādīta attēlā. Kā autobusa vadītājs izmantojiet mikroshēmu 74AC 244 vai 74HC244 (K1564AP5), 74LS244 (K555AP5) vai 74ALS244 (K1533AP5).

LED VD1 norāda mikrokontrollera ierakstīšanas režīmu,

LED VD2 - lasīšana,

LED VD3 - strāvas padeves klātbūtne ķēdē.

Strāvas padevei nepieciešamo spriegumu ķēde ņem no ISP savienotāja, t.i. no programmējamās ierīces. Šī shēma ir pārveidota STK200/300 programmētāja shēma (pievienotas gaismas diodes, lai atvieglotu darbību), tāpēc tā ir saderīga ar visām datoru programmētāju programmām, kas darbojas ar STK200/300 shēmu. Lai strādātu ar šo programmētāju, izmantojiet programmu CVAVR

Programmētāju var izgatavot uz iespiedshēmas plates un ievietot LPT savienotāja korpusā, kā parādīts attēlos:




Lai strādātu ar programmētāju, ir ērti izmantot LPT pieslēgvietas paplašinājumu, kuru ir viegli izgatavot pašam (piemēram, no Centronix kabeļa printerim), galvenais ir nepataupīt vadus zemei ​​(18- 25 savienotāju kājas) vai nopirkt. Kabelis starp programmētāju un programmējamo mikroshēmu nedrīkst pārsniegt 20-30 cm.

Esmu ne reizi vai divas reizes teicis, ka studēt MK jāsāk ar montētāju. Tam tika veltīts vesels kurss mājaslapā (lai gan tas nav īpaši konsekventi, bet pamazām ķemmēju to līdz adekvātam izskatam). Jā, tas ir grūti, rezultāts nebūs pirmajā dienā, bet jūs iemācīsities saprast, kas notiek jūsu kontrolierī. Jūs zināt, kā tas darbojas, nevis kopēt citu cilvēku avotus kā mērkaķis un mēģināt saprast, kāpēc tas pēkšņi pārstāja darboties. Turklāt C ir daudz vieglāk izveidot redneck kodu, kas iznāks ar dakšiņu visnepiemērotākajā brīdī.

Diemžēl visi vēlas rezultātus nekavējoties. Tāpēc nolēmu iet citu ceļu - uztaisīt pamācību par C, bet ar viņa apakšveļas atrādīšanu. Labs iegulšanas programmētājs vienmēr cieši tur savu aparatūru, neļaujot tai spert nevienu soli bez atļaujas. Tātad vispirms būs C kods, tad tas, ko kompilators radīja un kā tas viss faktiski darbojas :)

No otras puses, C stiprā puse ir koda pārnesamība. Ja, protams, visu uzrakstīsi pareizi. Darba algoritmu un to aparatūras implementāciju sadalīšana dažādās projekta daļās. Pēc tam, lai pārsūtītu algoritmu uz citu mikrokontrolleri, pietiks pārrakstīt tikai interfeisa slāni, kurā tiek ierakstīti visi izsaukumi uz aparatūru, un atstāt visu darba kodu kā ir. Un, protams, lasāmība. C pirmkods ir vieglāk saprotams no pirmā acu uzmetiena (lai gan... piemēram, man ir vienalga, uz ko norādīt - vai tas būtu C vai ASM :)), bet atkal, ja viss ir uzrakstīts pareizi. Es arī pievērsīšu uzmanību šiem punktiem.

Mana atkļūdošanas dēlis kalpos kā eksperimentālā aparatūra, kurā tiks instalēta lauvas tiesa no visiem piemēriem.

Pirmā C programma AVR

Kompilatora izvēle un vides iestatīšana
AVR ir daudz dažādu C kompilatoru:
Vispirms tas IAR AVR C- gandrīz noteikti ir atzīts par labāko AVR kompilatoru, jo pats kontrolieris tika izveidots, cieši sadarbojoties Atmel un IAR speciālistiem. Bet par visu ir jāmaksā. Un šis kompilators ir ne tikai dārga komerciāla programmatūra, bet arī tam ir tik daudz iestatījumu, ka ir nepieciešams daudz pūļu, lai to vienkārši apkopotu tajā. Es tiešām neveidoju ar viņu draudzību, jo projekts sabruka dīvainu kļūdu dēļ saistīšanas posmā (vēlāk es uzzināju, ka tā bija greiza plaisa).

Otrais nāk WinAVR GCC- spēcīgs optimizācijas kompilators. Pilnībā atvērtā koda, starpplatformu, kopumā visi dzīves prieki. Tas arī lieliski integrējas AVR Studio, ļaujot atkļūdot tieši tur, kas ir sasodīti ērti. Kopumā es to izvēlējos.

Ir arī CodeVision AVR C ir ļoti populārs kompilators. Tas kļuva populārs savas vienkāršības dēļ. Tajā varat iegūt darba programmu tikai dažu minūšu laikā - sākuma koda vednis to ievērojami atvieglo, izspiežot standartus visu veidu lietu inicializācijai. Godīgi sakot, man tas ir nedaudz aizdomīgi - reiz, kad man bija jāizjauc šī kompilatora rakstītā programma, tas izrādījās kaut kāds haoss, nevis kods. Briesmīgi daudz nevajadzīgu kustību un operāciju, kā rezultātā radās ievērojams koda daudzums un lēna veiktspēja. Tomēr, iespējams, bija kļūda tās personas DNS, kura uzrakstīja sākotnējo programmaparatūru. Turklāt viņš grib naudu. Ne tik daudz kā IAR, bet pamanāms. Un demonstrācijas režīmā tas ļauj rakstīt ne vairāk kā 2 kb koda.
Protams, ir plaisa, bet, ja jūs gatavojaties zagt, tas ir miljons IAR nozīmē :)

Ir arī Image Craft AVR C Un MicroC no mikroelektronikas. Man nevajadzēja izmantot nevienu, bet S.W.G.ļoti slavinoši MicroPascal, saka, šausmīgi ērta programmēšanas vide un bibliotēkas. Es domāju, ka MicroC nebūs sliktāks, bet tas ir arī apmaksāts.

Kā jau teicu, es izvēlējos WinAVR trīs iemeslu dēļ: tas ir bezmaksas, integrējas AVR Studio, un tam ir rakstīts tikai ļoti daudz gatavu kodu visiem gadījumiem.

Tāpēc lejupielādējiet WinAVR instalāciju, izmantojot AVR Studio. Tālāk vispirms tiek instalēta studija, pēc tam WinAVR tiek uzvilkta virsū un pievienota studijai spraudņa veidā. Es ļoti iesaku instalēt WinAVR uz īsa ceļa, piemēram, C:\WinAVR, tādējādi jūs izvairīsities no daudzām problēmām ar ceļiem.

Projekta izveide
Tātad, studija ir uzstādīta, C ir ieskrūvēts, ir pienācis laiks mēģināt kaut ko ieprogrammēt. Sāksim ar vienkāršāko, vienkāršāko. Palaidiet studiju, atlasiet tur jaunu projektu kā AVR GCC kompilatoru un ievadiet projekta nosaukumu.

Tiek atvērts darba lauks ar tukšu *.c failu.

Tagad nenāks par ļaunu konfigurēt ceļu parādīšanu studijas grāmatzīmēs. Lai to izdarītu, dodieties uz:
Izvēlnes rīki - Opcijas - Vispārīgi - Failu cilnes un nolaižamajā sarakstā atlasiet "Tikai faila nosaukums". Pretējā gadījumā nebūs iespējams strādāt - cilnē būs pilns faila ceļš, un ekrānā būs ne vairāk kā divas vai trīs cilnes.

Projekta iestatīšana
Kopumā tiek uzskatīts, ka ir klasisks izveidot make failu, kurā ir aprakstītas visas atkarības. Un tas droši vien ir pareizi. Bet man, kas uzauga ar pilnībā integrētiem IDE, piemēram uVision vai AVR studijašī pieeja ir dziļi sveša. Tāpēc darīšu pēc sava prāta, visu izmantojot studijas līdzekļus.

Ieduriet pogu ar pārnesumu.


Šie ir jūsu projekta iestatījumi vai drīzāk iestatījumi make faila automātiskai ģenerēšanai. Pirmajā lapā jums vienkārši jāievada frekvence, kādā jūsu MK darbosies. Tas ir atkarīgs no drošinātāju bitiem, tāpēc mēs pieņemam, ka mūsu frekvence ir 8000000Hz.
Pievērsiet uzmanību arī optimizācijas līnijai. Tagad ir -Os - tā ir izmēru optimizācija. Pagaidām atstājiet to kā ir, tad varat mēģināt spēlēt ar šo parametru. -O0 nav optimizācijas vispār.

Nākamais solis ir ceļu konfigurēšana. Pirmkārt, pievienojiet tur savu projekta direktoriju - tur pievienosit trešo pušu bibliotēkas. Ceļš “.\” parādīsies sarakstā.

Make fails ir ģenerēts, varat to apskatīt sava projekta noklusējuma mapē, vienkārši ieskatieties un skatiet, kas tur ir.


Tas pagaidām ir viss. Visur noklikšķiniet uz Labi un dodieties uz avotu.

Problēmas formulēšana
Tukša papīra lapa vilina īstenot kādu viltīgu ideju, jo banāla diodes mirkšķināšana vairs nedarbojas. Tūlīt ņemsim vērsi pie ragiem un ieviesīsim savienojumu ar datoru – tas ir pirmais, ko daru.

Tas darbosies šādi:
Kad COM portā ierodas viens (kods 0x31), mēs ieslēgsim diodi, un, kad pienāk nulle (kods 0x30), tā izslēdzas. Turklāt viss tiks darīts ar pārtraukumiem, un fona uzdevums būs citas diodes mirgošana. Vienkārši un jēgpilni.

Ķēdes montāža
Mums ir jāpievieno USB-USART pārveidotāja modulis ar mikrokontrollera USART tapām. Lai to izdarītu, paņemiet džemperi no diviem vadiem un novietojiet to uz tapām šķērsām. Tas ir, mēs savienojam kontroliera Rx ar pārveidotāja Tx, bet pārveidotāja Tx - ar kontroliera Rx.

Galu galā šī ir diagramma:


Es neapsveru iespēju pievienot atlikušās tapas, barošanu vai atiestatīšanu, tas ir standarts.

Koda rakstīšana

Uzreiz atļaušos izdarīt atrunu, ka pašas C valodas aprakstā īpaši neiedziļināšos. Šim nolūkam ir vienkārši milzīgs daudzums materiālu, sākot no klasiskās “C programmēšanas valodas” no K&R līdz dažādām rokasgrāmatām.

Es atradu vienu šādu metodi savā krātuvē, es to izmantoju, lai pētītu šo valodu. Tur viss ir īss, skaidrs un precīzs. Es to pakāpeniski salieku kopā un velku uz savu vietni.

Tiesa, visas nodaļas vēl nav pārsūtītas, bet domāju, ka tas nebūs ilgi.

Maz ticams, ka es to varēšu aprakstīt labāk, tāpēc no apmācības kursa tā vietā, lai sniegtu detalizētu informāciju par niansēm, es vienkārši sniegšu tiešas saites uz atsevišķām šīs rokasgrāmatas lapām.

Bibliotēku pievienošana.
Pirmkārt, mēs pievienojam nepieciešamās bibliotēkas un galvenes ar definīcijām. Galu galā C ir universāla valoda, un mums viņam jāpaskaidro, ka mēs strādājam tieši ar AVR, tāpēc ierakstiet rindiņu avota kodā:

1 #iekļauts

#iekļauts

Šis fails atrodas mapē WinAVR un tajā ir visu kontroliera reģistru un portu apraksts. Turklāt viss tur ir viltīgs, ar piesaisti konkrētam kontrolierim, ko kompilators pārraida caur veidot fails parametrā MCU un pamatojoties uz šo mainīgo, jūsu projektam ir pievienots galvenes fails ar visu šī konkrētā kontrollera portu un reģistru adrešu aprakstu. Oho! Arī bez tā tas ir iespējams, taču tad nevarēsit izmantot simboliskus reģistru nosaukumus, piemēram, SREG vai UDR, un jums būs jāatceras katra adrese, piemēram, “0xC1”, kas būs galvassāpes.

Pati komanda #iekļauts<имя файла> ļauj projektam pievienot jebkura teksta faila saturu, piemēram, failu ar funkciju aprakstu vai cita koda fragmentu. Un, lai direktīva varētu atrast šo failu, mēs norādījām ceļu uz mūsu projektu (WinAVR direktorijs jau ir reģistrēts tur pēc noklusējuma).

Galvenā funkcija.
C programma pilnībā sastāv no funkcijām. Tos var ligzdot un izsaukt vienu no otra jebkurā secībā un dažādos veidos. Katrai funkcijai ir trīs obligātie parametri:

  • Atgriešanas vērtība ir piem. grēks (x) atgriež x sinusa vērtību. Īsumā kā matemātikā.
  • Pārraidītie parametri ir tie paši X.
  • Funkciju korpuss.

Visām pārsūtītajām un atgrieztajām vērtībām ir jābūt noteikta veida atkarībā no datiem.

Jebkurā C programmā ir jābūt funkcijai galvenais kā ieejas punkts galvenajā programmā, pretējā gadījumā tas nemaz nav C :). Pēc galvenā klātbūtnes kāda cita avota kodā no miljons failiem, jūs varat saprast, ka šī ir galvenā programmas daļa, ar kuru viss sākas. Tātad jautāsim:

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

int main(void) (atgriež 0; )

Tas arī viss, ir uzrakstīta pirmā vienkāršākā programma, nav svarīgi, ka tā neko nedara, mēs esam tikko sākuši.

Izdomāsim, ko mēs izdarījām.
starptŠis ir datu tips, ko atgriež galvenā funkcija.

Protams, mikrokontrollerī galvenais principā neko nevar atdot un teorētiski tam vajadzētu būt nederīgs galvenais (neesošs), bet GCC sākotnēji ir paredzēts personālajam datoram, un tur programma pēc pabeigšanas var atgriezt vērtību operētājsistēmai. Tāpēc GCC ieslēgts nederīgs galvenais (neesošs) zvēr ar Brīdinājumu.

Tā nav kļūda, tā darbosies, bet man nepatīk brīdinājumi.

nederīgsŠis ir datu veids, ko mēs nododam funkcijai, šajā gadījumā galvenais arī nevar pieņemt neko no ārpuses, tāpēc nederīgs- manekens. Stubs tiek izmantots, ja nekas nav jāpārraida vai jāatgriež.

Šeit tie ir { } cirtaini breketes ir programmas bloks, šajā gadījumā funkcijas pamatteksts galvenais, kods atradīsies tur.

atgriezties- šī ir atgriešanas vērtība, ko galvenā funkcija atgriezīs pēc pabeigšanas, jo mums ir int, tas ir, skaitlis, tad mums ir jāatgriež skaitlis. Lai gan tam joprojām nav jēgas, jo... uz mikrokontrollera, mēs varam tikai nekur no galvenā. Es atgriežu nulli. Jo tas nav svarīgi. Bet kompilators parasti ir gudrs un šim gadījumam kodu neģenerē.
Lai gan, ja perverss, tad no galvenais Varat doties uz MK - piemēram, iekļūt sāknēšanas ielādētāja sadaļā un izpildīt to, taču, lai labotu pārejas adreses, būs nepieciešama zema līmeņa programmaparatūra. Tālāk jūs redzēsiet pats un sapratīsit, kā to izdarīt. Par ko? Tas ir cits jautājums, 99,999% gadījumu tas nav nepieciešams :)

Mēs to izdarījām un devāmies tālāk. Pievienosim mainīgo, mums tas nav īsti vajadzīgs un bez tā nav jēgas ieviest mainīgos, bet mēs mācāmies. Ja funkcijas pamattekstā tiek pievienoti mainīgie, tie ir lokāli un pastāv tikai šajā funkcijā. Izejot no funkcijas, šie mainīgie tiek dzēsti un RAM atmiņa tiek piešķirta svarīgākām vajadzībām. .

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

int main(void) ( neparakstīts char i; return 0; )

neparakstīts nozīmē neparakstīts. Fakts ir tāds, ka binārajā attēlojumā zīmei tiek piešķirts visnozīmīgākais bits, kas nozīmē, ka skaitlis +127/-128 iekļaujas vienā baitā (char), bet, ja zīmi atmet, tas ietilps no 0 līdz 255. Parasti zīme nav vajadzīga. Tātad neparakstīts.
i ir tikai mainīgais nosaukums. Vairāk ne.

Tagad mums ir jāinicializē porti un UART. Protams, jūs varat paņemt un savienot bibliotēku un izsaukt kaut kādu UartInit(9600); bet tad tu nezināsi, kas īsti notika.

Mēs to darām:

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 bodu dalītāju (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddalītājs) ; UBRRH = HI(bauddalītājs) ; 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 bodrate 9600L #define boddivider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO(bauddalītājs);<

Baisi? Faktiski ir tikai piecas pēdējās reālā koda rindas. Viss, tas #definēt tā ir priekšprocesora makro valoda. Gandrīz tādas pašas lietas kā Assembly, taču sintakse nedaudz atšķiras.

Tie atvieglos jūsu ikdienas nepieciešamo koeficientu aprēķināšanas operācijas. Pirmajā rindā mēs to sakām XTAL jūs varat droši aizstāt 8000000, un L- tipa norāde, sakot, ka garš ir procesora takts frekvence. Tas pats pārraides ātrumu— datu pārraides biežums, izmantojot UART.

bodu dalītājs jau sarežģītāk, tā vietā tiks aizstāta izteiksme, kas aprēķināta pēc formulas no divām iepriekšējām.
Nu un L.O. Un SVEIKI no šī rezultāta tiks ņemti zemie un augstie baiti, jo Acīmredzot tas var neietilpst vienā baitā. IN SVEIKI X (makro ievades parametrs) tiek pārvietots astoņas reizes pa labi, kā rezultātā paliek tikai nozīmīgākais baits. Un iekšā L.O. mēs veicam bitu UN ar numuru 00FF, kā rezultātā paliks tikai zemais baits.

Tātad viss, kas izdarīts, ir kā #definēt jūs varat to droši izmest un aprēķināt nepieciešamos skaitļus kalkulatorā un nekavējoties ievadīt tos rindās UBBRL = …. un UBBRH = .....

Var. Bet! Dari šo PILNĪGI NEIESPĒJAMI!

Darbosies tā vai tā, bet tev būs t.s burvju skaitļi- vērtības, kas ņemtas no nekurienes un nezināmu iemeslu dēļ, un, ja jūs atverat šādu projektu pēc pāris gadiem, būs sasodīti grūti saprast, kas tās ir. Arī tagad, ja vēlaties mainīt ātrumu vai mainīt kvarca frekvenci, viss būs jāpārrēķina vēlreiz, bet jūs nomainījāt pāris ciparus kodā un viss. Kopumā, ja nevēlaties tikt apzīmēts kā kodētājs, izveidojiet savu kodu tā, lai tas būtu viegli lasāms, saprotams un viegli modificējams.

Tad viss ir vienkārši:
Visi šie “UBRRL un Co” ir UART raidītāja konfigurācijas reģistri, ar kuru palīdzību mēs sazināsimies ar pasauli. Un tagad mēs esam piešķīruši tiem vajadzīgās vērtības, iestatot tos vajadzīgajā ātrumā un režīmā.

Ieraksta veids 1< Nozīmē sekojošo: paņemiet 1 un ievietojiet to vietā RXEN baitā. RXENšis ir reģistra 4. bits UCSRB, Tātad 1< veido bināro skaitli 00010000, TXEN- šis ir 3. bits un 1< dos 00001000. Single "|" tas ir bitiski VAI, tātad 00010000 | 00001000 = 00011000. Tādā pašā veidā atlikušie nepieciešamie konfigurācijas biti tiek iestatīti un pievienoti vispārējai kaudzei. Rezultātā savāktais numurs tiek reģistrēts UCSRB. Sīkāka informācija ir aprakstīta MK datu lapā USART sadaļā. Tāpēc nenovērsīsim uzmanību no tehniskām detaļām.

Gatavs, laiks redzēt, kas noticis. Noklikšķiniet uz kompilācijas un sāciet emulāciju (Ctrl+F7).

Atkļūdošana
Cauri skrēja visādas progresa joslas, mainījās studija un pie galvenās funkcijas ieejas parādījās dzeltena bultiņa. Šeit pašlaik darbojas procesors, un simulācija ir apturēta.

Fakts ir tāds, ka sākotnēji tas bija rindā UBRRL = LO (bauddalītājs); Galu galā tas, kas mums ir definē, nav kods, bet vienkārši provizoriski aprēķini, tāpēc simulators ir nedaudz blāvs. Bet tagad viņš saprata, pirmā instrukcija ir izpildīta un ja jūs kāpt kokā I/O skats, uz USART sadaļu un paskatieties uz UBBRL baitu tur, redzēsiet, ka vērtība jau ir! 0x33.

Sniedziet to vienu soli tālāk. Skatiet, kā mainās otra reģistra saturs. Tāpēc apskatiet tos visus, pievērsiet uzmanību tam, ka visi norādītie biti ir iestatīti tā, kā es jums teicu, un tie tiek iestatīti vienlaikus visam baitam. Tas netiks tālāk par Atgriešanos - programma ir beigusies.

Atvēršana
Tagad atiestatiet simulāciju uz nulli. Noklikšķiniet tur Atiestatīt (Shift+F5). Atveriet izjaukto sarakstu, tagad redzēsit, kas patiesībā notiek kontrollerī. Skatīt -> Demontētājs. Un ne YYAAAAAA!!! Montētājs!!! ŠAUSMAS!!! UN TAS IR VAJAG. Lai vēlāk, kad kaut kas noiet greizi, tu nebūtu stulbs kodā un neuzdotu lamu jautājumus forumos, bet uzreiz iedziļināties iekšā un redzētu, kur esat iestrēdzis. Tur nav nekā biedējoša.

Vispirms būs topi no sērijas:

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 lēciens +00000002: 940C0034 JMP 0x00000034 lēciens +00000004: 940C0034 JMP 0x000mp06034000C +90 0x00000034 lēciens +00000008: 940C0034 JMP 0x00000034 lēciens +0000000A: 940C0034 JMP 0x00000034 lēciens +0000000C: 9400000C: 940 JMP000x 0000000E: 940C0034 JMP 0x000034 Pārlēkt +00000010: 940c0034 JMP 0x00000034 Pārlēkt +000012: 940c0034 JMP 0x00000030x JMP 0000034 Lēciens +00000016: 940C003 4 JMP 0x00000034 Lēciens +00000018: 940c0034 JMP 0x00000034 Lēciens +0000001a: 940c00x3040 JMP 0000001c : 940C0034 JMP 0x00000034 Pārlēkt +0000001E: 940C0034 JMP 0x00000034 Pārlēkt +00000020: 940C0034 JMP 0x000C.2000 MP 0x00000 034 lēciens +00000024: 940C0034 JMP 0x00000034 lēciens +00000026: 940C0034 JMP 0x00000034 lēciens +00000028: 30400028: 3040mp0

00000000: 940C002A JMP 0x00002A lēciens +00000002: 940C0034 JMP 0x00000034 lēciens +00000004: 940C0034 JMP 0x00000340x0603040 000034 Lēciens +000008: 940C0034 JMP 0x00000034 Lēciens +0000000a: 940c0034 JMP 0x00000034 Pārlēciens +0000000C: 940c0034 JMP000030000000 : 940C0034 JMP 0x00000034 Pārlēkt +00000010: 940C0034 JMP 0x00000034 Pārlēkt +00000012: 940C0034 JMP 0x00000034 Pārlēkt +0400034 JMP 034 lēciens +00000016: 940C0034 JMP 0x00000034 lēciens +00000018: 940C0034 JMP 0x00000034 lēciens +0000001A: 940C0034 JMP000x300 JMP000x4 : 940C0034 JMP 0x00000034 Pārlēkt +0000001E: 940C0034 JMP 0x00000034 Pārlēkt +00000020: 940C0034 JMP 0x00000034 Pārlēkt 0x00000034 Pārlēkt 03 4 Lēciens +00000024: 940C0034 JMP 0x00000034 Lēciens +00000026: 940C0034 JMP 0x00000034 Lēciens +00000028: 940C0034 JMP000x30

Šī ir pārtraukumu vektoru tabula. Mēs pie tā atgriezīsimies vēlāk, bet pagaidām vienkārši paskatieties un atcerieties, ka tā pastāv. Pirmā kolonna ir zibatmiņas šūnas adrese, kurā atrodas komanda, otrā ir komandas kods, trešā ir komandas mnemonika, tā pati montāžas instrukcija, trešā ir komandas operandi. Nu automātiskais komentārs.
Tātad, ja paskatās, ir nepārtrauktas pārejas. Un JMP komandas kods ir četri baiti, tajā ir lēciena adrese, kas rakstīta atpakaļ - zemais baits zemajā adresē un lēciena komandas kods 940C

0000002B: BE1F OUT 0x3F, R1 Out uz I/O atrašanās vietu

Šīs nulles ierakstīšana adresē 0x3F Ja paskatās uz I/O skata kolonnu, jūs redzēsit, ka adrese 0x3F ir SREG reģistra adrese - kontrollera karoga reģistrs. Tie. mēs atiestatām SREG, lai programmu palaistu nulles apstākļos.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Tūlītēja ielāde +0000002D: E0D4 LDI R29,0x04 Tūlītēja ielāde +0000002E: BFDE OUT 0x3E,R29 Izeja uz I/O atrašanās vietu +0000002F: BFCD uz I/O atrašanās vieta

0000002C: E5CF LDI R28,0x5F Tūlītēja ielāde +0000002D: E0D4 LDI R29,0x04 Tūlītēja ielāde +0000002E: BFDE OUT 0x3E,R29 Izeja uz I/O atrašanās vietu +0000002F: BFCD uz I/O atrašanās vieta

Tiek ielādēts steka rādītājs. Jūs nevarat tieši ielādēt I/O reģistros, tikai caur starpreģistru. Tāpēc vispirms LDI uz starpproduktu un pēc tam OUT uz I/O. Vēlāk arī pastāstīšu vairāk par steku. Pagaidām ziniet, ka šī ir dinamiska atmiņas apgabals, kas karājas RAM beigās un saglabā adreses un starpposma mainīgos. Tagad mēs esam norādījuši, no kurienes sāksies mūsu kaudze.

00000032: 940C0041 JMP 0x00000041 Pārlēkt

Pārejiet uz pašām programmas beigām, un tur ir aizliegts pārtraukt un cieši cilpot sevi:

1 2 +00000041: 94F8 CLI globālā pārtraukuma atspējošana +00000042: CFFF RJMP PC-0x0000 Relatīvais lēciens

00000041: 94F8 CLI globālā pārtraukuma atspējošana +00000042: CFFF RJMP PC-0x0000 Relatīvais lēciens

Tas notiek neparedzētu apstākļu gadījumā, piemēram, aizejot no galvenās funkcijas. Kontrolieri var izņemt no šādas cilpas, veicot aparatūras atiestatīšanu vai, visticamāk, atiestatot no sargsuņa. Nu, vai, kā jau teicu iepriekš, izlabojiet to hex redaktorā un dodieties uz turieni, kur vien mūsu sirds vēlas. Ņemiet vērā arī to, ka ir divu veidu pārejas: JMP un RJMP pirmā ir tieša pāreja uz adresi. Tas aizņem četrus baitus un var tieši pāriet pa visu atmiņas apgabalu. Otrs pārejas veids ir RJMP – relatīvs. Viņa komanda aizņem divus baitus, bet viņš pārvietojas no pašreizējās pozīcijas (adreses) 1024 soļus uz priekšu vai atpakaļ. Un tā parametri norāda nobīdi no pašreizējā punkta. To lieto biežāk, jo vienā līmenī aizņem pusi vietas, un reti ir vajadzīgas garas pārejas.

1 +00000034: 940C0000 JMP 0x00000000 lēciens

00000034: 940C0000 JMP 0x00000000 Pārlēkt

Un tas ir lēciens uz koda sākumu. Sava veida atsāknēšana. Šeit varat pārbaudīt, vai visi vektori pārlec. Secinājums no tā ir tāds, ka, ja jūs tagad iespējojat pārtraukumus (pēc noklusējuma tie ir atspējoti) un jūsu pārtraukums notiek, bet nav apstrādātāja, tad notiks programmatūras atiestatīšana - programma tiks atgriezta pašā sākumā.

Galvenā funkcija. Viss ir līdzīgi, pat nevajag to aprakstīt. Paskatieties, kā jau aprēķinātais skaitlis tiek ievadīts reģistros. Kompilatora priekšprocesors satriec!!! Tātad bez "maģiskiem" skaitļiem!

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

00000036: E383 LDI R24,0x33 Tūlītēja ielāde +00000037: B989 OUT 0x09,R24 Out uz I/O vietu 15: UBRRH = HI (bauddalītājs); +00000038: BC10 OUT 0x20,R1 Out uz I/O vietu 16: UCSRA = 0; +00000039: B81B OUT 0x0B,R1 Out uz I/O vietu 17: UCSRB = 1<

Un šeit ir kļūda:

1 2 3 +0000003E: E080 LDI R24.0x00 Tūlītēja ielāde +0000003F: E090 LDI R25.0x00 Tūlītēja ielāde +00000040: 9508 RET Apakšprogrammas atgriešana

0000003E: E080 LDI R24.0x00 Tūlītēja ielāde +0000003F: E090 LDI R25.0x00 Tūlītēja ielāde +00000040: 9508 RET Apakšprogrammas atgriešana

Jautājums, kāpēc kompilators pievieno tādus topus? Un tas nav nekas vairāk kā Return 0, funkciju definējām kā int main(void), tāpēc bez iemesla iztērējām vēl četrus baitus :) Un ja uztaisīsi void main(void) tad paliks tikai RET, bet brīdinājums. šķiet, ka mūsu galvenā funkcija neko neatgriež. Vispār dari kā gribi :)

Grūti? Acīmredzot nē. Noklikšķiniet uz soli pa solim izpilde disassemblera režīmā un skatiet, kā procesors izpilda atsevišķas instrukcijas, kas notiek ar reģistriem. Kā notiek kustība caur komandām un galīgā cilpa?

Turpinājums pēc pāris dienām...

Ārpus virsotnēm:
Aleksejs78 Es izveidoju Firefox spraudni, kas atvieglo navigāciju manā vietnē un forumā.
Diskusija un lejupielāde,

Kaut kā uzreiz jutos spiests sniegt padomu par programmēšanas vides izvēli AVR kontrolleriem. Tikai nemetiet man ar čībām. Es esmu tikai nedaudz :)

Mikrokontrolleriem ir daudz programmēšanas valodu. Ir arī diezgan daudz programmēšanas vidi, un ir nepareizi tās salīdzināt savā starpā. Nav labāko programmēšanas valodu. Tas nozīmē, ka jums būs jāizvēlas sev piemērotākā valoda un programmēšanas vide.

Ja šobrīd esi izvēles priekšā, pie kā sākt strādāt, tad šeit ir daži ieteikumi tev.

Iepriekšēja programmēšanas pieredze. Neaizmirstiet par savu iepriekšējo programmēšanas pieredzi. Pat ja tas būtu BASIC. Pat ja tas bija sen skolā. Programmēšana ir kā braukšana ar velosipēdu – kad sākat, jūs ātri atceraties visu, ko esat aizmirsis. Sāciet ar BASIC - apgūstiet to - vēlāk būs vieglāk izvēlēties kaut ko piemērotāku saviem mērķiem.

Palīdzība no vides. Vai jūsu draugi raksta Paskālā? Problēma jums ir atrisināta - rakstiet Paskālā! Viņi vienmēr jums palīdzēs ar padomu, sniegs jums bibliotēkas un sniegs jums gatavus projektus, ko mācīties. Kopumā viņi ar prieku uzņems jūs savā kopienā. Ja jūs darāt pretējo, jūs iegūsit pretēju rezultātu. NVS nozares draugi jūs iepriecinās, ja nolemsiet studēt Assembler. Negaidiet palīdzību.

Laba grāmata par AVR programmēšanuļoti palīdzēs. Diemžēl tādu ir ļoti maz. Ja jūs saskaraties ar grāmatu un domājat, ka viss ir izskaidrots ļoti pieejamā veidā, izmēģiniet to. Neiesaku mācīties no e-grāmatām kā pēdējo līdzekli, tās izdrukāt. Ir ļoti neērti pārslēgties starp vidi un grāmatas faila tekstu. Daudz patīkamāk ir lasīt grāmatu un izmēģināt to uzreiz, nenovirzoties no pārslēgšanas, turklāt varat veikt piezīmes pie malām un pierakstīt radušās idejas.

Programmēšanas vide ir vienkāršāka. Ja jūsu valodai ir vairākas programmēšanas vides, nevilcinieties un izvēlieties vienkāršāku. Lai tas būtu mazāk funkcionāls. Ļaujiet viņai sastādīt šausmīgi uzpūstu kodu. Galvenais ir tikai sākt strādāt. Kad jūtaties ērti vienkāršā vidē, varat viegli pāriet uz modernāku un “pareizāku” vidi. Un neklausieties tajos, kuri saka, ka zaudēsit vairāk laika - viņi kļūdās. Sākumskolas skolēniem netiek lūgts lasīt “Karu un mieru” viņiem tiek dotas vienkāršākas grāmatas - ar attēliem.

Bibliotēkas. Bibliotēku pieejamība valodu apguvē ir pretrunīga. Protams, vēlāk tie ievērojami atvieglos dzīvi, taču sākotnēji “Melnās kastes” bibliotēkas ir nesaprotamas un īsti neveicina valodas izpratni. No otras puses, tie padara programmas vieglāk lasāmas un ļauj iesācējam bez lielām pūlēm izveidot sarežģītas programmas. Tāpēc pārāk neuztraucieties par viņu klātbūtni. Vismaz sākumā.

Efektīvs kods. Programmēšanas vides izvēle, lai apgūtu programmēšanu, pamatojoties tikai uz to, cik efektīva ir tā apkopotā koda, ir slikta ideja. Galvenais, lai, uzsākot studijas, justos ērti – tas, kas no tā sanāk, ir desmitā lieta. Protams, jūs varat strādāt pie tā vēlāk.

Burvji. Jebkura ierīce, kas atrodas mikroshēmā, ir jākonfigurē, izmantojot portus. Procedūra ir diezgan nogurdinoša, un ir nepieciešamas datu lapas. Turklāt ir nianses, kuras iesācējam nav viegli aptvert. Tāpēc ļoti vēlams, lai vidē būtu burvji. Vyzards ir automātiskie uztvērēji SPI, I2C, USART utt. Jo vairāk ierīču tiek atbalstītas, jo labāk. Jūs iestatāt nepieciešamos perifērijas parametrus, un vednis pats ģenerē kodu, kas nodrošinās norādītos parametrus. Ļoti atvieglo dzīvi.


Vispārīgi ieteikumi tāds - programmēšanai sākotnējā posmā jābūt pēc iespējas vienkāršākai (pat primitīvai). Programmēšanas videi jābūt viegli apgūstamai (jo, pirmkārt, ir jāpārvalda programmēšana un nevajadzētu tērēt laiku, kārtojot iestatījumus). Vēlams rusificēts. Noderētu arī krievu rokasgrāmata un programmu paraugi. Vēlama iespēja pazibināt kristālu no apkārtējās vides. Pēc tam, apgūstot programmēšanas pamatus, varat pāriet uz sarežģītākām čaulām.


Pēdējais ieteikums: strādājiet ar īstu kristālu. Nebaidieties to sadedzināt. Gūstiet praktisku pieredzi. Darbs ar emulatoriem (piemēram, Proteus), lai arī atbrīvos no ķēpāšanās ar lodāmuru, nekad nespēs sniegt tādu gandarījumu, ko gūsi no darba programmas un pirmās gaismas diodes mirgošanas! Sapratne, ka esat izveidojis reālu darba diagrammu ar savām rokām, sniedz pārliecību un stimulu virzīties tālāk!

(Apmeklēts 7 377 reizes, 1 apmeklējumi šodien)

Es nolēmu uzrakstīt īsu ievadrakstu tiem, kuri pirmo reizi sāka programmēt mikrokontrollerus un nekad iepriekš nebija pazīstami ar C valodu. Mēs neiedziļināsimies detaļās, mēs nedaudz parunāsim par visu, lai iegūtu vispārēju priekšstatu par darbu ar CodeVisionAVR.

Sīkāku informāciju angļu valodā var atrast CodeVision lietotāja rokasgrāmatā, kā arī iesaku vietni http://somecode.ru ar video nodarbībām par C mikrokontrolleriem un Deitel grāmatu “Kā programmēt C valodā”, šī ir sākusies vienīgā labā grāmata, ko pati esmu izmantojusi.

Sāksim ar faktu, ka neatkarīgi no tā, kādas darbības mēs veicam, galu galā tas viss ir atkarīgs no mikrokontrollera programmaparatūras. Pats programmaparatūras process notiek šādi: izmantojot noteiktu programmu, tiek atlasīts programmaparatūras fails, tiek atlasīti parametri, tiek nospiesta poga un programmaparatūra tiek tieši mirgota, kas būtībā ir kopija. Tāpat kā jūs kopējat mūziku vai dokumentus no datora uz zibatmiņas disku, procesa fizika ir tāda pati.

Pati programmaparatūrai ir .hex paplašinājums, un tā ir instrukciju kopa vieninieku un nulles formā, kas ir saprotama mikrokontrolleram. Kur es varu iegūt programmaparatūru? Varat to lejupielādēt no elektronikas vietnēm vai uzrakstīt pats. To var rakstīt īpašās programmās, ko sauc par izstrādes vidi. Man vispazīstamākās ir AVR Studio, IAR, CodeVision, WinAVR... Nav iespējams pateikt, kura no šīm vidēm ir labāka vai sliktāka, katram savs. Varam teikt, ka šīs programmas atšķiras galvenokārt ar ērtībām, programmēšanas valodu un cenu. Šajā vietnē tiek ņemts vērā tikai CodeVision.

Mēs esam sakārtojuši vidi, tagad apskatīsim programmaparatūras rakstīšanas procesu. Programmā CodeVision vispirms ir jāizveido projekts. To var izveidot, izmantojot koda vedni, vai tukšu. Jebkurā gadījumā jums ir jāizvēlas izmantotā mikrokontrollera veids un jānorāda tā frekvence. Izmantojot vedni, jums tiks lūgts atlasīt sākotnējos iestatījumus un ģenerēt avota kodu ar iestatījumiem. Pēc tam parādīsies logs, kurā varat rediģēt šo kodu. Lai gan jūs varat ierakstīt savu avota kodu Notepad un pēc tam pievienot to projektam iestatījumos.

Avota koda fails ir komandu kopums programmēšanas valodā, CodeVision uzdevums ir pārtulkot šīs komandas binārā kodā, jūsu uzdevums ir uzrakstīt šo pirmkodu. CodeVision saprot C valodu, pirmkoda failiem ir paplašinājums “.c”. Bet CodeVision ir dažas konstrukcijas, kas netiek izmantotas C valodā, tāpēc daudziem programmētājiem tas nepatīk, un izmantotā valoda tiek saukta par C līdzīgu. Taču tas neliedz rakstīt nopietnus projektus. Daudzi piemēri, kodu ģenerators un liels bibliotēku komplekts sniedz CodeVision lielas priekšrocības. Vienīgais negatīvais ir tas, ka tas ir maksas, lai gan ir bezmaksas versijas ar koda ierobežojumu.

Avota kodā jābūt galvenei ar izmantotā mikrokontrollera veidu un galveno funkciju. Piemēram, tiek izmantots ATtiny13

#iekļauts void main(void) ( ) ;

#iekļauts void main(void) ( );

Pirms galvenās funkcijas varat savienot nepieciešamās bibliotēkas, deklarēt globālos mainīgos, konstantes un iestatījumus. Bibliotēka ir atsevišķs fails, parasti ar paplašinājumu “.h”, kurā jau ir iepriekš uzrakstīts kods. Dažos projektos mums šis kods var būt vajadzīgs, bet citos mums tas nav vajadzīgs. Piemēram, vienā projektā lietojam LCD displejus, bet citā ne. Bibliotēku darbam ar LCD displeju “alcd.h” var savienot šādi:

#iekļauts #iekļauts void main(void) ( ) ;

#iekļauts #iekļauts void main(void) ( );

Mainīgie ir atmiņas apgabali, kuros var ievietot noteiktas vērtības. Piemēram, ja pievienojat divus skaitļus, rezultāts ir kaut kur jāsaglabā, lai to izmantotu turpmāk. Vispirms jādeklarē mainīgais, t.i. piešķiriet tam atmiņu, piemēram:
int i=0;
tie. mēs deklarējām mainīgo i un ievietojām tajā vērtību 0, int ir mainīgā veids vai vienkāršāk, tas nozīmē piešķirtās atmiņas lielumu. Katrs mainīgā tips var saglabāt tikai noteiktu vērtību diapazonu. Piemēram, int var rakstīt kā skaitļus no -32768 līdz 32767. Ja nepieciešams izmantot skaitļus ar daļēju daļu, tad rakstzīmēm mainīgais ir jādeklarē kā peldošs, izmantojiet char veidu.

bits, _Bits 0 vai 1 raksts no -128 līdz 127 neparakstīts simbols no 0 līdz 255 int no -32768 līdz 32767 neparakstīts int no 0 līdz 65535 garš int no -2147483648 līdz 2147483647 no 90 ± 7 garš int no 90 ±7 29 75e- 38 līdz ±3,402e38

Galvenās funkcijas iekšpusē galvenā programma jau darbojas. Pēc funkcijas izpildes programma apstāsies, tāpēc viņi izveido bezgalīgu while cilpu, kas nepārtraukti atkārto vienu un to pašu programmu.

void main(void) ( while (1) ( ) ; );

void main(void) ( while (1) ( ); );

Jūs varat ierakstīt komentāru jebkurā avota koda daļā, tas nekādā veidā neietekmēs programmas darbību, bet palīdzēs veikt piezīmes par rakstīto kodu. Jūs varat komentēt rindu ar divām slīpsvītrām //pēc kurām kompilators ignorēs visu rindu vai vairākas rindiņas /**/, piemēram:

/*Mateātiskās pamatdarbības:*/ int i= 0; //deklarē mainīgo i un piešķir tam vērtību 0//Papildinājums: i = 2 + 2 ; //Atņemšana: i = 2 - 2 ; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 0//Reizināšana: i = 2 * 2 ; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 4//Iedalījums: i = 2/2; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 1

/*Matemātiskās pamatoperācijas:*/ int i=0; //deklarē mainīgo i un piešķir tam vērtību 0 //Papildinājums: i = 2+2; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 4 //Atņemšana: i = 2-2; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 0 //Reizināšana: i = 2*2; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 4 //Dalījums: i = 2/2; //pēc šīs izteiksmes izpildes mainīgais i būs vienāds ar 1

Bieži vien programmai ir jāpārslēdzas no viena koda uz citu, atkarībā no nosacījumiem tam ir nosacītas if() darbības, piemēram:

if(i>3) //ja i ir lielāks par 3, tad piešķir i vērtību 0 ( i=0; ) /*ja i ir mazāks par 3, tad ej uz kodu, kas seko nosacījuma pamattekstam, t.i. aiz iekavām ()*/

Arī tad, ja var lietot kopā ar citu – citādi

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

Ir arī salīdzināšanas operators “==”, kuru nevajadzētu sajaukt ar “=” piešķiršanu. Apgrieztā darbība nav vienāda ar "!=", teiksim

if(i==3)//ja i ir 3, piešķir i vērtību 0 (i=0; ) if(i!=5) //ja i nav 5, piešķir i vērtību 0 (i=0; )

Pāriesim pie sarežģītākām lietām – funkcijām. Pieņemsim, ka jums ir noteikts koda fragments, kas tiek atkārtots vairākas reizes. Turklāt šis kods ir diezgan liels. Katru reizi to rakstīt ir neērti. Piemēram, programmā, kas kaut kā maina mainīgo i, nospiežot D porta pogas 0 un 3, tiek izpildīts tas pats kods, kas atkarībā no mainīgā i vērtības ieslēdz porta B kājas.

Void main(void) ( ja (PIND.0== 0 ) //pārbaudiet, vai PD0 poga ir nospiesta(ja (i== 0) //ja i==0 iespējot PB0( PORTB.0= 1 ; ) ja (i== 5 ) // ja i==5 iespējot PB1( PORTB.1= 1 ; ) ) … ja (PIND.3== 0 ) // dariet to pašu, pārbaudot pogu PD3( ja (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) )

void main(void) ( if(PIND.0==0) //pārbaudi, vai ir nospiesta poga uz PD0 ( if(i==0) //ja i==0 ieslēdz PB0 ( PORTB.0=1; ) if( i==5) // ja i==5 ieslēdz PB1 ( PORTB.1=1; ) ) ... if(PIND.3==0) // dari to pašu, pārbaudot pogu PD3 ( ja(i==0 ) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) )

Kopumā kods nav īpaši liels, bet tas varētu būt daudzkārt lielāks, tāpēc daudz ērtāk būtu izveidot savu funkciju.
Piemēram:

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

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

void nozīmē, ka funkcija neko neatgriež, vairāk par šo zemāk i_check() - tas ir mūsu funkcijas nosaukums, jūs varat to saukt kā vēlaties, es to saucu tieši tā - pārbaudiet i. Tagad mēs varam pārrakstīt mūsu kodu:

void i_check() ( ja(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) void main(void) ( if(PIND.0==0 ) //pārbaudīt, vai PD0 poga ir nospiesta ( i_check(); ) ... if(PIND.3==0) ( i_check(); ) )

Kad kods sasniedz rindiņu i_check(); tad tas ielēks funkcijā un izpildīs kodu iekšā. Piekrītu, kods ir kompaktāks un skaidrāks, t.i. funkcijas palīdz aizstāt to pašu kodu, tikai vienu rindiņu. Lūdzu, ņemiet vērā, ka funkcija ir deklarēta ārpus galvenā koda, t.i. pirms galvenās funkcijas. Jūs varat teikt, kāpēc man tas ir vajadzīgs, bet, studējot nodarbības, jūs bieži saskaraties ar funkcijām, piemēram, LCD ekrāna notīrīšana lcd_clear() - funkcija nepieņem nekādus parametrus un neko neatgriež, bet tā notīra ekrāns. Dažreiz šī funkcija tiek izmantota gandrīz katrā otrajā rindā, tāpēc koda ietaupījums ir acīmredzams.

Daudz interesantāk izskatās izmantot funkciju, ja tā ņem vērtības, piemēram, ir mainīgais c un ir funkcijas summa, kas ņem divas int tipa vērtības. Kad galvenā programma izpilda šo funkciju, argumenti jau būs iekavās, tāpēc "a" kļūs vienāds ar divi, bet "b" kļūs vienāds ar 1. Funkcija tiks izpildīta un "c" kļūs vienāds ar 3 .

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

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

Viena no visbiežāk izmantotajām līdzīgām funkcijām ir kursora pārvietošana uz LCD displeja lcd_gotoxy(0,0); kas, starp citu, ņem arī argumentus - x un y koordinātas.

Vēl viena funkcijas izmantošanas iespēja, kad tā atgriež vērtību, tagad tā vairs nebūs nederīga, uzlabosim iepriekšējo funkcijas piemēru divu skaitļu pievienošanai:

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

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

Rezultāts būs tāds pats kā pēdējo reizi c=3, taču ņemiet vērā, ka mainīgajam “c” mēs piešķiram tādas funkcijas vērtību, kas vairs nav spēkā neesoša, bet atgriež divu int tipa skaitļu summu. Tādā veidā mēs neesam piesaistīti konkrētam mainīgajam “c”, kas palielina elastību funkciju lietošanā. Vienkāršs šādas funkcijas piemērs ir ADC datu nolasīšana, funkcija atgriež izmērīto vērtību result=read_adc();. Beigsim ar funkcijām.

Tagad pāriesim pie masīviem. Masīvs ir saistīti mainīgie. Piemēram, jums ir sinusa tabula ar vairākiem punktiem, jūs neveidosiet mainīgos int sinus1=0; int sinus2=1; utt. Šim nolūkam tiek izmantots masīvs. Piemēram, varat izveidot šādu trīs elementu masīvu:
int sinus=(0,1,5);
Kopējais masīva elementu skaits ir norādīts kvadrātiekavās. Trešā elementa vērtību mainīgajam “c” var piešķirt šādi:
с=sinuss;
Lūdzu, ņemiet vērā, ka masīva elementu numerācija sākas no nulles, t.i. "c" kļūs vienāds ar pieci. Šim masīvam nav sinusa elementa!!!
Varat piešķirt vērtību atsevišķam elementam, piemēram:
sinuss=10;

Jūs, iespējams, jau pamanījāt, ka CodeVision nav virkņu mainīgo. Tie. jūs nevarat izveidot mainīgo virkni hello=”hello”; Lai to izdarītu, jums būs jāizveido atsevišķu rakstzīmju masīvs.

lcd_putchar(sveiki); lcd_putchar(sveiki); lcd_putchar(sveiki);

utt.
Tas izrādās diezgan apgrūtinoši, šeit palīgā nāk cikli.
Piemēram, kamēr cilpa

while(PINB.0!=0) ( )

Kamēr poga nav nospiesta, nedariet neko - palaidiet tukšu cilpu.

Vēl viena iespēja ir for cilpa

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

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

Nozīme ir tieši tāda pati kā kamēr, tiek pievienots tikai sākotnējais nosacījums i=0 un nosacījums, kas tiek izpildīts katrā ciklā i++. Kods cilpas iekšpusē ir pēc iespējas vienkāršots.

Pēc programmas uzrakstīšanas tiek apkopots avota kods, un, ja kļūdu nav, jūs saņemsit kāroto programmaparatūru projekta mapē. Tagad jūs varat mirgot mikrokontrolleri un baudīt ierīces darbību.

Jums nevajadzētu nekavējoties mēģināt savā programmaparatūrā izmantot cilpas, masīvus un funkcijas. Jūsu galvenais uzdevums ir panākt, lai programmaparatūra darbotos, tāpēc dariet to tā, kā jums ir vieglāk, un nepievērsiet uzmanību koda lielumam. Pienāks laiks, kad gribēsies ne tikai rakstīt darba kodu, bet rakstīt to skaisti un kompakti. Pēc tam būs iespējams iedziļināties C valodas savvaļā. Tiem, kas vēlas apgūt visu, vēlreiz iesaku grāmatu “Kā programmēt C valodā”, ir daudz piemēru un uzdevumu. Instalējiet Visual Studio, izveidojiet win32 konsoles lietojumprogrammu un praktizējiet tur pēc sirds patikas.


Šajā avr apmācības kursā es mēģināju aprakstīt visus mikrokontrolleru programmēšanas iesācējiem paredzētos pamatus avr. Visi piemēri ir veidoti uz mikrokontrollera atmega8. Tas nozīmē, ka, lai atkārtotu visas nodarbības, jums būs nepieciešams tikai viens MK. Proteus tiek izmantots kā elektroniskās shēmas emulators - manuprāt, labākais risinājums iesācējiem. Programmas visos piemēros ir rakstītas C kompilatorā avr CodeVision AVR. Kāpēc ne kādā montētājā? Tā kā iesācējs jau ir piekrauts ar informāciju, un programma, kas reizina divus skaitļus, aizņem apmēram simts rindiņas assemblerā, un sarežģītos, drosmīgos projektos viņi izmanto C. CodeVision AVR kompilators ir pielāgots atmel mikrokontrolleriem, ir ērts kodu ģenerators, labs interfeiss un tieši no Jūs varat mirgot mikrokontrolleri ar to.

Šis apmācības kurss izskaidros un ar vienkāršiem piemēriem parādīs, kā:

  • Sāciet programmēt mikrokontrollerus, kur sākt, kas jums nepieciešams.
  • Kādas programmas izmantot AVR programmaparatūras rakstīšanai, koda simulēšanai un atkļūdošanai datorā,
  • Kādas perifērijas ierīces atrodas MK iekšpusē, kā tās vadīt, izmantojot savu programmu
  • Kā uzrakstīt gatavu programmaparatūru mikrokontrollerī un kā to atkļūdot
  • Kā izveidot PCB savai ierīcei
Lai spertu pirmos soļus MK programmēšanas virzienā, jums būs nepieciešamas tikai divas programmas:
  • Proteus ir emulatora programma (tajā jūs varat izveidot shēmu, neizmantojot īstu lodēšanu, un pēc tam pārbaudīt mūsu programmu šajā shēmā). Vispirms mēs uzsāksim visus Proteus projektus, un tad varēsim pielodēt īsto ierīci.
  • CodeVisionAVR ir C programmēšanas valodas kompilators AVR. Tajā mēs izstrādāsim programmas mikrokontrolleram, un tieši no tā būs iespējams mirgot īstu MK.
Pēc Proteus instalēšanas palaidiet to
Viņš aicina apskatīt projektus, kas viņam nāk līdzi, mēs pieklājīgi atsakāmies. Tagad izveidosim tajā visvienkāršāko shēmu. Lai to izdarītu, noklikšķiniet uz ikonas un vizuāli nekas nenotiek. Tagad jums jānoklikšķina uz mazā burta P (izvēlēties no bibliotēkas) komponentu saraksta panelī tiks atvērts komponentu atlases logs
maskas laukā ievadām tā komponenta nosaukumu, kuru vēlamies atrast bibliotēkā. Piemēram, mums jāpievieno mega8 mikrokontrolleris
rezultātu sarakstā norādiet uz mega8 un nospiediet pogu labi. Mega8 mikrokontrolleris parādās mūsu komponentu sarakstā
Tādējādi komponentu sarakstam pievienojam vēl vienu rezistoru, laukā ievadot vārdu maska res un LED vadīja

Lai diagrammā novietotu daļas, noklikšķiniet uz detaļas, pēc tam noklikšķiniet uz diagrammas lauka, atlasiet komponenta atrašanās vietu un noklikšķiniet vēlreiz. Lai diagrammai kreisajā pusē pievienotu zemējumu vai vispārīgu negatīvu, noklikšķiniet uz “Termināls” un atlasiet Zemējums. Tādējādi, pievienojot visas sastāvdaļas un savienojot tās, mēs iegūstam šo vienkāršo shēmu
Tas ir viss, tagad mūsu pirmā shēma ir gatava! Bet jūs varētu jautāt, ko viņa var darīt? Nekas. Nekas, jo lai mikrokontrolleris darbotos, vajag uzrakstīt tam programmu. Programma ir to komandu saraksts, kuras izpildīs mikrokontrolleris. Mums ir nepieciešams, lai mikrokontrolleris tiktu uzstādīts uz kājas PC0 loģiskais 0 (0 volti) un loģiskais 1 (5 volti).

Programmas rakstīšana mikrokontrolleram

Programmu rakstīsim C valodā, izmantojot CodeVisionAVR kompilatoru. Pēc CV palaišanas tas mums jautā, ko mēs vēlamies izveidot: avotu vai projektu Mēs izvēlamies pēdējo un noklikšķiniet uz Labi. Tālāk mums tiks lūgts palaist CVAVR CodeWizard vedni (tas ir nenovērtējams rīks iesācējam, jo ​​tas var ģenerēt programmas galveno skeletu) izvēlēties
Vednis sākas ar aktīvo cilni Chip, šeit mēs varam atlasīt mūsu MK modeli - tas ir mega8, un frekvenci, ar kādu MK darbosies (pēc noklusējuma mega8 ir iestatīta frekvence 1 megaherts), tāpēc mēs iestatām viss, kā parādīts iepriekš redzamajā ekrānuzņēmumā. Dodieties uz cilni Ports
Atmega8 mikrokontrolleram ir 3 porti: ports C, ports D, ports B. Katram portam ir 8 kontakti. Portu kājas var būt divos stāvokļos:
  • Izeja
Izmantojot DDRx.y reģistru, mēs varam iestatīt tapu kā ievadi vai izvadi. Ja iekšā
  • DDRx.y = 0 - izvade darbojas kā IEEJA
  • DDRx.y = 1 tapa darbojas IZEJA
Kad tapa ir konfigurēta kā izeja, mēs varam iestatīt to uz loģisko 1 (+5 volti) un loģisko 0 (0 volti). Tas tiek darīts, rakstot uz PORTx.y reģistru. Tālāk mēs detalizēti runāsim par I/O portiem. Tagad mēs iestatām visu, kā parādīts ekrānuzņēmumā, un noklikšķiniet uz Fails-> Ģenerēt, saglabāt un iziet. Tālāk CodeWizard liks mums saglabāt projektu, mēs to saglabājam un skatāmies kodu:

#iekļauts //bibliotēka laika aizkaves izveidei void main(void) ( PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x01; // padarīt PC0 tapu par izvadi PORTD=0x00; DDRD=0x00; // Timer/Counter 0 inicializācija TCCR0=0x00 // Timer/Counter TCCR1L=0x00 OCR1BL=0x00 Pārtraukuma(-u) inicializācija TIMSK=0x00 // Analog Comparator inicializācija ACSR=0x80, kamēr (1) ( )


Šeit viss tev var šķist biedējošs un nepazīstams, bet patiesībā viss tā nav. Kodu var vienkāršot, novēršot to MK perifērijas ierīču inicializāciju, kuras mēs neizmantojam. Pēc vienkāršošanas tas izskatās šādi:

#iekļauts //bibliotēka darbam ar mega8 mikrokontrolleri #include //bibliotēka laika aizkaves izveidei void main(void) ( DDRC=0x01; /* padarīt PC0 tapu par izvadi Ieraksts 0x01 jums var šķist nepazīstams, un tas ir tikai skaitlis 1 heksadecimālā formā, šī rinda būs līdzvērtīga uz 0b00000001 binārā, tad es rakstīšu šādi.*/ kamēr (1) ( )


Viss ir kārtībā. Bet, lai LED mirgotu, mums ir jāmaina PC0 tapas loģikas līmenis. Lai to izdarītu, galvenajai cilpai jāpievieno vairākas rindas:

#iekļauts //bibliotēka darbam ar mega8 mikrokontrolleri #include //bibliotēka laika aizkaves izveidei void main(void) ( DDRC=0x01; /* padarīt PC0 tapu par izvadi Ieraksts 0x01 jums var šķist nepazīstams, un tas ir tikai skaitlis 1 heksadecimālā formā, šī rinda būs līdzvērtīga uz 0b00000001 binārā, tad es to uzrakstīšu tieši šādi.*/ while (1) // programmas galvenā cilpa (// atver programmas galvenās cilpas operatora iekava PORTC.0=1; / / iestatīt pieslēgvietu C 1 uz delay_ms(500) // uzlikt 500 milisekundes aizkavi. ;//aizver galvenās programmas cilpas operatora iekava)


Tas arī viss, kods tagad ir gatavs. Noklikšķiniet uz ikonas Veidot visus projekta failus, lai apkopotu (tulkot MK procesora instrukcijās) mūsu programmu. Exe mapē, kas atrodas mūsu projektā, vajadzētu parādīties failam ar hex paplašinājumu, tas ir mūsu programmaparatūras fails MK. Lai mūsu programmaparatūru ievadītu Proteus virtuālajā mikrokontrollerā, jums ir jāveic dubultklikšķis uz Proteus mikrokontrollera attēla. Parādīsies šāds logs
Noklikšķiniet uz mapes ikonas laukā Programmas fails, atlasiet mūsu programmaparatūras hex failu un noklikšķiniet uz Labi. Tagad mēs varam palaist mūsu ķēdes simulāciju. Lai to izdarītu, Proteus loga apakšējā kreisajā stūrī noklikšķiniet uz pogas "Atskaņot".


Dalīties