Prosedyre for programmering av avr mikrokontrollere. Råd for nybegynnere av mikrokontrollerprogrammerere. Nødvendig sett med programmer

Så vi sorterte ut arbeidet til kjernen angående overganger og adressering. Det er på tide å rette oppmerksomheten mot et annet område - minnet.

Det er to typer av det (EEPROM teller ikke siden det vanligvis er en perifer, men mer om det senere):

  • RAM - RAM
  • ROM - ROM, aka flash, aka programminne

Siden arkitekturen vår er Harvard, har operatøren sin egen adressering, og blitsen har sin egen. I dataarket kan du se RAM-adresseringsstrukturen.

Vær oppmerksom på adressene med en gang! RON og perifere registre, samt RAM er plassert i samme adresserom. De. adresser fra 0000 til 001F opptar våre registre, så opp til adresse 005F er det I/O-celler - porter. Gjennom portene konfigureres alt som er om bord på kontrolleren. Og først da, fra adresse 0060, kommer RAM-en vår, som vi kan bruke til det tiltenkte formålet.

Vær dessuten oppmerksom på at I/O-registrene også har sin egen adressering - adresserommet til I/O-registrene (fra 00 til 3F), det er angitt på venstre side av figuren. IO/Register Block Denne adresseringen fungerer KUN i OUT- og IN-instruksjoner Dette fører til en interessant funksjon.

Perifere registre kan nås på to forskjellige måter:

  • Via IN/OUT-kommandoer på en kort adresse i I/O-adresserommet
  • Gjennom en gruppe LOAD/STORE-kommandoer på en full adresse i RAM-adresserommet

Eksempel. La oss ta inngangsregisteret til den asynkrone transceiveren UDR; den har adressen 0x0C (0x2C); adressen i det generelle adresserommet er angitt i parentes.

LDI R18,10; Vi lastet inn tallet 10 i register R18. Akkurat sånn OUT UDR,R18 ; Utledet på den første måten, kompilatoren selv; Erstatter verdien 0x0C i stedet for UDR STS 0x2C,R18 ; De tok meg ut den andre veien. Via Store-kommandoen; Ved å skrive inn adressen direkte.

Begge metodene gir identiske resultater. MEN! De som fungerer ved å adressere i input/output-rommet (OUT/IN) er to byte kortere. Dette er forståelig - de trenger ikke å lagre dobbelbyte-adressen til en vilkårlig minnecelle, og den korte adressen til input-output-plassen passer inn i dobbelbyte-instruksjonskoden.

Riktignok er det en annen vits her. Faktum er at hvert år dukker det opp flere og flere steiner fra AVR og det er mer og mer kjøtt i dem. Og hver knitring trenger sine egne perifere I/O-registre. Og nå har vi nådd det punktet hvor ATMega88 (som erstattet Mega8) allerede har så mange perifere enheter at I/O-registrene ikke lenger passer inn i grensen for 3F adresseplass.

Oops, de har kommet. Og det er her de som bytter fra gamle steiner til nye begynner å uttrykke forundrede uttrykk – hvorfor fungerer UT/INN-kommandoene på noen perifere registre, men ikke på andre?

Og det er enkelt - det var ikke nok dybde.

Men kjernen er én, den kan ikke lenger lages om. Og her opptrådte ATMEL-folket utspekulert – de innførte de såkalte minnekartlagte registrene. De. alle de registrene som ikke passet inn i 3F-grensen er nå tilgjengelig på bare én måte - gjennom Load/Store.

For en vits. Hvis du åpner noen m88def.inc, så kan du se hvilke av I/O-registrene som er "riktige" og hvilke som er minnekartlagt.

Det vil være noe sånt som dette:

; ***** I/O REGISTER DEFINISJONER **************************************** ******** * ; MERK: ; Definisjoner merket "MEMORY MAPPED" er utvidede I/O-porter; og kan ikke brukes med IN/OUT-instruksjoner .equ UDR0 = 0xc6 ; MINNE MAPPET .equ UBRR0L = 0xc4 ; MINNE MAPPET .equ UBRR0H = 0xc5 ; MINNE MAPPET .equ UCSR0C = 0xc2; MINNE MAPPET .equ UCSR0B = 0xc1; MINNE KORTlagt .equ UCSR0A = 0xc0; MINNE MAPPET bla bla bla, og mye mer.equ OSCCAL = 0x66 ; MINNE MAPPET .equ PRR = 0x64; MINNE MAPPET .equ CLKPR = 0x61; MINNE MAPPET .equ WDTCSR = 0x60; MINNE MAPPET .equ SREG = 0x3f;<------ А тут пошли обычные.equ SPL = 0x3d .equ SPH = 0x3e .equ SPMCSR = 0x37 .equ MCUCR = 0x35 .equ MCUSR = 0x34 .equ SMCR = 0x33 .equ ACSR = 0x30

Dette er paiene.

Og i dette feltet forstår du at et stort lodnet orgel flyr mot kompatibiliteten på tvers av modeller for monteringskoden med mål om å dekke det tett. Tross alt er det én ting å korrigere alle slags makrodefinisjoner og definisjoner som beskriver registre, og en annen å sitte og, som Askepott, skille de riktige portene fra de gale.

Det finnes imidlertid en løsning. Makrospråk! Liker du ikke kommandosystemet? Lag din egen med blackjack og horer!
La oss bygge vårt eget team UOUT, som en universell OUT

Tilsvarende for IN-kommandoen. Generelt, med slike makroer kan du diversifisere assembleren veldig, og gjøre den om til et kraftig programmeringsspråk som kan rive i stykker alle slags C og Pascal som en fille.

Vel, hva snakker jeg om... om RAM.

Så vi ordnet adresseringen. Nå vet du hvor du skal lete etter minneadressene der brukerens RAM-celler starter - i dataarket, Memory Map-delen. Men det for referanse å vite.

Og i koden vår starter RAM med direktivet. DSEG Husker du malen vår?

Inkluder "m16def.inc" ; Vi bruker ATMega16 ;= Start macro.inc =============================== ; Makroer her;= Slutt makro.inc =============================================== RAM ================================================= ============ .DSEG ; RAM-segmentet; FLASH ================================================= ========== .CSEG ; Kodesegment; EEPROM ================================================== ======== .ESEG ; EEPROM-segment

Etter .DSEG kan vi sette våre variabler. Og her har vi rett og slett et utbrudd av celler - okkuper hvilken som helst. Skriv inn adressen og vær fornøyd. Men hvorfor telle adresser manuelt? La kompilatoren tenke her.

Derfor vil vi ta og sette en etikett

0x0060 ## ;Variables 0x0061 ## 0x0062 ## 0x0063 ## ;Variables2 0x0064 ## 0x0065 ## ;Variables4 kunne starte her

Som ## hvilken som helst byte. Som standard FF. Det er selvfølgelig ingen grunn til å snakke om inntasting av variabler, initialisering, overløpskontroll og andre borgerlige gleder. Dette er Sparta! Jeg mener, montør. Alt for hånd.
Hvis vi trekker en analogi med C, så er det som å jobbe med hukommelse gjennom tomromspekere alene. Sishniks vil forstå. De vil forstå og bli forferdet. Fordi denne verden er grusom og forrædersk. Jeg feilberegnet indeksen litt og mistet andre data. Og pokker du vil fange denne feilen hvis den ikke dukker opp med en gang.

Så oppmerksomhet, oppmerksomhet og atter oppmerksomhet. Vi kjører alle minneoperasjoner gjennom sporing og ingenting vil svikte eller flyte over.

.ORG-direktivet fungerer også i datasegmentet.Det fungerer akkurat på samme måte - det overfører adresser, i dette tilfellet merker, herfra til slutten av minnet. Bare en subtilitet - ORG 0000 vil gi oss begynnelsen av RAM, og dette er R0 og andre registre. Og null kilometer RAM med Mega16 som eksempel vil gi ORG 0x0060. Og i andre kontrollere er det en annen verdi. Det er lat å gå gjennom dataarket hver gang, så det er en slik makrodefinisjon som SRAM_START, som indikerer starten på RAM for en spesifikk MK.

Så hvis vi vil at begynnelsen av RAM-minnet, for eksempel 100 byte, skal ligge under en slags søppelbuffer, så gjør vi dette trikset.

1 2 3 4 .DSEG .ORG SRAM_START+100 Variabler: .byte 3

DSEG .ORG SRAM_START+100 Variabler: .byte 3

Ferdig, vi ryddet buffersonen fra begynnelsen til 100.

Ok, vi har ordnet adresseringen. Hvordan jobbe med minneceller? Og for disse formålene er det to grupper av kommandoer. LOAD og STORE er den største gruppen av kommandoer.

Faktum er at ingenting kan gjøres med en RAM-celle annet enn å laste en byte inn i den fra RON, eller å laste ut en byte fra den til RON.

Store (ST**) kommandoer skrives til RAM, og Load (LD**) kommandoer leses.

Lesing går til register R16…R31, og celleadressen spesifiseres enten direkte i kommandoen. Her er et enkelt eksempel. Det er en variabel variabel på tre byte, den må økes med 1. Det vil si. utføre Variables++-operasjon

