Programmering av mikrokontrollere i C fra bunnen av. CodeVisionAVR. Generell informasjon for nybegynnere i programmering i C-språket. Hvilken mikrokontroller å velge for arbeid

På en eller annen måte følte jeg meg umiddelbart tvunget til å gi råd om valg av programmeringsmiljø for AVR-kontrollere. Bare ikke kast tøfler på meg. Jeg er bare litt :)

Det er mange programmeringsspråk for mikrokontrollere. Det er også ganske mange programmeringsmiljøer og det er feil å sammenligne dem med hverandre. Beste språk programmering eksisterer ikke. Dette betyr at du må velge det språket og programmeringsmiljøet som passer best for deg.

Hvis du for øyeblikket står overfor et valg om hva du skal begynne å jobbe med, så er her noen anbefalinger for deg.

Tidligere programmeringserfaring. Ikke overse din tidligere programmeringserfaring. Selv om det var BASIC. Selv om det var lenge siden på skolen. Programmering er som å sykle – når du først starter, husker du raskt alt du har glemt. Begynn med BASIC - mestr det - senere vil det være lettere å velge noe mer egnet for dine formål.

Hjelp fra miljøet. Skriver vennene dine i Pascal? Problemet er løst for deg - skriv i Pascal! De vil alltid hjelpe deg med råd, gi deg biblioteker og gi deg ferdige prosjekter å studere. Generelt vil de gjerne ønske deg velkommen inn i samfunnet deres. Gjør du det motsatte, får du motsatt resultat. Venner av CIS-industrien vil hakke deg hvis du bestemmer deg for å studere Assembler. Ikke forvent hjelp.

God bok på AVR programmering vil hjelpe mye. Dessverre er det svært få av dem. Hvis du kommer over en bok og du tror at alt er forklart på en svært tilgjengelig måte, prøv den. Jeg anbefaler ikke å studere fra e-bøker; som en siste utvei, skriv dem ut. Det er svært upraktisk å bytte mellom miljøet og teksten i bokfilen. Det er mye mer behagelig å lese en bok og prøve den med en gang, uten å bli distrahert av å bytte; i tillegg kan du gjøre notater i margen og skrive ned ideene som dukker opp.

Programmeringsmiljøet er enklere. Hvis det er flere programmeringsmiljøer for ditt språk å velge mellom, ikke nøl, velg det som er enklere. La det være mindre funksjonelt. La henne kompilere fryktelig oppsvulmet kode. Det viktigste er å bare begynne å jobbe. Når du først blir komfortabel i et enkelt miljø, kan du enkelt flytte til et mer avansert og "riktig" miljø. Og ikke hør på de som sier at du vil miste mer tid - de tar feil. Barneskoleelever blir ikke bedt om å lese «Krig og fred», de får enklere bøker – med bilder.

Biblioteker. Tilgjengeligheten av biblioteker er kontroversiell for språkopplæring. Selvfølgelig vil de senere gjøre livet mye enklere, men til å begynne med er "Black Box"-biblioteker uforståelige og bidrar egentlig ikke til å forstå språket. På den annen side gjør de programmer lettere å lese og lar en nybegynner bygge komplekse programmer uten mye anstrengelse. Så ikke bry deg for mye om deres tilstedeværelse. I hvert fall først.

Effektiv kode.Å velge et programmeringsmiljø for å lære programmering basert utelukkende på hvor effektiv koden den kompilerer er en dårlig idé. Hovedsaken er at du føler deg komfortabel når du begynner å studere – det som kommer ut av det er det tiende. Selvfølgelig kan du jobbe med dette senere.

Veivisere. Enhver enhet om bord på brikken må konfigureres ved hjelp av porter. Prosedyren er ganske kjedelig og datablad er påkrevd. I tillegg er det nyanser som ikke er lette for en nybegynner å forstå. Derfor er det veldig ønskelig å ha veivisere i miljøet. Vyzards er automatiske tunere for SPI, I2C, USART, etc. Jo flere enheter som støttes, jo bedre. Du angir de nødvendige perifere parameterne, og veiviseren genererer selv kode som vil gi de spesifiserte parameterne. Gjør livet mye enklere.