DSEG-variabler: .byte 3 Variables2: .byte 1 .CSEG ; Variabelen er i minnet; først må du få den. LDS R16, Variabler ; Les den første variabelbyten i R16 LDS R17, Variables+1 ; Les den andre variabelbyten i R17 LDS R18, Variables+2 ; Vel, den tredje byten i R18; La oss nå legge til 1 til det, fordi AVR kan ikke bare legge til med en konstant; for å trekke fra, må du forvrenge. Det gir imidlertid ingen spesielle problemer. SUBI R16,(-1); generelt er SUBI en subtraksjon, men -(- gir + SBCI R17,(-1) ; Og her er overføringen tatt i betraktning. Men mer om det senere. SBCI R18,(-1) ; Matematikk i assembler er en annen historie STS Variables, R16 ; Lagre alt er som det var STS Variables+1,R17 STS Variables+2,R18

Eller du kan bruke en annen metode. Indirekte registrering via indeksregister.

DSEG-variabler: .byte 3 Variables2: .byte 1 .CSEG ; Ta adressen til vår variabel LDI YL,low(Variables) LDI YH,High(Variables) ; Variabelen er i minnet; først må du få den. LD R16, Y+; Les den første variabelbyten i R16 LD R17, Y+ ; Les den andre variabelbyten i R17 LD R18, Y+ ; Vel, den tredje byten i R18; La oss nå legge til 1 til det, fordi AVR kan ikke bare legge til med en konstant; for å trekke fra, må du forvrenge. Det gir imidlertid ingen spesielle problemer. SUBI R16,(-1); egentlig er SUBI en subtraksjon, men -(- gir + SBCI R17,(-1) ; Og her er overføringen tatt i betraktning. Men mer om det senere. SBCI R18,(-1) ; Matematikk i assembler er en annen historie ST -Y,R18 ; Vi beholder alt som det var. ST -Y,R17 ; Men i omvendt rekkefølge ST -Y,R16

Operasjoner med etter- og før-dekrement brukes allerede her. I den første leser vi først, så legger vi til adressen 1. I den andre trekker vi først 1 fra adressen, og lagrer deretter.

Det er praktisk å bruke slike inkrementelle kommandoer for å iterere gjennom arrays i minnet eller tabeller.
Og det er også en indirekte relativ skrive/lese LDD/STD og andre alternativer for alle tre typer indekser (X,Y,Z). Generelt røyk dataarket og kommandosystemet.

Stable
Å, stakken er en flott ting. Det jeg elsker med det er at stabelavbrudd gjør et fungerende program til et komplett rot. Fordi stabeloperasjoner krever økt oppmerksomhet, fordi hvis en stabel er ødelagt et sted og du ikke kan spore den med en gang, vil du fange den senere... Generelt sett er det en skjønnhet, ikke en dings.

Hvorfor elsker jeg deg? Vel, hvis C er et dumt håndverk, raskt og effektivt, så er montering en filigrankunst. Hvordan galninger som Jim nagler mesterverk fra papir og bare fra papir, selv om det ser ut til at du kan kjøpe en ferdig prefabrikkert modell og lim for din egen fornøyelse. Så også her – selve prosessen er overveldende. Inkludert fra bryet med feilsøking :))))

Så om stabelen. Hva det er? Og dette er minneområdet. Fungerer etter prinsippet om en stabel. De. Den siste han la fra seg, tok han den første.

Stabelen har en peker som peker til toppen av stabelen. Et spesielt register SP er ansvarlig for stabelpekeren, eller rettere sagt er det et registerpar SPL og SPH. Men i mikrokontrollere med en liten mengde RAM, for eksempel i Tini2313, er det bare SPL

Når kontrolleren starter, er vanligvis det første de gjør initialisering av stabelen, og skriver i SP adressen til bunnen, hvorfra den vil vokse. Vanligvis er dette slutten på RAM, og det vokser mot begynnelsen.

Dette gjøres på denne måten, helt i starten av programmet:

1 2 3 4 5 LDI R16,Lav(RAMEND) OUT SPL,R16 LDI R16,Høy(RAMEND) OUT SPH,R16

LDI R16,Lav(RAMEND) OUT SPL,R16 LDI R16,Høy(RAMEND) OUT SPH,R16

Der RAMEND er en makrodefinisjon som indikerer slutten av RAM i gjeldende MK.

Det er det, stabelen er klar til å gå. Data skyves på stabelen ved å bruke PUSH Rn-kommandoen, og hentes via POP Rn.
Rn er hvilken som helst av RON.

Kommandoene CALL, RCALL, ICALL, RET, RETI og calling a interrupt fungerer også med stabelen, men mer om det senere.

La oss leke med stabelen for å føle hvordan den fungerer, for å forstå hvordan og hvor den beveger seg.

Skriv inn følgende kode i studioet:

CSEG ; LDI-kodesegment R16,Lav(RAMEND) ; Stabelinitialisering OUT SPL,R16 LDI R16,Høy(RAMEND) OUT SPH,R16 LDI R17,0 ; Lasteverdier LDI R18.1 LDI R19.2 LDI R20.3 LDI R21.4 LDI R22.5 LDI R23.6 LDI R24.7 LDI R25.8 LDI R26.9 PUSH R17 ; Vi legger verdiene på stabelen PUSH R18 PUSH R19 PUSH R20 PUSH R21 PUSH R22 PUSH R23 PUSH R24 PUSH R25 PUSH R26 POP R0 ; Pop-verdier fra stabelen POP R1 POP R2 POP R3 POP R4 POP R5 POP R6 POP R7 POP R8 POP R9

Kjør nå studioet trinn for trinn og se hvordan SP endrer seg. Stack Pointer kan sees i studio på samme sted som Program Counter.

Først initialiserer vi stabelen og laster registrene med data. Resultatet blir følgende bilde:

Deretter, ved å bruke POP-kommandoen, henter vi data fra stabelen. Vær oppmerksom på at det ikke spiller noen rolle for oss hvor vi legger dataene på stabelen og hvor vi laster dem. Det viktigste er rekkefølgen på installasjonen! Vi legger den inn fra de høyere registrene, og vil få den i de lavere. Dette vil øke stabelpekeren.

PUSH R16 PUSH R17 POP R16 POP R17

For eksempel har jeg allerede snakket om begrensningen av lavere RON - de lar deg ikke skrive et tall direkte inn i deg selv. Kun gjennom registrene til seniorgruppen. Men dette er upraktisk!

Problemet løses ved hjelp av en makro. Jeg kalte det LDIL - LDI lav

MAKRO LDIL PUSH R17; La oss lagre verdien til et av de høyere registrene på stabelen. LDI R17,1; La oss laste inn vår umiddelbare verdi MOV @0,R17 i den; La oss overføre verdien til registeret til den lave gruppen. POP R17; La oss gjenopprette verdien til det høyeste registeret fra stabelen. .ENDM

Nå kan du enkelt bruke vår hjemmelagde kommando.

1 LDIL R0,18

Over tid får filen med makroer slike hjemmelagde kommandoer og arbeidet blir enkelt og hyggelig.

Stabelfeil
Stabelen vokser mot dataene, og forestill deg nå at vi har en tilstandsvariabel i minnet og den ligger på adressen, for eksempel 0x0450. Farlig nær toppen av stabelen. Variabelen lagrer for eksempel tilstanden til den endelige tilstandsmaskinen som den videre logikken til programmet avhenger av. La oss si at hvis det er 3, så går vi og gjør én ting, hvis det er 4 så noe annet, hvis det er 5 så noe annet og så videre opp til 255 tilstander. Og i henhold til arbeidslogikken, etter 3 skal det være 4re, men ikke 10

Og så var det 3. Og så, i et forferdelig øyeblikk, falt forholdene så mye sammen at stabelen vokste og toppen nådde denne variabelen, la inn en verdi der, for eksempel 20, og så falt greyhounden tilbake. Å legge møkka bak seg er et klassisk eksempel på stabeloverflyt. Og logikken i programmet kollapset fullstendig på grunn av dette.

Eller det motsatte eksempelet - stabelen ble skjøvet opp til variablene, men i det øyeblikket ble variablene oppdatert og overskrev stabeldataene. Som et resultat ble noe galt fjernet fra stabelen (vanligvis skjeve returadresser) og programmet krasjet. Dette alternativet er forresten mye mer harmløst, fordi... i dette tilfellet er jamben synlig umiddelbart og den dukker ikke opp PLUTSELIG etter at Gud vet hvor lenge.

Dessuten kan denne feilen vises og forsvinne. Avhengig av hvordan programmet fungerer og hvor dypt det laster stabelen. Imidlertid er en slik bummer mer vanlig når du skriver i C, hvor du ikke kan se hvor aktivt arbeid med stabelen foregår. På ASMA er alt mye mer gjennomsiktig. Og her kan dette oppstå på grunn av en ærlig skjev algoritme.

Montører møter ofte andre stabelfeil. Først av alt, glemsel. Jeg la inn noe og glemte å ta det ut. Hvis problemet var i en subrutine eller et avbrudd, blir returadressen forvrengt (mer om det litt senere), stabelen blir revet av og programmet kollapser umiddelbart. Eller uoppmerksomhet - jeg lagret dataene i én rekkefølge og hentet dem i en annen. Oops, innholdet i registrene er utvekslet.

For å unngå slike feil må du først og fremst overvåke stabelen, og for det andre å planlegge plasseringen av variabler i minnet riktig. Holde de mest kritiske områdene og variablene (som tilstandsmaskiner eller programlogikkflagg) borte fra toppen av stabelen, nærmere begynnelsen av minnet.

Noen vil tro at de kan ta stabelen og plassere den ikke helt på enden av RAM-en, men et sted nærmere, og etterlate den en lomme for kritiske data. Egentlig ingen god idé. Faktum er at stabelen kan skyves både nedover ved hjelp av PUSH-kommandoen og oppover ved hjelp av POP-kommandoene. Den andre, selv om det skjer mye sjeldnere, fordi... Dette er mer en synd med skjeve hender enn en tungvint algoritme, men det skjer også.
Men hovedsaken er at selve stabelen er en veldig viktig struktur. Hele mekanismen til subrutiner og funksjoner hviler på den. Så en stabelfeil er en nødsituasjon i alle fall.

Stabelperversjoner
Mitt favorittemne. =)))) Til tross for at selve stabelpekeren beregnes under PUSH- og POP-kommandoene, er det ingen som hindrer oss i å plukke den ut av SP og bruke verdiene til å manuelt beregne adressen til dataene som ligger på. stabelen. Eller korriger stabeldataene som vi vil.
For hva? Vel, du kan finne mange applikasjoner hvis du anstrenger hjernen og begynner å tenke utenfor boksen :))))

I tillegg sendes parametere gjennom stabelen i klassisk C og Pascal på x86-arkitekturen og lokale variabler fungerer. De. Før du kaller en funksjon, skyves først alle variabler inn på stabelen, og deretter, etter å ha kalt funksjonen, blir bytes av fremtidige lokale variabler skjøvet inn i stabelen.

Deretter, ved å bruke SP som referansepunkt, kan vi behandle disse variablene som vi vil. Og når stabelen frigjøres med POP-kommandoen, blir de tilintetgjort, noe som frigjør minne.

I AVR er alt noe annerledes (tilsynelatende på grunn av den lille mengden minne, hvor du egentlig ikke kan stikke inn i stabelen, men det er mye RON), men du kan også prøve å bruke denne mekanismen.

Riktignok ligner dette allerede på nevrokirurgi. Jeg gjorde en liten feil og pasienten er død.

Takket være stabelen og RAM, kan du klare deg med bare to eller tre registre, uten mye stress med mangelen på dem.

Flashminne

EEPROM-minnet er lite, bare noen få byte, og noen ganger må du lagre mye data, for eksempel en melding til romvesener eller en sinustabell, for ikke å kaste bort tid på å beregne det. Du vet aldri hva som må lagres i minnet på forhånd. Derfor kan data lagres i programminnet, i samme kilobyte flash som kontrolleren har om bord.

Vi skriver det ned, men hvordan kan vi få det? For å gjøre dette, må du først sette noe der.
Legg derfor til en etikett på slutten av programmet, innenfor .CSEG-segmentet, for eksempel data, og etter det, ved å bruke .db-operatoren, skriv inn dataene dine.

DB-operatoren betyr at vi bruker en byte for hver konstant. Det er også operatorer som spesifiserer dobbelbyte-konstanter DW (samt DD og DQ).

1 data: .db 12,34,45,23

data: .db 12,34,45,23

Nå peker dataetiketten til adressen til den første byten i arrayet, de resterende bytene er lokalisert ved forskyvning, og legger bare en til adressen.

En subtilitet er at kompilatoren erstatter merkeadressen, og den anser den som hoppadressen for programtelleren. Og han, hvis du husker, adresserer dobbelbyte-ord - tross alt kan lengden på kommandoen være enten 2 eller 4 byte.

Og dataene våre er byte-for-byte, og når de får tilgang til dem, adresserer kontrolleren dem også byte-for-byte. Adressen i ord er dobbelt så liten som adressen i byte, og dette må tas i betraktning når du multipliserer adressen med to.

For å laste inn data fra programminnet, bruk kommandoen fra Load Program Memory-gruppen

For eksempel, LPM Rn,Z

Den går inn i register Rn nummeret fra cellen som registerparet Z peker på. La meg minne deg på at Z er to registre, R30 (ZL) og R31 (ZH). Den lave byten til adressen legges inn i R30, og den høye byten i R31.

I koden ser det slik ut:

LDI ZL,lav(data*2) ; Vi legger inn den lave byten til adressen i registerparet Z LDI ZH,high(data*2) ; Vi legger inn den høye byten til adressen i registerparet Z; multiplikasjon med to skyldes det faktum at adressen er angitt i; i dobbelbyte-ord, men vi trenger dem i byte. ; Derfor ganger vi med to; Etter å ha lastet inn adressen, kan du laste nummeret fra minnet LPM R16, Z; i register R16 etter denne kommandoen vil det være tallet 12, ; hentet fra programminnet. ; et sted på slutten av programmet, men i .CSEG-datasegmentet: .db 12,34,45,23

Nå som vi allerede er kjent med noen av egenskapene og funksjonene til mikrokontrollere, oppstår naturligvis et logisk spørsmål: hva trengs for å programmere mikrokontrollere? Hvilke programmer og enheter trengs, og hvor kan jeg få tak i dem?


For at en mikrokontroller skal løse problemer og utføre visse funksjoner, må den programmeres, det vil si at et program eller programkode må skrives inn i den.

Struktur og rekkefølge for å skrive et program

Først av alt, før du begynner å skrive et program, eller snarere programkode, bør du tydelig forstå hvilke funksjoner mikrokontrolleren vil utføre. Derfor må du først bestemme det endelige målet for programmet. Når det er definert og fullstendig forstått, blir det utarbeidet en algoritme for programmet. En algoritme er en sekvens av kommandoutførelse. Bruken av algoritmer lar deg strukturere prosessen med å skrive kode tydeligere, og når du skriver komplekse programmer, lar det deg ofte redusere tiden brukt på utvikling og feilsøking.

Det neste trinnet etter kompilering av algoritmen er å skrive programkoden direkte. Programmer for mikrokontrollere er skrevet på språket Si eller montør . Only Assembly er mer et sett med instruksjoner enn et programmeringsspråk og er et lavnivåspråk.


Vi skal skrive programmer i C, som er et språk på høyt nivå. Programmer i C skrives mye raskere sammenlignet med lignende programmer i Assembly. I tillegg er alle komplekse programmer skrevet primært i C.

Her skal vi ikke sammenligne fordeler og ulemper ved å skrive programmer i Assembly og C. Over tid, etter å ha fått litt erfaring med MK-programmering, vil du trekke nyttige konklusjoner for deg selv.

Selve programkoden kan skrives i et hvilket som helst standard tekstredigeringsprogram, for eksempel Notisblokk. Imidlertid bruker de i praksis mer praktiske redaktører, som vil bli diskutert nedenfor.

Kompilere et program

C-koden vi skrev er ennå ikke forståelig for mikrokontrolleren, siden MK forstår kommandoer bare i det binære (eller heksadesimale) systemet, som er et sett med nuller og enere. Derfor må C-koden konverteres til nuller og enere. For dette formålet brukes et spesielt program, kalt kompilator, og selve prosessen kodetransformasjon kalles kompilering.

For å flashe MK-fastvaren, kalles en enhet Programmerer. Avhengig av typen programmerer, er inngangen koblet til en COM- eller USB-port, og utgangen er koblet til visse pinner på mikrokontrolleren.


Det er et bredt utvalg av programmerere og utviklingstavler, men vi er ganske fornøyd med den enkleste Programmerer, som i Kina ikke koster mer enn $3.


Etter at mikrokontrolleren er blinket, blir programmet feilsøkt og testet på en ekte enhet eller, som de også sier, på maskinvare.

La oss nå oppsummere trinnene for programmering av mikrokontrollere.


Når du skriver enkle programmer, kan du klare deg uten det andre punktet, det vil si uten å tegne en algoritme på papir; det er nok å holde det i hodet.

Det skal bemerkes at feilsøking og testing av programmet også utføres før flashing av MK-fastvaren.

Nødvendig sett med programmer

Det er mange nyttige og praktiske programmer for programmering av MK. De er både betalte og gratis. Blant dem er det tre hovedtyper:

1) Atmel Studio

2) CodeVisionAVR

3) WinAVR

Alle disse programmene er relatert til IDEJeg integrert D utvikling E nvironment – ​​integrert utviklingsmiljø. Du kan skrive kode i dem, kompilere og feilsøke den.

Du bør være oppmerksom på Code Vision AVR. Denne IDE gjør det enklere og raskere å skrive kode. Programmet er imidlertid betalt.

I den innledende fasen av programmeringen er det bedre å skrive alle programmer manuelt, uten noen forenklinger. Dette vil hjelpe deg raskt å tilegne deg de nødvendige ferdighetene, og i fremtiden kan du godt forstå og redigere koder skrevet av noen andre for å passe dine behov. Derfor anbefaler jeg å bruke Atmel Studio. For det første er det helt gratis og kontinuerlig oppdatert, og for det andre ble det utviklet av et selskap som produserer mikrokontrollere som vi skal lære å programmere på.

Fastvare- og programfeilsøking

Vi vil flashe mikrokontrollere ved å bruke et ekstra program.

Hvis en mikrokontroller ikke er tilgjengelig, kan operasjonen emuleres ved hjelp av programmet. Det forenkler prosessen med å feilsøke et program betraktelig selv om du har en mikrokontroller, så du trenger ikke å oppdatere den ofte, fordi enhver mikrokontroller har et begrenset antall omskrivinger, selv om dette tallet er ganske stort.

Når du blinker og feilsøker MK, er det praktisk å plassere det på et brødbrett, men dette er slett ikke nødvendig. Derfor, for større bekvemmelighet, er et brødbrett også nyttig. Det er et stort utvalg av brødbrett, men jeg anbefaler at du tar den som har så mange hull som mulig. Når vi begynner å koble til skjermer med syv segmenter, vil du begynne å sette pris på fordelene med større breadboards.

Et annet viktig element som vil være nyttig for oss er den tekniske dokumentasjonen for MK, kalt dataark. Generelt må du laste ned datablad for ATmega8 mikrokontroller.

Kiselev Roman, mai 2007 Artikkel oppdatert 26. mai 2014