Generelle anbefalinger slik - programmering på det innledende stadiet bør være så enkelt som mulig (selv primitivt). Programmeringsmiljøet skal være enkelt å lære (siden du for det første trenger å mestre programmering og ikke kaste bort tid på å fikle med innstillingene). Helst russifisert. En russisk manual og eksempler på programmer vil også være nyttig. Evnen til å blinke krystallen fra omgivelsene er ønskelig. Etter hvert som du mestrer det grunnleggende om programmering, kan du gå videre til mer komplekse skall.


En siste anbefaling: arbeid med en ekte krystall. Ikke vær redd for å brenne den. Få praktisk erfaring. Å jobbe med emulatorer (for eksempel Proteus), selv om det vil frigjøre deg fra mas med et loddebolt, vil aldri kunne gi deg den tilfredsstillelsen du vil få fra arbeidsprogrammet og den første blinkingen av LED! Å forstå at du har laget et ekte arbeidsdiagram med egne hender gir deg selvtillit og insentiv til å gå videre!

(Besøkt 7 377 ganger, 1 besøk i dag)

Hei, kjære Habrazhitel!

I denne artikkelen vil jeg snakke om hvordan jeg en gang bestemte meg for å begynne å programmere mikrokontrollere, hva som var nødvendig for dette og hva som endte opp med å skje.

Temaet mikrokontrollere interesserte meg for lenge siden, tilbake i 2001. Men så viste det seg å være problematisk å få en programmerer på bostedet mitt, og det var ikke snakk om å kjøpe den via Internett. Jeg måtte utsette denne saken til bedre tider. Og så, en vakker dag, oppdaget jeg at det hadde kommet bedre tider uten å forlate hjemmet, jeg kunne kjøpe alt jeg trengte. Jeg bestemte meg for å prøve det. Så det vi trenger:

1. Programmerer
Det er mange alternativer på markedet - fra de billigste ISP-programmererne (In-System Programming) for noen få dollar, til kraftige programmerer-debuggere for et par hundre. Jeg hadde ikke mye erfaring i denne saken, først bestemte jeg meg for å prøve en av de enkleste og billigste - USBasp. Jeg kjøpte den på eBay på en gang for $12, nå kan du finne den for til og med $3-4. Dette er faktisk en kinesisk versjon av programmereren fra Thomas Fischl. Hva kan jeg si om ham? Bare én ting - det fungerer. I tillegg støtter den ganske mange AVR-kontrollere i ATmega- og ATtiny-serien. Under Linux krever ingen driver.

For å flashe fastvaren må du koble programmeringsutgangene VCC, GND, RESET, SCK, MOSI, MISO med de tilsvarende utgangene til mikrokontrolleren. For enkelhets skyld satte jeg sammen hjelpekretsen direkte på brødbrettet:

Til venstre på brettet er den samme mikrokontrolleren som vi skal blinke.

2. Mikrokontroller
Jeg brydde meg ikke så mye med valget av mikrokontroller og tok ATmega8 fra Atmel - 23 I/O-pinner, to 8-bits timere, en 16-bit, frekvens opptil 16 MHz, lavt forbruk (1-3,6 mA) , billig ($2). Generelt, for en start - mer enn nok.

Under Linux fungerer kombinasjonen avr-gcc + avrdude fint for å kompilere og laste fastvare til kontrolleren. Installasjonen er triviell. Ved å følge instruksjonene kan du installere all nødvendig programvare på noen få minutter. Den eneste nyansen du bør ta hensyn til er at avrdude (programvare for opptak til kontrolleren) kan kreve superbrukerrettigheter for å få tilgang til programmereren. Løsningen er å kjøre den via sudo (ikke en veldig god idé), eller registrere spesielle udev-rettigheter. Syntaksen kan variere i forskjellige OS-versjoner, men i mitt tilfelle ( Linux Mint 15) å legge til følgende regel i filen /etc/udev/rules.d/41-atmega.rules fungerte:

# USBasp programmerer SUBSYSTEM=="usb", ATTR(idVendor)=="16c0", ATTR(idProduct)=="05dc", GROUP="plugdev", MODE="0666"

Etter dette må du selvfølgelig starte tjenesten på nytt
service udev omstart
Du kan kompilere og flashe uten problemer direkte fra kommandolinje(hvem ville tvile på det), men hvis det er mange prosjekter, så er det mer praktisk å installere en plugin og gjøre alt direkte fra Eclipse-miljøet.