Så, hva er en mikrokontroller (heretter referert til som MK)? Dette er relativt sett en liten datamaskin plassert i en enkelt integrert krets. Den har en prosessor (arithmetic logic unit, eller ALU), flash-minne, EEPROM-minne, mange registre, I/O-porter, samt ekstra bjeller og fløyter som tidtakere, tellere, komparatorer, USART-er, etc. Etter at strømmen er tilkoblet , starter mikrokontrolleren opp og begynner å kjøre programmet som er lagret i flashminnet. Samtidig kan den kontrollere en lang rekke eksterne enheter via I/O-porter.

Hva betyr dette? Dette betyr at i MK kan du implementere enhver logisk krets som vil utføre visse funksjoner. Dette betyr at MK er en mikrokrets, hvis indre innhold vi faktisk lager selv. Dette gjør det mulig, etter å ha kjøpt flere helt identiske MK-er, å sette sammen helt forskjellige kretser og enheter på dem. Hvis du vil gjøre endringer i driften av en elektronisk enhet, trenger du ikke å bruke loddebolt, du trenger bare å omprogrammere MK. I dette tilfellet trenger du ikke engang å fjerne den fra enheten din hvis du bruker en AVR, siden disse MK-ene støtter programmering i kretsløp. Dermed bygger mikrokontrollere bro over gapet mellom programmering og elektronikk.

AVR-er er 8-bits mikrokontrollere, det vil si at deres ALU kan utføre enkle operasjoner med bare 8-bits tall i en klokkesyklus. Nå er det på tide å snakke om hvilken MK vi skal bruke. Jeg jobber med en ATMega16 MK. Det er veldig vanlig og kan kjøpes i nesten alle radiodelerbutikker for omtrent 100 rubler. Hvis du ikke finner den, kan du kjøpe en hvilken som helst annen MK i MEGA-serien, men i dette tilfellet må du se etter dokumentasjon for den, siden de samme "bena" til forskjellige MK-er kan utføre forskjellige funksjoner, og, etter å ha koblet til, ser det ut til at Hvis alle konklusjonene er riktige, kan du få en fungerende enhet, eller kanskje bare en sky av stinkende røyk. Når du kjøper en ATMega16, sørg for at den kommer i en stor 40-pinners DIP-pakke, og kjøp også en stikkontakt for den som den kan settes inn i. For å jobbe med det trenger du også ekstra enheter: LED, knapper, kontakter, etc.

ATMega16 har et veldig stort antall forskjellige funksjoner. Her er noen av dens egenskaper:

  • Maksimal klokkefrekvens – 16 MHz (8 MHz for ATMega16L)
  • De fleste kommandoer utføres i én klokkesyklus
  • 32 8-biters arbeidsregistre
  • 4 fulle 8-bits I/O-porter
  • to 8-bits timer/tellere og en 16-bit
  • 10-bits analog-til-digital-omformer (ADC)
  • intern klokkegenerator på 1 MHz
  • analog komparator
  • grensesnitt SPI, I2C, TWI, RS-232, JTAG
  • kretsprogrammering og selvprogrammering
  • pulsbreddemodulasjonsmodul (PWM).

Fullstendige egenskaper for denne enheten, samt instruksjoner for deres bruk, finnes i referanseboken (datablad) for denne MK. Riktignok er den på engelsk. Hvis du kan engelsk, sørg for å laste ned dette dataarket, det inneholder mye nyttig informasjon.

La oss endelig komme i gang. Jeg anbefaler å lage et spesielt utviklings- og feilsøkingsbrett for mikrokontrolleren, der du kan sette sammen en hvilken som helst elektrisk krets med en mikrokontroller uten loddebolt (eller nesten uten). Å bruke et slikt brett vil i stor grad lette arbeidet med MK og fremskynde prosessen med å lære programmeringen. Det ser slik ut:

Hva trenger du til dette?

Først trenger du selve brettet. Jeg kjøpte en ferdig i en radiodelsbutikk for 115 rubler. Så loddet jeg alle nødvendige deler til den. Resultatet er en utrolig praktisk ting, som du kan montere enhver elektrisk krets på i løpet av få minutter ved å koble til kabler og installere mikrokretser og indikatorer.

For å koble til kretselementer er det veldig praktisk å bruke kabler med kontakter i endene. Disse kontaktene settes på "bena" som stikker ut ved siden av hver port på MK. Mikrokontrolleren skal installeres i stikkontakten, og ikke loddes til brettet, ellers vil det være veldig vanskelig å fjerne den hvis du brenner den ved et uhell. Nedenfor er pinouten til ATMEGA16 MK:

La oss forklare hvilke ben vi er interessert i nå.

  • VCC - strøm tilføres her (4,5 - 5,5 V) fra en stabilisert kilde
  • GND – grunn
  • RESET – tilbakestill (ved lavt spenningsnivå)
  • XTAL1, XTAL2 – en kvartsresonator er koblet til her
  • PA, PB, PC, PD – inngangs-/utgangsporter (henholdsvis A, B, C og D).

Alt som produserer 7-11 V DC kan brukes som strømkilde. For stabil drift av MK kreves en stabilisert strømforsyning. Som stabilisator kan du bruke mikrokretser i serien 7805. Dette er lineære integrerte stabilisatorer, hvis inngang tilføres 7-11 V like ustabilisert strøm, og utgangen er 5 V stabilisert strøm. Før og etter 7805 må du installere filterkondensatorer (elektrolytisk for filtrering av lavfrekvent interferens og keramikk for høyfrekvent). Hvis du ikke finner en stabilisator, kan du bruke et 4,5 V-batteri som strømkilde. MK-en må få strøm direkte fra den.

Nedenfor er et diagram over MK-forbindelsen:

La oss nå finne ut hva som er hva her.

BQ1 er en kvartsresonator som setter driftsfrekvensen til MK. Du kan sette hvilken som helst opptil 16 MHz, men siden vi planlegger å jobbe i fremtiden med en COM-port, anbefaler jeg å bruke resonatorer for følgende frekvenser: 14,7456 MHz, 11,0592 MHz, 7,3725 MHz, 3,6864 MHz eller 1,8432 MHz (senere) det vil bli klart hvorfor). Jeg brukte 11,0592 MHz. Det er klart at jo høyere frekvens, desto høyere hastighet på enheten.

R1 er en pull-up motstand som opprettholder en spenning på 5 V ved RESET-inngangen. Et lavt spenningsnivå på denne inngangen indikerer en tilbakestilling. Etter tilbakestillingen starter MK opp (10 - 15 ms) og begynner å kjøre programmet igjen. Siden dette er en høyimpedansinngang, kan du ikke la den "dingle i luften" - en liten pickup på den vil føre til en uventet tilbakestilling av MK. Det er nettopp dette R1 er for. For pålitelighet anbefaler jeg også å installere kondensator C6 (ikke mer enn 20 µF).

SB1 – tilbakestillingsknapp.

Kvartsresonatoren og filterkondensatoren C3 bør plasseres så nær MK som mulig (ikke lenger enn 5-7 cm), siden det ellers kan oppstå forstyrrelser i ledningene som kan føre til funksjonsfeil på MK.

Det blå rektangelet i diagrammet skisserer selve programmereren. Det er praktisk å lage det i form av en ledning, hvor den ene enden er koblet til LPT-porten, og den andre til en bestemt kontakt ved siden av MK. Ledningen bør ikke være for lang. Hvis det oppstår problemer med denne kabelen (vanligvis ikke, men alt kan skje), må du lodde Altera ByteBlaster-adapteren. Hvordan du gjør dette er skrevet i beskrivelsen av AVReal-programmereren.

Nå som vi har behandlet maskinvaren, er det på tide å gå videre til programvaren.

Det finnes flere utviklingsmiljøer for AVR-programmering. For det første er dette AVR Studio - det offisielle programmeringssystemet fra Atmel. Den lar deg skrive i assembler og feilsøke programmer skrevet i assembly, C og C++. IAR er et kommersielt programmeringssystem i C, C++ og assemblerspråk. WinAVR er en kompilator med åpen kildekode. AtmanAVR er et programmeringssystem for AVR med et grensesnitt nesten helt likt som Visual C++ 6. AtmanAVR lar deg også feilsøke programmer og inneholder mange hjelpefunksjoner som gjør det enklere å skrive kode. Dette programmeringssystemet er kommersielt, men i henhold til lisensen kan du bruke det gratis i en måned.

Jeg foreslår å begynne å jobbe med IAR som det mest transparente utviklingsmiljøet. I IAR lages et prosjekt helt for hånd; derfor, etter å ha fullført flere prosjekter, vil du allerede tydelig vite hva hver linje med kode betyr og hva som vil skje hvis du endrer den. Når du jobber med AtmanAVR, må du enten bruke en forhåndsdefinert mal, som er svært tungvint og vanskelig å forstå for en person uten erfaring, eller ha mange problemer med header-filer når du setter sammen prosjektet fra bunnen av. Etter å ha behandlet IAR, vil vi senere se på andre kompilatorer.

Så først, få litt IAR. Det er veldig vanlig og å finne det burde ikke være noe problem. Etter å ha lastet ned IAR 3.20 fra et sted, installer kompilatoren/arbeidsmiljøet og start det. Etter dette kan du begynne å jobbe.

Etter å ha lansert IAR, velg fil/ny/arbeidsområde, velg banen til prosjektet vårt og lag en mappe for det og gi det et navn, for eksempel "Prog1". La oss nå lage et prosjekt: Prosjekt / Opprett nytt prosjekt... La oss også kalle det "Prog1". Høyreklikk på prosjekttittelen i prosjekttreet og velg "Alternativer"

Her vil vi konfigurere kompilatoren for en spesifikk MK. Først må du velge ATMega16-prosessortypen på Target-fanen, merk av for Aktiver bitdefinisjoner i I/O-inkluder filer på fanen Library Configuration (slik at du kan bruke bitnavnene til forskjellige MK-registre i programkoden ), og velg C-bibliotekstypen der /EU++. I ICCAVR-kategorien må du merke av for Aktiver multibyte-støtte på Språk-fanen, og slå av optimalisering på Optimalisering-fanen (ellers vil det ødelegge vårt første program).

Deretter velger du XLINK-kategorien. Her må du bestemme formatet til den kompilerte filen. Siden vi nå setter alternativer for feilsøkingsmodusen, som beskrevet i tittelen, må vi få en feilsøkingsfil som utdata. Senere åpner vi den i AVR Studio. For å gjøre dette må du velge extension.cof, og filtypen er ubrof 7.

Klikk nå på OK, og endre deretter Debug til Release.

Gå til Alternativer igjen, hvor alle parametere unntatt XLINK er satt til det samme. I XLINK endrer du filtypen til .hex, og filformatet til intel-standart.

Det er alt. Nå kan du begynne å skrive ditt første program. Opprett en ny kilde/tekst og skriv inn følgende kode i den:

#inkludere"iom16.h" kort usignert int i; tomrom hoved( tomrom) (DDRB = 255; PORTB = 0; samtidig som(1) { hvis(PORTB == 255) PORTB = 0; ellers PORTB++; til(i=0; i

Filen "iom16.h" ligger i mappen (C:\Program Files)\IAR Systems\Embedded Workbench 3.2\avr\inc. Hvis du bruker en annen MK, for eksempel ATMega64, velger du filen "iom64.h". Disse overskriftsfilene lagrer informasjon om MK: navnene på registre, biter i registre og navnene på avbrudd. Hver enkelt pinne til port A, B, C eller D kan fungere som enten en inngang eller en utgang. Dette bestemmes av Data Direction Register (DDR). 1 gjør benet til en utgang, 0 til en inngang. Ved å sette for eksempel DDRA = 13, lager vi "benene" PB0, PB2, PB3 utganger, resten - innganger, fordi 13 i binær er 00001101.

PORTB er et register som bestemmer tilstanden til portpinnene. Etter å ha skrevet 0 der, setter vi spenningen på alle utganger til 0 V. Da er det en endeløs sløyfe. Når de programmerer MK, lager de alltid en endeløs sløyfe der MK utfører en eller annen handling til den er tilbakestilt eller til en avbrudd oppstår. I denne syklusen skriver de så å si "bakgrunnskode", som MK kjører som det siste. Dette kan for eksempel være å vise informasjon på en skjerm. I vårt tilfelle økes innholdet i PORTB-registeret til det er fullt. Etter det begynner alt på nytt. Til slutt, en ti tusen syklus for loop. Det er nødvendig for å danne en synlig forsinkelse i å bytte tilstanden til port B.



Nå lagrer vi denne filen i prosjektmappen som Prog1.c, kopierer iom16.h-filen til prosjektmappen, velger Project/Add Files og legger til “iom16.h” og “Prog1.c”. Velg Release, trykk F7, programmet kompilerer og meldingen skal vises:


Totalt antall feil: 0
Totalt antall advarsler: 0

Her er et bilde av programmereren min:

Last ned AVReal-programmereren. Kopier den (AVReal32.exe) til Release/exe-mappen, der Prog1.hex-filen skal være plassert. Vi leverer strøm til MK, kobler programmeringskabelen. Åpne Far Manager (det er mest praktisk å flashe MK), gå til denne mappen, trykk Ctrl+O. Siden vi har en helt ny MK, så greier vi

avreal32.exe +MEGA16 -o11.0592MHZ -p1 -fblev=0,jtagen=1,cksel=F,sut=1 –w

Ikke glem å angi riktig frekvens hvis du ikke bruker 11059200 Hz! Samtidig er den såkalte sikringer – registre som kontrollerer driften (bruk av en intern generator, Jtag, etc.). Etter dette er den klar til å motta det første programmet. Programmereren får den brukte LPT-porten, frekvensen, filnavnet og andre som parametere (alle er oppført i beskrivelsen av AVReal). Vi ringer:

Avreal32.exe +Mega16 -o11.0592MHz -p1 -e -w -az -% Prog1.hex

Hvis tilkoblingen er riktig, vil programmereren rapportere vellykket programmering. Det er ingen garanti for at dette vil fungere første gang (første gang du ringer programmet). Selv blir jeg noen ganger programmert andre gang. Kanskje LPT-porten er defekt eller det er forstyrrelser i kabelen. Hvis det oppstår problemer, sjekk kabelen nøye. Fra min egen erfaring vet jeg at 60 % av funksjonsfeilene er assosiert med mangel på kontakt på rett sted, 20 % med tilstedeværelsen av en unødvendig, og ytterligere 15 % med feilloddning av feil ting til feil ting. Hvis alt annet feiler, les beskrivelsen av programmereren og prøv å bygge Byte Blaster.

La oss anta at alt fungerer for deg. Hvis du nå kobler åtte LED-er til port B på MK (gjør dette med MK-en slått av, og det er lurt å inkludere 300-400 Ohm motstander i serie med LED-ene) og setter på strøm, vil et lite mirakel skje - et " bølge” vil løpe gjennom dem!

© Kiselev Roman
mai 2007

desember 2015

1. Fordeler med den foreslåtte metoden

Enhetskretser basert på mikrokontrollere (MCUer) kjennetegnes vanligvis ved en kombinasjon av to vanskelige å kombinere kvaliteter: maksimal enkelhet og høy funksjonalitet. I tillegg kan funksjonaliteten endres og utvides i fremtiden uten å gjøre noen endringer i kretsen - bare ved å bytte ut programmet (blinker). Disse funksjonene forklares av det faktum at skaperne av moderne mikrokontrollere prøvde å plassere på en brikke alt som en utvikler av en elektronisk enhet kunne trenge - i det minste så mye som mulig. Som et resultat ble det et skifte i vekt fra kretser og installasjon til programvare. Med bruk av MK er det nå mindre behov for å "laste" kretsen med deler, og det er færre forbindelser mellom komponenter. Dette gjør selvfølgelig kretsen mer attraktiv for repetisjon av både erfarne og nybegynnere elektronikkingeniører. Men som vanlig må du betale for alt. Heller ikke dette var uten vanskeligheter. Hvis du kjøper en ny MK, installer den i en krets som er riktig satt sammen av deler som kan repareres og bruker strøm, så vil ingenting fungere - enheten vil ikke fungere. Mikrokontrolleren trenger et program.

Det ser ut til at alt er enkelt med dette også - på Internett kan du finne mange ordninger med gratis fastvare. Men her er det en hake: fastvaren må på en eller annen måte "lastes opp" til mikrokontrolleren. For noen som aldri har gjort dette før, blir en slik oppgave ofte et problem og den viktigste frastøtende faktoren, som ofte tvinger dem til å forlate gledene ved å bruke MK og se etter ordninger basert på "løs" og rigid logikk. Men alt er ikke så komplisert som det kan virke ved første øyekast.

Etter å ha analysert publikasjoner på Internett, kan du se at dette problemet oftest løses på en av to måter: kjøpe en ferdig programmerer eller lage en hjemmelaget. Samtidig er publiserte kretser av hjemmelagde programmerere veldig ofte urimelig komplekse - mye mer komplekse enn det som egentlig er nødvendig. Selvfølgelig, hvis du planlegger å flashe MK hver dag, er det bedre å ha en "kul" programmerer. Men hvis behovet for en slik prosedyre oppstår sjelden, fra tid til annen, kan du klare deg uten en programmerer helt. Nei, vi snakker selvfølgelig ikke om å lære å gjøre dette med tankens kraft. Dette betyr at ved å forstå hvordan programmereren samhandler med mikrokontrolleren når vi skriver og leser informasjon i programmeringsmodusen, kan vi nøye oss med tilgjengelige verktøy for et bredere formål. Disse verktøyene må erstatte både programvare- og maskinvaredelene til programmereren. Maskinvaren må gi en fysisk tilkobling til MK-mikrokretsen, muligheten til å bruke logiske nivåer på inngangene og lese data fra utgangene. Programvaredelen skal sikre driften av algoritmen som styrer alle nødvendige prosesser. Vi legger også merke til at kvaliteten på opptak av informasjon i MK ikke avhenger av hvor "kul" programmereren din er. Det finnes ikke noe som heter "bedre registrert" eller "verre". Det er bare to alternativer: "registrert" og "ikke registrert". Dette forklares med at opptaksprosessen inne i krystallen styres direkte av MK selv. Du trenger bare å gi den strøm av høy kvalitet (ingen forstyrrelser eller krusning) og organisere grensesnittet på riktig måte. Hvis resultatene av testavlesningen ikke viser feil, er alt i orden - du kan bruke kontrolleren til det tiltenkte formålet.

For å skrive et program inn i MK uten å ha en programmerer, trenger vi en USB-RS232TTL portomformer og i tillegg. USB-RS232TTL-omformeren lar deg bruke en USB-port for å lage en COM-port som skiller seg fra den "ekte" bare ved at inngangene og utgangene bruker TTL logiske nivåer, det vil si spenning i området fra 0 til 5 volt ( du kan lese mer i artikkelen " "). I alle fall er en slik omformer nyttig å ha i "husholdningen", så hvis du ikke allerede har en, er den definitivt verdt å kjøpe. Når det gjelder de logiske nivåene, er TTL i vårt tilfelle til og med en fordel fremfor en vanlig COM-port, fordi inngangene og utgangene til en slik port kan kobles direkte til en hvilken som helst mikrokontroller drevet av 5 V, inkludert ATtiny og ATmega. Men ikke prøv å bruke en vanlig COM-port - de bruker spenninger i området fra -12 til +12 V (eller -15...+15V). I dette tilfellet er direkte tilkobling til mikrokontrolleren uakseptabel!!!