For Windows må du installere en driver. Ellers er det ingen problemer. Av hensyn til vitenskapelig interesse prøvde jeg AVR Studio + eXtreme Burner-kombinasjonen på Windows. Igjen, alt fungerer utmerket.

La oss begynne å programmere

AVR-kontrollere kan programmeres både i assembler (AVR assembler) og i C. Her mener jeg at alle bør ta sitt eget valg avhengig av den spesifikke oppgaven og deres preferanser. Personlig begynte jeg først å fikle med assembler. Ved programmering i assembler blir arkitekturen til enheten tydeligere og du får følelsen av at du dykker direkte inn i kontrolleren. I tillegg tror jeg at i programmer som er spesielt kritiske i størrelse og ytelse, kan kunnskap om assembler være svært nyttig. Etter å ha blitt kjent med AVR-montøren, krøp jeg til C.

Etter å ha blitt kjent med arkitekturen og grunnleggende prinsipper bestemte jeg meg for å sette sammen noe nyttig og interessant. Her hjalp datteren min meg, hun spiller sjakk og en vakker kveld sa hun at hun ville ha en klokke for tidsbestemte partier. BAM! Her er den - ideen om det første prosjektet! Du kan selvfølgelig bestille dem på eBay, men jeg ville lage min egen klokke, med svarte... eh... indikatorer og knapper. Ikke før sagt enn gjort!

Det ble besluttet å bruke to 7-segments diodeindikatorer som display. For kontroll var 5 knapper nok - "Player 1", "Player 2", "Reset", "Settings" og "Pause". Vel, ikke glem lydindikasjonen for slutten av spillet. Ser ut som det er det. Figuren nedenfor viser et generelt diagram for tilkobling av mikrokontrolleren til indikatorer og knapper. Vi trenger det når vi analyserer kildekoden til programmet:

Debriefing

La oss starte, som forventet, fra inngangspunktet til programmet - hovedfunksjonen. Faktisk er det ikke noe bemerkelsesverdig med det - å sette opp porter, initialisere data og en endeløs løkke med prosesseringsknapptrykk. Vel, ringer sei() - muliggjør avbruddsbehandling, mer om dem litt senere.

Int main(void) ( init_io(); init_data(); sound_off(); sei(); while(1) ( handle_buttons(); ) returner 0; )
La oss se på hver funksjon separat.

Void init_io() ( // sett utgang DDRB = 0xFF; DDRD = 0xFF; // sett inngang DDRC = 0b11100000; // pull-up motstander PORTC |= 0b00011111; // timer avbryter TIMSK = (1<

Det er veldig enkelt å sette opp I/O-porter - et tall skrives inn i DDRx-registeret (hvor x er bokstaven som angir porten), og hver bit betyr om den korresponderende pinnen vil være en inngangsenhet (tilsvarer 0) eller en utgangsenhet (tilsvarer 1). Ved å sende tallet 0xFF til DDRB og DDRD laget vi derfor B- og D-utgangsporter. Følgelig er DDRC-kommandoen = 0b11100000; gjør de første 5 pinnene til port C til inngangspinner og de resterende til utgangspinner. PORTC-kommando |= 0b00011111; inkluderer interne pull-up motstander på 5 kontrollerinnganger. I følge diagrammet er knapper koblet til disse inngangene, som når de trykkes kortslutter dem til jord. På denne måten forstår kontrolleren at knappen er trykket.

Deretter kommer oppsettet av to timere, Timer0 og Timer1. Vi bruker den første til å oppdatere indikatorene, og den andre til å telle ned tiden, etter å ha konfigurert den til å utløse hvert sekund. En detaljert beskrivelse av alle konstantene og metoden for å sette tidtakeren til et spesifikt intervall finnes i ATmega8-dokumentasjonen.

Avbryt håndtering

ISR (TIMER0_OVF_vect) ( display(); if (_buzzer > 0) ( _buzzer--; if (_buzzer == 0) sound_off(); ) ) ISR(TIMER1_COMPA_vect) ( if (ActiveTimer == 1 && Timer1 > 0) ( Timer1--; if (Timer1 == 0) process_timeoff(); ) if (ActiveTimer == 2 && Timer2 > 0) ( Timer2--; if (Timer2 == 0) process_timeoff(); ) )

Når timeren utløses, overføres kontrollen til den aktuelle avbruddsbehandleren. I vårt tilfelle er dette TIMER0_OVF_vect-behandleren, som kaller prosedyren for å vise tid på indikatorer, og TIMER1_COMPA_vect, som behandler nedtellingen.

Utgang til indikatorer

Void display() ( display_number((Timer1/60)/10, 0b00001000); _delay_ms(0.25); display_number((Timer1/60)%10, 0b00000100); _delay_ms(0.25); display_number(0)/10%6 , 0b00000010); _delay_ms(0,25); display_number((Timer1%60)%10, 0b00000001); _delay_ms(0.25); display_number((Timer2/60)/10, 0b100000000);(0b100000000);(0b100000000);(0b100000000); 60)%10, 0b01000000); _delay_ms(0.25); display_number((Timer2%60)/10, 0b00100000); _delay_ms(0.25); display_number((Timer2%60)%10, 0b0_001;(0b00_001). = 0; ) void display_number(int number, int maske) ( PORTB = number_mask(number); PORTD = maske; )