Ideen om å lage et skript for Perpetuum M-programmet, som implementerer funksjonene til programmereren, oppsto etter å ha lest en rekke publikasjoner på Internett som tilbyr visse løsninger for MK-firmware. I hvert tilfelle ble det oppdaget alvorlige mangler eller overdrevne vanskeligheter. Ofte kom jeg over programmeringskretser som inneholdt en mikrokontroller, og samtidig ble det gitt råd ganske seriøst som: "... og for å programmere mikrokontrolleren for denne programmereren trenger vi... det stemmer - en annen programmerer!" Deretter ble det foreslått å gå til en venn, se etter en betalt tjeneste, etc. Kvaliteten på programvaren som ble distribuert på nettverket for disse formålene var heller ikke imponerende - mange problemer ble lagt merke til både med funksjonalitet og med "skyen" i brukergrensesnittet. Det tar ofte mye tid å forstå hvordan du bruker et program - det må studeres selv for å utføre de enkleste handlingene. Et annet program kan gjøre noe i lang tid og flittig, men brukeren lærer at ingenting blir skrevet til MK først etter at hele firmware er fullstendig fullført og påfølgende testlesing. Følgende problem oppstår også: brukeren prøver å velge sin MK fra listen over støttede krystaller, men den er ikke på listen. I dette tilfellet vil du ikke kunne bruke programmet - inkludering i listen over manglende MK-er er som regel ikke gitt. I tillegg ser det merkelig ut å manuelt velge en kontroller fra listen, med tanke på at programmereren i mange tilfeller selv kan bestemme typen MK. Alt dette sies ikke for å kaste gjørme på eksisterende produkter, men for å forklare årsaken til utseendet til manuset til Perpetuum M-programmet, beskrevet i denne artikkelen. Problemet eksisterer virkelig, og det gjelder først og fremst nybegynnere som ikke alltid klarer å overvinne denne "veggen" for å ta sitt første skritt inn i mikrokontrollernes verden. Det foreslåtte skriptet tar hensyn til manglene som finnes i andre programmer. Maksimal "gjennomsiktighet" av algoritmens operasjon er implementert, et ekstremt enkelt brukergrensesnitt som ikke krever læring og som ikke gir noen sjanse til å bli forvirret og "klikke på feil ting." Hvis den nødvendige MK ikke er blant de støttede, kan du legge til beskrivelsen selv ved å ta de nødvendige dataene fra dokumentasjonen som er lastet ned fra MK-utviklerens nettsted. Og, viktigst av alt, er manuset åpent for studier og modifikasjoner. Hvem som helst kan åpne den i en tekstredigerer, studere og redigere den etter eget skjønn, endre eksisterende funksjoner etter smak og legge til manglende.

Den første versjonen av manuset ble laget i juni 2015. Denne versjonen gir kun støtte for Atmels ATtiny- og ATmega-seriemikrokontrollere med funksjoner for skriving/lesing av flashminne, innstilling av konfigurasjonsbiter og automatisk gjenkjenning av kontrollertype. Skriving og lesing av EEPROM er ikke implementert. Det var planer om å supplere funksjonaliteten til skriptet : legge til skriving og lesing av EEPROM, implementere støtte for PIC-kontrollere osv. Av denne grunn er scriptet ennå ikke publisert.Men på grunn av tidsmangel ble implementeringen av planen forsinket, og slik at det beste ikke blir fienden til det gode, ble det besluttet å publisere den eksisterende versjonen. Hvis allerede implementerte funksjoner ikke vil være nok, vær så snill å ikke bli opprørt. I dette tilfellet kan du prøve å legge til ønsket funksjon selv. Jeg vil ikke skjule: ideen om å lage dette skriptet har i utgangspunktet også en pedagogisk betydning. Etter å ha forstått algoritmen og lagt til noe eget til den, vil du bedre kunne forstå driften av MK i programmeringsmodus, slik at i I fremtiden vil du ikke finne deg selv i posisjonen som en jente foran en ødelagt bil, som ser ettertenksomt på innsiden og ikke forstår hvorfor det "ikke fungerer."

2. MK-grensesnitt i programmeringsmodus

Det er flere forskjellige måter å sette kontrolleren i programmeringsmodus og arbeide med den i denne modusen. Den enkleste å implementere for kontrollere i ATtiny- og ATmega-serien er kanskje SPI. Vi vil bruke den.

Men før vi begynner å vurdere signalene som er nødvendige for å generere SPI, vil vi ta en rekke forbehold. Mikrokontrolleren har konfigurasjonsbiter. Dette er noe sånt som vippebrytere, bytte som lar deg endre noen egenskaper til mikrokretsen i samsvar med prosjektets behov. Fysisk er dette ikke-flyktige minneceller, som de som et program er skrevet inn i. Forskjellen er at det er svært få av dem (opptil tre byte for ATmega), og de er ikke en del av adresserommet til noe minne. Skriving og lesing av konfigurasjonsdata utføres av separate kommandoer i MK-programmeringsmodus. Nå er det viktig å merke seg at noen konfigurasjonsbiter påvirker selve muligheten til å bruke SPI. Med noen av verdiene deres kan det vise seg at SPI ikke kan brukes. Hvis du kommer over en slik mikrokontroller, vil ikke metoden som er foreslått i denne artikkelen hjelpe. I dette tilfellet må du enten endre innstillingene til konfigurasjonsbitene i programmereren, som støtter en annen programmeringsmodus, eller bruke en annen mikrokontroller. Men dette problemet gjelder bare for brukte MK-er, eller de som noen allerede har "spilt" uten hell med. Faktum er at nye MCU-er kommer med konfigurasjonsbitinnstillinger som ikke forhindrer bruk av SPI. Dette bekreftes av testresultatene til programmererskriptet for Perpetuum M-programmet, hvor fire forskjellige MK-er (ATmega8, ATmega128, ATtiny13, ATtiny44) ble flashet. De var alle nye. Den første innstillingen av konfigurasjonsbitene var i samsvar med dokumentasjonen og forstyrret ikke bruken av SPI.

Gitt ovenstående, bør du ta hensyn til følgende biter. SPIEN-biten tillater eller nekter eksplisitt bruken av SPI, derfor må verdien i vårt tilfelle være aktiverende. RSTDISBL-biten er i stand til å snu en av utgangene til mikrokretsen (forhåndsbestemt) til inngangen til "reset"-signalet, eller ikke snu den (avhengig av verdien skrevet til denne biten). I vårt tilfelle er "reset"-inngangen nødvendig (hvis den er fraværende, vil det ikke være mulig å bytte MK til programmeringsmodus via SPI). Det er også biter av CKSEL-gruppen som spesifiserer kilden til klokkesignalet. De forhindrer ikke bruken av SPI, men de må også huskes, for hvis det ikke er noen klokkepulser i det hele tatt, eller hvis frekvensen deres er lavere enn akseptabelt for en gitt SPI-hastighet, vil det heller ikke skje noe godt. Vanligvis har nye MCU-er som har en intern RC-oscillator CKSEL-gruppebitene konfigurert til å bruke den. Dette passer oss ganske bra - klokkefunksjonen leveres uten ekstra innsats fra vår side. Det er ikke nødvendig å lodde kvartsresonatoren eller koble til en ekstern generator. Hvis de angitte bitene inneholder en annen innstilling, må du sørge for klokke i henhold til innstillingen. I dette tilfellet kan det være nødvendig å koble en kvartsresonator eller en ekstern klokkegenerator til MCU. Men i denne artikkelen vil vi ikke vurdere hvordan dette gjøres. Eksemplene på å koble til en MK for programmering i denne artikkelen er designet for det enkleste tilfellet.

Ris. 1. Datautveksling via SPI i programmeringsmodus

La oss nå gå til figur 1, hentet fra dokumentasjonen for ATmega128A MK. Den viser prosessen med å overføre en byte til MK og samtidig motta en byte fra MK. Begge disse prosessene, som vi ser, bruker de samme klokkepulsene som leveres fra programmereren til mikrokontrolleren ved SCK-inngangen - en av pinnene til mikrokretsen, som en slik rolle er tildelt i SPI-programmeringsmodus. Ytterligere to signallinjer gir datamottak og overføring én bit per klokkesyklus. Gjennom MOSI-inngangen kommer data inn i mikrokontrolleren, og lesedata hentes fra MISO-utgangen. Legg merke til de to stiplede linjene tegnet fra SCK til MISO og MOSI. De viser i hvilket øyeblikk mikrokontrolleren "svelger" databiten satt ved MOSI-inngangen, og i hvilket øyeblikk den selv setter sin egen databit til MISO-utgangen. Alt er ganske enkelt. Men for å sette MK inn i programmeringsmodus, trenger vi fortsatt et RESET-signal. La oss heller ikke glemme den vanlige GND-ledningen og VCC-strømforsyningen. Totalt viser det seg at bare 6 ledninger må kobles til mikrokontrolleren for å flashe fastvaren via SPI. Nedenfor vil vi analysere dette mer detaljert, men foreløpig vil vi legge til at datautveksling med MK i programmeringsmodus via SPI utføres i pakker på 4 byte. Den første byten av hver pakke er i utgangspunktet helt dedikert til instruksjonskoding. Den andre byten, avhengig av den første, kan være en fortsettelse av kommandokoden, eller en del av adressen, eller kan ha en vilkårlig verdi. Den tredje byten brukes primært til å sende adresser, men kan ha en vilkårlig verdi i mange instruksjoner. Den fjerde byten overfører vanligvis data eller har en vilkårlig verdi. Samtidig med overføringen av den fjerde byte mottar noen kommandoer data som kommer fra mikrokontrolleren. Detaljer for hver kommando finnes i kontrollerdokumentasjonen i tabellen kalt "SPI Serial Programming Instruction Set". Foreløpig legger vi bare merke til at hele utvekslingen med kontrolleren er bygget opp fra en sekvens av 32-bits pakker, i hver av disse sendes ikke mer enn én byte med nyttig informasjon. Dette er ikke veldig optimalt, men totalt sett fungerer det bra.

3. Koble til MK for programmering

For å sikre at alle nødvendige signaler leveres til mikrokontrollerinngangene for å organisere SPI-grensesnittet og lese data fra MISO-utgangen, er det ikke nødvendig å lage en programmerer. Dette kan enkelt gjøres ved å bruke den vanligste USB-RS232TTL-konverteren.

På Internett kan du ofte finne informasjon om at slike omformere er dårligere og at det ikke kan gjøres noe alvorlig med dem. Men med hensyn til de fleste omformermodeller er denne oppfatningen feil. Ja, det er omformere på salg som ikke har alle innganger og utganger tilgjengelig sammenlignet med en standard COM-port (for eksempel bare TXD og RXD), mens de har en ikke-separerbar design (mikrokretsen er fylt med plast - det er umulig å nå pinnene). Men disse er ikke verdt å kjøpe. I noen tilfeller kan du få de manglende portinngangene og -utgangene ved å lodde ledningene direkte til brikken. Et eksempel på en slik "forbedret" omformer er vist i figur 2 (brikke PL-2303 - flere detaljer om formålet med pinnene i artikkelen ""). Dette er en av de billigste modellene, men har sine egne fordeler når den brukes i hjemmelagde design. Fullfunksjons adapterledninger med en standard ni-pinners kontakt på enden, som en COM-port, er også utbredt. De skiller seg fra en vanlig COM-port bare i TTL-nivåer og inkompatibilitet med eldre programvare og noe eldre maskinvare. Det kan også bemerkes at ledningene på CH34x-brikken viser seg å være mye mer pålitelige og stabile i ulike ekstreme tester sammenlignet med omformere på PL-2303. Men ved normal bruk er forskjellen ikke merkbar.

Når du velger en USB-RS232TTL-omformer, bør du også være oppmerksom på kompatibiliteten til driveren med versjonen av operativsystemet du bruker.

La oss se nærmere på prinsippet om å koble til en mikrokontroller og en USB-RS232TTL-omformer ved å bruke eksemplet på fire forskjellige MK-modeller: ATtiny13, ATtiny44, ATmega8 og ATmega128. Figur 3 viser det generelle diagrammet for en slik forbindelse. Det kan overraske deg å vite at RS232-signalene (RTS, TXD, DTR og CTS) blir brukt på feil måte. Men ikke bekymre deg for det: Perpetuum M-programmet er i stand til å jobbe med dem direkte - angi utgangsverdier og les inngangstilstander. I alle fall gir de mye brukte USB-RS232TTL-omformerne på CH34x- og PL-2303-brikker denne muligheten - dette er verifisert. Det skal heller ikke være noen problemer med andre populære omformere, siden standard Windows-funksjoner brukes for å få tilgang til porten.

Motstandene vist i det generelle diagrammet kan i prinsippet ikke installeres, men det er fortsatt bedre å installere dem. Hva er formålet deres? Ved å bruke TTL-inngangene og -utgangene til omformeren og fem-volts strømforsyningen til mikrokontrolleren, slipper vi dermed behovet for å koordinere logiske nivåer - alt er allerede helt riktig. Dette betyr at forbindelsene kan være direkte. Men under eksperimenter , alt kan skje. For eksempel, ifølge ondskapens lov, kan en skrutrekker falle akkurat på et sted hvor den umulig kan falle, og kortslutte noe som ikke i noe tilfelle bør kortsluttes. Selvfølgelig kan alt vise seg å være en "skrutrekker". Motstander i dette tilfellet reduserer noen ganger konsekvensene. et av formålene deres er å eliminere en mulig utgangskonflikt.Faktum er at etter at programmeringen er fullført, går mikrokontrolleren inn i normal driftsmodus, og det kan skje at dens pin koblet til utgangen på omformeren (RTS, TXD eller DTR) også blir en utgang, i henhold til programmet som nettopp er registrert i MK. I dette tilfellet vil det være veldig ille hvis to direkte tilkoblede utganger "kjemper" - prøv å sette forskjellige logiske nivåer. I en slik "kamp" kan noen "tape", men det ønsker vi ikke.

Verdiene til de tre motstandene er valgt på nivået 4,3 KOhm. Dette gjelder koblinger mellom omformerutgangen og mikrokontrollerinngangen. Nøyaktigheten til motstandene spiller ingen rolle: du kan redusere motstanden til 1 KOhm eller øke den til 10 KOhm (men i det andre tilfellet øker risikoen for interferens når du bruker lange ledninger på vei til MK). Når det gjelder koblingen mellom omformerinngangen (CTS) og mikrokontrollerutgangen (MISO), brukes en 100 Ohm motstand her. Dette forklares av særegenhetene ved inngangen til omformeren som brukes. Under testene ble det brukt en omformer på PL-2303-mikrokretsen, hvis innganger tilsynelatende er koblet til strømforsyningen positiv med en relativt lav motstand (i størrelsesorden flere hundre ohm). For å "bryte opptrekket" måtte jeg installere en motstand med så liten motstand. Du trenger imidlertid ikke å installere det i det hele tatt. På omformeren er dette alltid inngangen. Det kan ikke bli en vei ut, noe som betyr at det ikke vil være noen utgangskonflikt i enhver utvikling av hendelser.

Hvis brikken har en separat AVCC-pinne for å drive analog-til-digital-omformeren (for eksempel ATmega8 eller ATmega128), bør den kobles til den vanlige VCC-strømpinnen. Noen IC-er har mer enn én VCC-strømpinne eller mer enn én GND. For eksempel har ATmega128 3 GND-pinner og 2 VCC-pinner. I en permanent design er det bedre å koble pinner med samme navn til hverandre. I vårt tilfelle, under programmering, kan du bruke en VCC og GND pin hver.

Og her er hvordan ATtiny13-tilkoblingen ser ut. Figuren viser pinnetilordningene som brukes ved programmering via SPI. Ved siden av bildet ser du hvordan en midlertidig forbindelse ser ut i virkeligheten.


Noen kan si at dette ikke er alvorlig - tilkoblinger på ledningene. Men du og jeg er fornuftige mennesker. Målet vårt er å programmere mikrokontrolleren, bruke et minimum av tid og andre ressurser på den, og ikke å vise seg frem foran noen. Kvaliteten lider ikke. Metoden "på ledninger" i dette tilfellet er ganske effektiv og berettiget. Flashing av kontrollerens fastvare er en engangsprosedyre, så det er ingen vits i å dekke den med rhinestones. Hvis det er ment å endre fastvaren i fremtiden uten å fjerne kontrolleren fra kretsen (i det ferdige produktet), tas dette i betraktning under installasjonen under produksjonen av enheten. Vanligvis er det installert en kontakt (RESET, SCK, MOSI, MISO, GND) for dette formålet, og MK kan bli blinket selv etter installasjon på brettet. Men dette er kreative gleder. Vi vurderer det enkleste tilfellet.

La oss nå gå videre til ATtiny44 MK. Alt er stort sett likt her. Basert på tegningen og bildet vil selv en nybegynner ikke ha noen problemer med å finne ut av sammenhengen. I likhet med ATtiny44 kan du koble til mikrokontrollerne ATtiny24 og ATtiny84 - pinnetilordningene for disse tre er de samme.


Et annet eksempel på midlertidig tilkobling av en kontroller for å programmere den er ATmega8. Det er flere pinner her, men prinsippet er det samme - noen få ledninger, og nå er kontrolleren klar til å "fylle" informasjon i den. Den ekstra svarte ledningen på bildet som kommer fra pinne 13 deltar ikke i programmeringen. Den er designet for å fjerne et lydsignal fra den etter at MK går ut av programmeringsmodus. Dette skyldes det faktum at under feilsøking av manuset til "Perpetuum M" ble musikkboksprogrammet lastet ned til MK.


Ofte er én kontroller tilgjengelig i forskjellige hus. I dette tilfellet er tilordningen av pinner for hver sak fordelt annerledes. Hvis huset til kontrolleren din ikke ligner det som er vist på figuren, sjekk formålet med pinnene i den tekniske dokumentasjonen, som kan lastes ned fra MK-utviklerens nettsted.

For å fullføre bildet, la oss se på å koble en MK-mikrokrets med et stort antall "ben". Hensikten med den ekstra svarte ledningen på bildet som kommer fra pinne 15 er nøyaktig den samme som i tilfellet med ATmega8.


Du er sannsynligvis allerede overbevist om at alt er ganske enkelt. Alle som vet hvordan man teller pinnene til mikrokretser (fra merket i en sirkel mot klokken) vil finne ut av det. Og ikke glem nøyaktigheten. Mikrokretser elsker ryddige mennesker og tilgir ikke uforsiktig behandling.