Visningsfunksjonen bruker en dynamisk visningsmetode. Faktum er at hver enkelt indikator har 9 kontakter (7 for segmentkontroll, 1 for punkt og 1 for strøm). For å kontrollere 4 sifre, vil det være nødvendig med 36 kontakter. For bortkastet. Derfor er utgangen av sifre til en indikator med flere sifre organisert i henhold til følgende prinsipp:

Spenning leveres vekselvis til hver av de vanlige kontaktene, noe som lar deg markere ønsket nummer på den tilsvarende indikatoren ved å bruke de samme 8 kontrollkontaktene. Ved en høy nok utgangsfrekvens ser det ut som et statisk bilde for øyet. Det er grunnen til at alle de 8 strømkontaktene til begge indikatorene i diagrammet er koblet til 8 utganger på port D, og ​​16 segmentkontrollerende kontakter er koblet i par og koblet til 8 utganger på port B. Dermed fungerer displayet med en forsinkelse på 0,25 ms viser vekselvis ønsket tall på hver av indikatorene. Til slutt slås alle utganger som leverer spenning til indikatorene av (kommando PORTD = 0;). Hvis dette ikke gjøres, vil det sist viste sifferet fortsette å lyse til neste anrop til displayfunksjonen, noe som vil føre til lysere glød sammenlignet med resten.

Håndtere klikk