Før du går videre til programvaredelen, sørg for at USB-RS232TTL-konverteringsdriveren er riktig installert (sjekk Windows Enhetsbehandling). Husk eller skriv ned nummeret på den virtuelle COM-porten som vises når du kobler til omformeren. Dette nummeret må legges inn i teksten til manuset, som du kan lese om nedenfor.

4. Script - programmerer for "Perpetuum M"

Vi fant ut maskinvaredelen av "programmereren". Dette er allerede halve kampen. Nå gjenstår det å forholde seg til programvaredelen. Dens rolle vil bli utført av Perpetuum M-programmet under kontroll av et skript, som implementerer alle nødvendige funksjoner for å samhandle med mikrokontrolleren.

Arkivet med skriptet skal pakkes ut i samme mappe der perpetuum.exe-programmet ligger. I dette tilfellet, når du kjører perpetuum.exe-filen, vil en meny vises på skjermen med en liste over installerte skript, blant dem vil det være linjen "AVR MK Programmer" (det kan være den eneste). Dette er linjen vi trenger.

Skriptet ligger i PMS-mappen i filen "MK Programmer AVR.pms". Denne filen kan sees, studeres og redigeres om nødvendig i et vanlig tekstredigeringsprogram som Windows Notisblokk. Før du bruker skriptet, må du mest sannsynlig gjøre endringer i teksten relatert til portinnstillinger. For å gjøre dette, sjekk navnet på porten som brukes i Windows Device Manager og, om nødvendig, foreta passende endring på linjen "PortName="COM4";" - i stedet for tallet 4 kan det være et annet tall. Når du bruker en annen USB-RS232TTL-konverteringsmodell, kan det hende du må endre innstillingene for signalinversjon (skriptlinjer som begynner med ordet "Høy"). Du kan sjekke inversjonen av signaler med USB-RS232TTL-omformeren ved å bruke et av eksemplene i instruksjonene for Perpetuum M-programmet (del av funksjoner for å jobbe med porten).

MK_AVR-undermappen inneholder filer med beskrivelser av støttede kontrollere. Hvis kontrolleren du trenger ikke er blant dem, kan du legge til den du trenger selv, etter en analogi. Ta en av filene som et eksempel, og bruk et tekstredigeringsprogram, skriv inn de nødvendige dataene, ta det fra dokumentasjonen for mikrokontrolleren din. Det viktigste er å være forsiktig, skriv inn dataene uten feil, ellers vil MK ikke bli programmert, eller vil bli programmert feil. Den originale versjonen støtter 6 mikrokontrollere: ATtiny13, ATtiny24, ATtiny44, ATtiny84, ATmega8 og ATmega128. Skriptet implementerer automatisk gjenkjenning av den tilkoblede kontrolleren - det er ikke nødvendig å spesifisere det manuelt. Hvis identifikatoren lest fra MK ikke er blant de tilgjengelige beskrivelsene, vises en melding om at kontrolleren ikke kunne gjenkjennes.

Arkivet med manuset inneholder også tilleggsinformasjon. AVR controller inc files-mappen inneholder en veldig nyttig og omfattende samling av kontrollerdefinisjonsfiler. Disse filene brukes når du skriver dine egne programmer for MK. Fire flere mapper "MusicBox_..." inneholder filer med et program i Assembly-språk og fastvare klar for nedlasting til MK separat for ATtiny13, ATtiny44, ATmega8 og ATmega128. Hvis du allerede har koblet til en av disse MK-ene for programmering, som foreslått i denne artikkelen, kan du flashe den akkurat nå - du får en musikkboks. Mer om dette nedenfor.

Når du velger linjen "MK AVR Programmer" i skriptmenyen, begynner skriptet å bli utført. Samtidig åpner den porten, sender en kommando til MK om å bytte til programmeringsmodus, mottar bekreftelse fra MK om vellykket overgang, ber om MK-identifikator og søker etter en beskrivelse av denne MK ved sin identifikator blant de tilgjengelige filer med beskrivelser. Hvis den ikke finner den nødvendige beskrivelsen, viser den en tilsvarende melding. Hvis en beskrivelse blir funnet, åpnes hovedmenyen til programmereren. Du kan se skjermbildet i figur 8. Ytterligere forståelse er ikke vanskelig - menyen er veldig enkel.

I den første versjonen av skriptet er noen funksjoner til en fullverdig programmerer ikke implementert. For eksempel er det ingen måte å lese og skrive til EEPROM. Men hvis du åpner skriptet i et tekstredigeringsprogram, vil du se at det er veldig lite i størrelse, til tross for at det viktigste allerede er implementert i det. Dette antyder at det ikke er så vanskelig å legge til de manglende funksjonene - språket er veldig fleksibelt, det lar deg implementere rik funksjonalitet i et lite program. Men i de fleste tilfeller er selv de eksisterende funksjonene nok.

Noen funksjonsbegrensninger er beskrevet direkte i skriptteksten:
//implementerte opptak bare fra nulladressen (Utvidet segmentadressepost ignoreres, LOAD OFFSET - også)
//rekkefølgen og kontinuiteten til poster i HEX-filen er ikke kontrollert
//sjekksum er ikke sjekket
Dette gjelder arbeid med en HEX-fil, hvorfra fastvarekoden for MK er hentet. Hvis denne filen ikke er ødelagt, vil det ikke ha noen effekt å sjekke kontrollsummen. Hvis det er forvrengt, vil det ikke være mulig å oppdage det ved hjelp av skriptet. I de fleste tilfeller vil de gjenværende restriksjonene ikke skade, men du må fortsatt huske på dem.

5. Musikkboks - et enkelt håndverk for nybegynnere

Hvis du har en av disse mikrokontrollerne: ATtiny13, ATtiny44, ATmega8 eller ATmega128, kan du enkelt gjøre den om til en musikkboks eller musikkkort. For å gjøre dette er det nok å skrive den tilsvarende fastvaren inn i MK - en av de fire som er plassert i "MusicBox_..."-mappene i samme arkiv med skriptet. Fastvarekoder lagres i filer med filtypen ".hex". Å bruke ATmega128 til et slikt håndverk er selvfølgelig "fett", akkurat som ATmega8. Men dette kan være nyttig for testing eller eksperimentering, med andre ord for pedagogiske formål. Tekstene til programmene i Assembler er også vedlagt. Programmene ble ikke laget fra bunnen av - musikkboksprogrammet fra A.V. Belovs bok "AVR Microcontrollers in Amateur Radio Practice" ble tatt som grunnlag. Det opprinnelige programmet har gjennomgått en rekke betydelige endringer:
1. tilpasset hver av de fire MK-ene: ATtiny13, ATtiny44, ATmega8 og ATmega128
2. knapper har blitt eliminert - ingenting trenger å være koblet til kontrolleren bortsett fra strøm og en lydsender (melodier spilles etter hverandre i en endeløs loop)
3. varigheten av hver tone reduseres med varigheten av pausen mellom notene for å eliminere forstyrrelser i musikalsk rytme
4. den åttende melodien er koblet sammen, ikke brukt i bokversjonen
5. fra det subjektive: noen "forbedringer" for å optimalisere og gjøre algoritmen lettere å forstå

I noen melodier kan man høre usannhet og til og med grove feil, spesielt i «Smil» - i midten. Ringetonekodene ble hentet fra boken (eller rettere sagt, lastet ned fra bokens forfatters nettsted sammen med den originale asm-filen) og har ikke blitt endret. Tilsynelatende er det feil i kodingen av melodiene. Men dette er ikke et problem - alle som er "vennlige" med musikk kan enkelt finne ut av det og fikse alt.

I ATtiny13, på grunn av mangelen på en 16-bit teller, måtte en 8-bit teller brukes for å reprodusere noter, noe som førte til en liten reduksjon i nøyaktigheten til notene. Men dette merkes knapt på øret.

Om konfigurasjonsbitene. Innstillingene deres må samsvare med tilstanden til den nye mikrokontrolleren. Hvis din MK har blitt brukt et sted før, må du sjekke tilstanden til konfigurasjonsbitene, og om nødvendig bringe dem i tråd med innstillingene til den nye mikrokontrolleren. Du kan finne ut tilstanden til konfigurasjonsbitene til den nye mikrokontrolleren fra dokumentasjonen for denne MK (avsnittet "Fuse Bits"). Unntaket er ATmega128. Denne MCUen har M103C-biten, som muliggjør kompatibilitetsmodus med den eldre ATmega103. Aktivering av M103C-biten reduserer mulighetene til ATmega128 betraktelig, og denne biten er aktiv på den nye MK. Du må tilbakestille M103C til en inaktiv tilstand. For å manipulere konfigurasjonsbiter, bruk den tilsvarende delen av programmeringsskriptmenyen.

Det er ingen vits i å gi et diagram over musikkboksen: den inneholder bare en mikrokontroller, strømforsyning og en piezo-lydsender. Strøm tilføres på nøyaktig samme måte som vi gjorde ved programmering av MK. Lydgiveren er koblet mellom den felles ledningen (GND-pinne til kontrolleren) og en av MK-pinnene, hvor nummeret finnes i filen med programmonteringskoden (*.asm). I begynnelsen av programteksten for hver MK i kommentarene er det en linje: "lydsignalet genereres ved pinne XX." Når programmeringsskriptet er fullført, går mikrokontrolleren ut av programmeringsmodusen og går over i normal drift. Avspilling av melodier begynner umiddelbart. Ved å koble til en lydsender kan du sjekke dette. Du kan la lydsenderen være tilkoblet mens du programmerer krystallen bare hvis lyden er hentet fra en pinne som ikke brukes i SPI, ellers kan den ekstra kapasitansen på pinnen forstyrre programmeringen.