Void handle_buttons() ( handle_button(KEY_SETUP); handle_button(KEY_RESET); handle_button(KEY_PAUSE); handle_button(KEY_PLAYER1); handle_button(KEY_PLAYER2); ) void handle_button(int-tast) (int-bit; bryter (nøkkel) (case KEY_SETUP) = SETUP_BIT; break; case KEY_RESET: bit = RESET_BIT; break; case KEY_PAUSE: bit = PAUSE_BIT; break; case KEY_PLAYER1: bit = PLAYER1_BIT; break; case KEY_PLAYER2: bit = PLAYER2_BIT; break; clear (standardbit return_; ) BUTTON_PIN, bit)) ( if (_pressed == 0) ( _delay_ms(DEBOUNCE_TIME); if (bit_is_clear(BUTTON_PIN, bit)) ( _pressed |= tast; // nøkkelhandlingsbryter (tast) ( case KEY_SETUP: process_setup(); break; case KEY_RESET: prosess_tilbakestill(); break; case KEY_PAUSE: prosess_pause(); break; case KEY_PLAYER1: prosessspiller1(); break; case KEY_PLAYER2: prosessspiller2(); pause; ) sound_on(15); ) ) ) else ( _pressed &= ~tast; ) )

Denne funksjonen poller alle 5 knappene etter tur og behandler klikket, hvis noen. Klikket registreres ved å sjekke bit_is_clear(BUTTON_PIN, bit) , dvs. knappen trykkes hvis den tilsvarende inngangen er koblet til jord, noe som vil skje, i henhold til diagrammet, når knappen trykkes. En forsinkelse på DEBOUNCE_TIME og gjentatt sjekk er nødvendig for å unngå flere unødvendige operasjoner på grunn av kontaktsprett. Lagring av trykket status i de tilsvarende bitene av variabelen _pressed brukes for å forhindre gjentatt utløsning når knappen holdes nede i lang tid.
Funksjonene for å behandle klikk er ganske trivielle og jeg mener at de ikke trenger ytterligere kommentarer.

Fulltekst av programmet

#define F_CPU 4000000UL #inkluder #inkludere #inkludere #define DEBOUNCE_TIME 20 #define BUTTON_PIN PINC #define SETUP_BIT PC0 #define RESET_BIT PC1 #define PAUSE_BIT PC2 #define PLAYER1_BIT PC3 #define PLAYER2_BIT PC4 #define KEY_SETUP 0b000000B _PAUSE 0b00000100 #define KEY_PLAYER1 0b00001000 #define KEY_PLAYER2 0b00010000 volatile int ActiveTimer = 0; flyktig int Timer1 = 0; flyktig int Timer2 = 0; volatile int _buzzer = 0; volatile int _pressed = 0; // funksjonserklæringer void init_io(); void init_data(); int tall_maske(int tall); void handle_buttons(); void handle_button(int-nøkkel); void prosessoppsett(); void process_reset(); void process_pause(); void process_timeoff(); void prosessspiller1(); void prosessspiller2(); void display(); void display_number(int mask, int number); void sound_on(int intervall); void sound_off(); // avbryter ISR (TIMER0_OVF_vect) ( display(); if (_buzzer > 0) ( _buzzer--; if (_buzzer == 0) sound_off(); ) ) ISR(TIMER1_COMPA_vect) ( if (ActiveTimer == 1 && Timer1 > 0) ( Timer1--; if (Timer1 == 0) process_timeoff(); ) if (ActiveTimer == 2 && Timer2 > 0) ( Timer2--; if (Timer2 == 0) process_timeoff(); ) ) int main (void) ( init_io(); init_data(); sound_off(); sei(); while(1) ( handle_buttons(); ) return 0; ) void init_io() ( // sett utgang DDRB = 0xFF; DDRD = 0xFF ; // sett inngang DDRC = 0b11100000; // pull-up motstander PORTC |= 0b00011111; // timer avbryter TIMSK = (1<5940 || Timer2 > 5940) ( Timer1 = 0; Timer2 = 0; ) ) void process_reset() ( init_data(); ) void process_timeoff() ( init_data(); sound_on(30); ) void process_pause() ( ActiveTimer = 0; ) void prosessspiller1() ( ActiveTimer = 2; ) void prosessspiller2() ( ActiveTimer = 1; ) void handle_button(int-tast) ( int-bit; bryter (tast) ( case KEY_SETUP: bit = SETUP_BIT; break; case KEY_RESET: bit = RESET_BIT ; break; case KEY_PAUSE: bit = PAUSE_BIT; break; case KEY_PLAYER1: bit = PLAYER1_BIT; break; case KEY_PLAYER2: bit = PLAYER2_BIT; break; default: return; ) if (bit_is_clear(BUTTON_PIN, bit)) ( if (_pressed) 0) ( _delay_ms(DEBOUNCE_TIME); if (bit_is_clear(BUTTON_PIN, bit)) ( _presset |= tast; // tastehandlingsbryter (tast) ( case KEY_SETUP: process_setup(); break; case KEY_RESET: process_reset(); break; tilfelle KEY_PAUSE: prosess_pause(); pause; tilfelle KEY_PLAYER1: prosessspiller1(); pause; tilfelle KEY_PLAYER2: prosessspiller2(); pause; ) lyd_på(15); ) ) ) else ( _trykket &= ~tast; ) ) void handle_buttons() ( handle_button(KEY_SETUP); handle_button(KEY_RESET); handle_button(KEY_PAUSE); handle_button(KEY_PLAYER1); handle_button(KEY_PLAYER2); ) void display() ( display_number((Timer1/000,0 0b100)/0b100,0 0)/0b1 ; _delay_ms(0.25); display_number((Timer1/60)%10, 0b00000100); _delay_ms(0.25); display_number((Timer1%60)/10, 0b00000010); _delay_ms(0.25) display 10, 0b00000001); _delay_ms(0.25); display_number((Timer2/60)/10, 0b10000000); _delay_ms(0.25); display_number((Timer2/60)%10, 0b01000000ms(Timer_0000ms).( %60)/10, 0b00100000); _delay_ms(0.25); display_number((Timer2%60)%10, 0b00010000); _delay_ms(0.25); PORTD = 0; ) void display_number (int nummer, int B maske) nummer (maske) (tall); PORTD = maske; ) void sound_on(int interval) ( _buzzer = interval; // put buzzer pin high PORTC |= 0b00100000; ) void sound_off() ( // put buzzer pin low PORTC &= ~0b00100000; )

Prototypen ble satt sammen på et brødbrett.

Leksjon 0.

Så i dag åpner vi en serie leksjoner om programmering av mikrokontrollere fra AVR-familien.

I dag vil følgende spørsmål bli diskutert:

  1. Hva er en mikrokontroller?
  2. Hvor brukes mikrokontrollere?

Introduksjon.

Mikrokontrollere er overalt. I telefoner, vaskemaskiner, «smarte hjem», verktøymaskiner på fabrikker og også i utallige andre tekniske enheter. Deres utbredte bruk gjør det mulig å erstatte komplekse analoge kretser med mer komprimerte digitale.

Så hva er en mikrokontroller?

Mikrokontroller (Mikrokontrollenhet, MCU) - en mikrokrets designet for å kontrollere elektroniske enheter. Du kan forestille deg den som en enkel datamaskin som er i stand til å samhandle med eksterne enheter. For eksempel åpne og lukke transistorer, motta data fra temperatursensorer, vise data på LCD-skjermer, etc. I tillegg kan mikrokontrolleren utføre forskjellig behandling av inndata, akkurat som din personlige datamaskin.

Det vil si at mikrokontrollere gir oss nesten ubegrensede muligheter for å kontrollere alle enheter, takket være tilstedeværelsen av I/0-porter (inn-/utgangsporter), samt muligheten til å programmere dem.

Hvor brukes mikrokontrollere?

  1. Husholdningsapparater (vaskemaskiner, mikrobølgeovner, etc.).
  2. Mobilteknologi (Roboter, robotsystemer, kommunikasjonsutstyr, etc.).
  3. Industrielt utstyr (maskinkontrollsystemer).
  4. Datateknologi (hovedkort, kontrollsystemer for eksterne enheter).
  5. Underholdningsutstyr (barneleker, dekorasjoner).
  6. Transport (kontrollsystemer for bilmotorer, sikkerhetssystemer)

Dette er ikke en fullstendig liste over applikasjoner for mikrokontrollere. Ofte er det svært lønnsomt å erstatte et sett med kontrollbrikker med én mikrokontroller, på grunn av forenklet produksjon og redusert strømforbruk.

Komme i gang med AVR

AVR- en familie av mikrokontrollere fra Atmel. De har tilstrekkelig ytelse for de fleste amatørenheter. De er også mye brukt i industrien.

Det finnes forskjellige programmeringsspråk for AVR-mikrokontrollere, men kanskje de mest passende er assembler og C, siden disse språkene best implementerer alle nødvendige evner for å administrere mikrokontrollermaskinvare.

Assembly language er et programmeringsspråk på lavt nivå som bruker det direkte instruksjonssettet til mikrokontrolleren. Å lage et program på dette språket krever god kjennskap til kommandosystemet til den programmerbare brikken og tilstrekkelig tid til å utvikle programmet. Monteringsspråk er dårligere enn C i hastigheten og bekvemmeligheten av programutvikling, men har merkbare fordeler i størrelsen på den endelige kjørbare koden, og følgelig hastigheten på dens utførelse.

C lar deg lage programmer med mye større komfort, og gir utvikleren alle fordelene med et språk på høyt nivå.
Det skal bemerkes nok en gang at arkitekturen og kommandosystemet til AVR ble opprettet med direkte deltakelse fra utviklerne av C-språkkompilatoren, og det tar hensyn til funksjonene til dette språket. Det går raskt å kompilere C-kildekode og produserer kompakt, effektiv kode.

De viktigste fordelene med C fremfor assembler: høy hastighet på programutvikling; universalitet som ikke krever en grundig studie av mikrokontrollerarkitekturen; bedre dokumenterbarhet og lesbarhet av algoritmen; tilgjengeligheten av funksjonsbiblioteker; støtte for flyttallsberegninger.

C-språket kombinerer programmeringsevner på lavt nivå harmonisk med egenskapene til et høynivåspråk. Muligheten til lavnivåprogrammering lar deg enkelt operere direkte på maskinvare, og egenskapene til høynivåspråket lar deg lage lett lesbar og modifiserbar programkode. I tillegg har nesten alle C-kompilatorer muligheten til å bruke assembler-innlegg for å skrive programseksjoner som er kritiske med tanke på utførelsestid og ressursforbruk.

Kort sagt, C er det mest praktiske språket for både nybegynnere som blir kjent med AVR-mikrokontrollere og seriøse utviklere.

Kompilatorer brukes til å konvertere kildekoden til et program til en fastvarefil for mikrokontroller.

Atmel tilbyr en kraftig assembly-kompilator som er inkludert i Atmel Studio-utviklingsmiljøet som kjører på Windows. Sammen med kompilatoren inneholder utviklingsmiljøet en debugger og en emulator.
Atmel Studio er helt gratis og tilgjengelig på Atmel-nettstedet.

For tiden er det ganske mange C-kompilatorer for AVR. Den kraftigste av dem anses å være kompilatoren fra IAR Systems fra Stockholm. Det var de ansatte som deltok i utviklingen av AVR-kommandosystemet på midten av 90-tallet. IAR C Compiler har omfattende kodeoptimaliseringsmuligheter og kommer som en del av det integrerte utviklingsmiljøet IAR Embedded Workbench (EWB), som også inkluderer en assembler-kompilator, linker, prosjekt- og biblioteksjef og debugger. Prisen på fullversjonen av pakken er 2820 EUR. På selskapets nettside kan du laste ned en gratis evalueringsversjon i 30 dager eller en ubegrenset versjon med kodestørrelsesgrense på 4 KB.

Det amerikanske selskapet Image Craft fra Palo Alto, California produserer en C-språkkompilator som har fått ganske stor popularitet. JumpStart C for AVR har akseptabel kodeoptimalisering og en ikke for høy pris (fra $50 til $499 avhengig av versjon). Demoversjonen av JumpStart C for AVR er fullt funksjonell i 45 dager.

Den rumenske Code Vision AVR C-kompilatoren har ikke blitt mindre populær; prisen på fullversjonen av denne kompilatoren er relativt lav og utgjør 150 EUR. Kompilatoren kommer med et integrert utviklingsmiljø, som i tillegg til standardfunksjoner inkluderer en ganske interessant funksjon - CodeWizardAVR Automatic Program Generator. Tilstedeværelsen av en seriell terminal i utviklingsmiljøet lar deg feilsøke programmer ved å bruke den serielle porten til mikrokontrolleren. Du kan laste ned en gratis evalueringsversjon fra utviklerne med en kodestørrelsesgrense på 4 KB og deaktivert lagring av den genererte kildekoden i C.

Selskapet MikroElektronika, som ligger i den serbiske byen Beograd, produserer en hel familie kompilatorer for AVR-mikrokontrollere. En kompilator for C-språket kalt mikroC PRO for AVR koster $249. Det finnes også mikroBasic og mikroPascal for samme pris. Det er demoversjoner på utviklerens nettsted med en kodestørrelsesgrense på 4096 byte. Fordelen med denne familien av kompilatorer er en enkelt plattform og en enkelt ideologi, som kan gi en enkel overgang ikke bare mellom språk, men også mellom mikrokontrollere (det finnes kompilatorversjoner for PIC, STM32, 8051...).

Det integrerte utviklingsmiljøet har blitt virkelig ikonisk. Den inkluderer kraftige C- og assembler-kompilatorer, AVRDUDE-programmereren, en debugger, en simulator og mange andre støtteprogrammer og verktøy. WinAVR integreres sømløst med Atmels AVR Studio utviklingsmiljø. Monteringsenheten er identisk i inngangskode med AVR Studio-montøren. C- og assembler-kompilatorer har muligheten til å lage feilsøkingsfiler i COFF-format, som lar deg bruke ikke bare innebygde verktøy, men også bruke den kraftige AVR Studio-simulatoren. En annen viktig fordel er at WinAVR distribueres gratis uten begrensninger (produsenter støtter GNU General Public License).

Som en oppsummering er det verdt å si at WinAVR er et ideelt valg for de som begynner å mestre AVR-mikrokontrollere. Det er dette utviklingsmiljøet som regnes som det viktigste i dette kurset.

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 ved å tilkobling, ser det ut til, 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 er det nødvendig med 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


Topp