Programmering av avr-mikrokontroller i C. Programmering av AVR-mikrokontroller i C. Så vad är en mikrokontroller

Jag bestämde mig för att skriva en kort introduktionsartikel för dem som började programmera mikrokontroller för första gången och som aldrig var bekant med C-språket tidigare. Vi kommer inte att gå in på detaljer, vi kommer att prata om allt lite för att få en allmän uppfattning om hur man arbetar med CodeVisionAVR.

Mer detaljerad information kan ses på engelska i CodeVision User Manual, och jag rekommenderar även webbplatsen http://somecode.ru med videolektioner om C för mikrokontroller och boken "How to Program in C" av Deitel, detta är den enda bra boken som jag själv började med.

Låt oss börja med det faktum att oavsett vilka åtgärder vi gör, i slutändan beror allt på mikrokontrollerns firmware. Själva firmwareprocessen sker enligt följande: med ett visst program väljs en firmwarefil, parametrar väljs, en knapp trycks ned och firmware blinkar direkt, vilket i huvudsak är en kopia. Precis som du kopierar musik eller dokument från en dator till en flash-enhet, är processens fysik densamma.

Själva firmwaren har en .hex-tillägg och är en uppsättning instruktioner, i form av ettor och nollor, vilket är förståeligt för mikrokontrollern. Var kan jag få firmware ifrån? Du kan ladda ner det från elektronikwebbplatser eller skriva det själv. Du kan skriva det i speciella program som kallas utvecklingsmiljö. De mest kända för mig är AVR Studio, IAR, CodeVision, WinAVR... Det är omöjligt att säga vilken av dessa miljöer som är bättre eller sämre, för var och en sin egen. Vi kan säga att dessa program skiljer sig främst i bekvämlighet, programmeringsspråk och pris. Inom denna webbplats beaktas endast CodeVision.

Vi har sorterat ut miljön, låt oss nu titta på processen att skriva firmware. I CodeVision måste du först skapa ett projekt. Den kan skapas med hjälp av kodguiden eller tom. I vilket fall som helst måste du välja vilken typ av mikrokontroller som används och ange dess frekvens. När du använder guiden kommer du att bli ombedd att välja initiala inställningar och generera källkod med inställningarna. Därefter kommer ett fönster upp där du kan redigera denna kod. Även om du kan skriva din källkod i Anteckningar och sedan bifoga den till projektet i inställningarna.

En källkodsfil är en uppsättning kommandon i ett programmeringsspråk, CodeVisions uppgift är att översätta dessa kommandon till binär kod, din uppgift är att skriva denna källkod. CodeVision förstår C-språket, källkodsfiler har tillägget ".c". Men CodeVision har några konstruktioner som inte används i C, vilket är anledningen till att många programmerare inte gillar det, och språket som används kallas C-liknande. Detta hindrar dig dock inte från att skriva seriösa projekt. Många exempel, en kodgenerator och en stor uppsättning bibliotek ger CodeVision en stor fördel. Det enda negativa är att det är betalt, även om det finns gratisversioner med kodbegränsning.

Källkoden måste innehålla en rubrik med vilken typ av mikrokontroller som används och huvudfunktionen. Till exempel används ATtiny13

#omfatta void main(void) ( );

#omfatta void main(void) ( );

Innan huvudfunktionen kan du ansluta de nödvändiga biblioteken, deklarera globala variabler, konstanter och inställningar. Ett bibliotek är en separat fil, vanligtvis med filtillägget ".h", som redan innehåller förskriven kod. I vissa projekt kan vi behöva den här koden, men i andra behöver vi den inte. Till exempel, i ett projekt använder vi LCD-skärmar, men i ett annat gör vi det inte. Du kan ansluta biblioteket för att arbeta med LCD-skärmen "alcd.h" så här:

#omfatta #omfatta void main(void) ( );

#omfatta #omfatta void main(void) ( );

Variabler är minnesområden där vissa värden kan placeras. Om du till exempel lägger till två siffror måste du spara resultatet någonstans för att kunna använda det i framtiden. Först måste du deklarera variabeln, dvs. allokera minne för det, till exempel:
int i=0;
de där. vi deklarerade variabeln i och placerade värdet 0 i den, int är typen av variabel, eller enklare betyder det storleken på det tilldelade minnet. Varje variabeltyp kan bara lagra ett visst värdeintervall. Till exempel kan int skrivas som tal från -32768 till 32767. Om du behöver använda tal med en bråkdel måste variabeln deklareras som ett flytande, för tecken, använd char-typen.

bit, _Bit 0 eller 1 char från -128 till 127 osignerad char från 0 till 255 int från -32768 till 32767 unsigned int från 0 till 65535 lång int från -2147483648 till 2147483647 osignerad från 7 ± 40 91 919. 5e- 38 till ±3,402e38

Inuti huvudfunktionen körs redan huvudprogrammet. Efter att ha utfört funktionen kommer programmet att stanna, så de gör en oändlig while-loop, som upprepar samma program konstant.

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

void main(void) ( medan (1) ( ); );

Du kan skriva en kommentar i vilken del av källkoden som helst; det kommer inte att påverka programmets funktion på något sätt, men kommer att hjälpa till att göra anteckningar om den skrivna koden. Du kan kommentera en rad med två snedstreck // varefter kompilatorn ignorerar hela raden eller flera rader /**/, till exempel:

/*Grundläggande matematikoperationer:*/ int i= 0 ; //deklarera variabeln i och tilldela den värdet 0//Addition: i = 2 + 2 ; //Subtraktion: i = 2 - 2 ; //efter att ha kört detta uttryck kommer variabeln i att vara lika med 0//Multiplikation: i = 2 * 2 ; //efter att ha kört detta uttryck kommer variabeln i att vara lika med 4//Division: i = 2 / 2 ; //efter att ha kört detta uttryck kommer variabeln i att vara lika med 1

/*Grundläggande matematiska operationer:*/ int i=0; //deklarera variabel i och tilldela den värdet 0 //Addition: i = 2+2; //efter exekvering av detta uttryck kommer variabeln i att vara lika med 4 //Subtraktion: i = 2-2; //efter exekvering av detta uttryck kommer variabeln i att vara lika med 0 //Multiplication: i = 2*2; //efter exekvering av detta uttryck kommer variabeln i att vara lika med 4 //Division: i = 2/2; //efter att ha kört detta uttryck kommer variabeln i att vara lika med 1

Ofta måste ett program övergå från ett stycke kod till ett annat, beroende på förhållandena; för detta finns det villkorade if()-operationer, till exempel:

if(i>3) //om i är större än 3, tilldela sedan i värdet 0 ( i=0; ) /*om i är mindre än 3, gå sedan till koden efter villkorets brödtext, dvs. efter parenteser ()*/

Även om kan användas tillsammans med annat - annars

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

Det finns också en jämförelseoperator "==", som inte ska förväxlas med "="-tilldelning. Den omvända operationen är inte lika med "!=", låt oss säga

if(i==3)//om i är 3, tilldela i värdet 0 ( i=0; ) if(i!=5) //om i inte är 5, tilldela i värdet 0 ( i=0; )

Låt oss gå vidare till mer komplexa saker - funktioner. Låt oss säga att du har en viss kodbit som upprepas flera gånger. Dessutom är denna kod ganska stor i storlek. Det är obekvämt att skriva det varje gång. Till exempel, i ett program som på något sätt ändrar variabel i, när du trycker på knapp 0 och 3 på port D, exekveras samma kod, som, beroende på värdet på variabel i, slår på benen på port B.

void main(void) ( if (PIND.0== 0 ) //kontrollera om knappen på PD0 är nedtryckt(om (i== 0 ) //if i==0 aktivera PB0( PORTB.0= 1 ; ) om (i== 5 ) // om i==5 aktivera PB1( PORTB.1= 1 ; ) ) … if (PIND.3== 0 ) // gör samma sak när du kontrollerar PD3-knappen( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) ) )

void main(void) ( if(PIND.0==0) //kontrollera om knappen på PD0 är nedtryckt ( if(i==0) //if i==0 slå på PB0 ( PORTB.0=1; ) if( i==5) // if i==5 slå på PB1 ( PORTB.1=1; ) ) ... if(PIND.3==0) // gör samma sak när du kontrollerar PD3-knappen ( if(i==0 ) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) )

I allmänhet är koden inte särskilt stor, men den kan vara många gånger större, så det skulle vara mycket bekvämare att skapa en egen funktion.
Till exempel:

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

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

void betyder att funktionen inte returnerar något, mer om detta nedan i_check() - detta är namnet på vår funktion, du kan kalla den vad du vill, jag kallade den precis så - kontrollera i. Nu kan vi skriva om vår kod:

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) void main(void) ( if(PIND.0==0 ) //kontrollera om knappen på PD0 är nedtryckt ( i_check(); ) ... if(PIND.3==0) ( i_check(); ) )

När koden når raden i_check(); då hoppar den in i funktionen och kör koden inuti. Håller med, koden är mer kompakt och tydligare, d.v.s. funktioner hjälper till att ersätta samma kod, bara en rad. Observera att funktionen deklareras utanför huvudkoden, d.v.s. före huvudfunktionen. Du kan säga, varför behöver jag detta, men när du studerar lektionerna kommer du ofta att stöta på funktioner, till exempel att rensa LCD-skärmen lcd_clear() - funktionen accepterar inga parametrar och returnerar ingenting, men den rensar skärm. Ibland används den här funktionen nästan varannan rad, så kodbesparingarna är uppenbara.

Det ser mycket mer intressant ut att använda en funktion när den tar värden, till exempel finns det en variabel c och det finns en funktionssumma som tar två värden av typen int. När huvudprogrammet kör den här funktionen kommer argumenten redan att stå inom parentes, så "a" blir lika med två och "b" blir lika med 1. Funktionen kommer att köras och "c" blir lika med 3 .

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

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

En av de vanligaste liknande funktionerna är att flytta markören på LCD-skärmen lcd_gotoxy(0,0); som för övrigt också tar argument - x- och y-koordinater.

Ett annat alternativ för att använda en funktion, när den returnerar ett värde, nu kommer det inte längre att vara ogiltigt, låt oss förbättra det tidigare exemplet på en funktion för att lägga till två tal:

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

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

Resultatet blir detsamma som förra gången c=3, men observera att vi tilldelar variabeln "c" värdet på en funktion som inte längre är tom, utan returnerar summan av två tal av typen int. På så sätt är vi inte bundna till en specifik variabel "c", vilket ger flexibilitet vid användning av funktioner. Ett enkelt exempel på en sådan funktion är att läsa ADC-data, funktionen returnerar det uppmätta värdet result=read_adc();. Låt oss avsluta med funktionerna.

Låt oss nu gå vidare till arrayer. En array är relaterade variabler. Till exempel har du en sinustabell med flera punkter, du kommer inte att skapa variabler int sinus1=0; int sinus2=1; etc. En array används för detta. Du kan till exempel skapa en array med tre element så här:
int sinus=(0,1,5);
Det totala antalet arrayelement anges inom hakparenteser. Du kan tilldela värdet på det tredje elementet till variabeln "c" så här:
с=sinus;
Observera att numreringen av arrayelement börjar från noll, dvs. "c" blir lika med fem. Denna array har inget sinuselement!!!
Du kan tilldela ett värde till ett enskilt element så här:
sinus=10;

Du kanske redan har märkt att CodeVision inte har strängvariabler. De där. du kan inte skapa en variabel sträng hello="hej"; För att göra detta måste du skapa en rad individuella karaktärer.

lcd_putchar(hej); lcd_putchar(hej); lcd_putchar(hej);

etc.
Det visar sig ganska krångligt, det är här cykler kommer till undsättning.
Till exempel while loop

while(PINB.0!=0) ( )

Gör ingenting tills knappen trycks ned - kör en tom slinga.

Ett annat alternativ är for-slingan

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

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

Innebörden är exakt densamma som för while, endast initialvillkoret i=0 och villkoret som exekveras varje cykel i++ läggs till. Koden inuti slingan är så förenklad som möjligt.

Efter att du har skrivit ditt program kompileras källkoden, och om det inte finns några fel får du den eftertraktade firmwaren i projektmappen. Nu kan du flasha mikrokontrollern och njuta av enhetens funktion.

Du bör inte omedelbart försöka använda loopar, arrayer och funktioner i din firmware. Din huvudsakliga uppgift är att få den fasta programvaran att fungera, så gör det eftersom det är lättare för dig och var inte uppmärksam på storleken på koden. Tiden kommer när du inte bara vill skriva arbetskod, utan att skriva den vackert och kompakt. Då blir det möjligt att fördjupa sig i C-språkets vildmark. För den som vill behärska allt rekommenderar jag återigen boken ”Hur programmerar man i C”, det finns många exempel och uppgifter. Installera Visual Studio, skapa en win32-konsolapplikation och öva där så gott du kan.

Lektion 0.

Så idag öppnar vi en serie lektioner om programmering av mikrokontroller i AVR-familjen.

Idag kommer följande frågor att behandlas:

  1. Vad är en mikrokontroller?
  2. Var används mikrokontroller?

Introduktion.

Mikrokontroller finns överallt. I telefoner, tvättmaskiner, ”smarta hem”, verktygsmaskiner i fabriker och även i otaliga andra tekniska apparater. Deras utbredda användning gör det möjligt att ersätta komplexa analoga kretsar med mer komprimerade digitala.

Så vad är en mikrokontroller?

Mikrokontroller (Micro Controller Unit, MCU) - en mikrokrets utformad för att styra elektroniska enheter. Du kan föreställa dig den som en enkel dator som kan interagera med externa enheter. Till exempel öppna och stänga transistorer, ta emot data från temperatursensorer, visa data på LCD-skärmar, etc. Dessutom kan mikrokontrollern utföra olika behandlingar av indata, precis som din persondator.

Det vill säga, mikrokontroller erbjuder oss nästan obegränsade möjligheter att styra alla enheter, tack vare närvaron av I/0-portar (ingångs-/utgångsportar), samt möjligheten att programmera dem.

Var används mikrokontroller?

  1. Hushållsapparater (tvättmaskiner, mikrovågsugnar etc.).
  2. Mobil teknik (Robotar, robotsystem, kommunikationsutrustning etc.).
  3. Industriell utrustning (maskinstyrsystem).
  4. Datorteknik (moderkort, styrsystem för kringutrustning).
  5. Underhållningsutrustning (barnleksaker, dekorationer).
  6. Transport (kontrollsystem för bilmotorer, säkerhetssystem)

Detta är inte en komplett lista över applikationer för mikrokontroller. Ofta är det mycket lönsamt att ersätta en uppsättning kontrollchips med en mikrokontroller, på grund av förenklad produktion och minskad strömförbrukning.

Komma igång med AVR

AVR- en familj av mikrokontroller från Atmel.De har tillräcklig prestanda för de flesta amatörenheter. De används också i stor utsträckning inom industrin.

Det schematiska diagrammet för LPT-portprogrammeraren visas i figuren. Som busschaufför, använd mikrokretsen 74AC 244 eller 74HC244 (K1564AP5), 74LS244 (K555AP5) eller 74ALS244 (K1533AP5).

LED VD1 indikerar inspelningsläget för mikrokontrollern,

LED VD2 - läsning,

LED VD3 - närvaro av strömförsörjning till kretsen.

Kretsen tar den spänning som krävs för strömförsörjning från ISP-kontakten, d.v.s. från den programmerbara enheten. Denna krets är en omdesignad STK200/300-programmeringskrets (tillagda lysdioder för enkel användning), så den är kompatibel med alla PC-programmeringsprogram som fungerar med STK200/300-kretsen. För att arbeta med denna programmerare, använd programmet CVAVR

Programmeraren kan göras på ett kretskort och placeras i LPT-kontakthuset, som visas i figurerna:




För att arbeta med programmeraren är det bekvämt att använda en LPT-portförlängning, som är lätt att göra själv (till exempel från en Centronix-kabel för en skrivare), det viktigaste är att inte skona ledarna för marken (18- 25 kopplingsben) eller köp. Kabeln mellan programmeraren och det programmerbara chippet bör inte överstiga 20-30 cm.

Bitvisa operationer är baserade på de logiska operationer som vi behandlade tidigare. De spelar en nyckelroll vid programmering av AVR och andra typer av mikrokontroller. Nästan inget program klarar sig utan användningen av bitvisa operationer. Innan detta undvek vi dem medvetet för att underlätta processen att lära sig MK-programmering.

I alla tidigare artiklar programmerade vi endast I/O-portar och använde inte ytterligare inbyggda komponenter, till exempel timers, analog-till-digital-omvandlare, avbrott och andra interna enheter utan vilka MK förlorar all sin kraft.

Innan du går vidare till att bemästra de inbyggda enheterna i MK, måste du lära dig hur du kontrollerar eller kontrollerar enskilda bitar av registren i AVR MK. Tidigare har vi gjort en kontroll eller ställt in siffrorna för hela registret på en gång. Låt oss ta reda på vad skillnaden är och sedan gå vidare.

Bitvisa operationer

Oftast, när vi programmerade AVR-mikrokontroller, använde vi det, eftersom det är mer visuellt jämfört med och är väl förstått för nybörjare MK-programmerare. Till exempel behöver vi bara ställa in den 3:e biten av port D. För att göra detta, som vi redan vet, kan vi använda följande binära kod:

PORTD = 0b00001000;

Men med detta kommando ställer vi in ​​den tredje siffran till ett, och vi nollställer alla andra (0, 1, 2, 4, 5, 6 och 7:e). Låt oss nu föreställa oss en situation där den 6:e och 7:e biten används som ADC-ingångar och vid denna tidpunkt tas en signal från någon enhet emot på motsvarande MK-stift, och vi använder kommandot ovan för att återställa dessa signaler. Som ett resultat ser mikrokontrollern dem inte och tror att signalerna inte kom fram. Därför, istället för ett sådant kommando, bör vi använda ett annat som bara skulle ställa in den 3:e biten till en, utan att påverka de återstående bitarna. För att göra detta används vanligtvis följande bitvisa operation:

PORTD |= (1<<3);

Vi kommer att diskutera dess syntax i detalj nedan. Och nu ett annat exempel. Låt oss säga att vi måste kontrollera tillståndet för den tredje siffran i PIND-registret, och därigenom kontrollera tillståndet för knappen. Om denna bit återställs till noll, så vet vi att knappen trycks ned och sedan exekveras kommandokoden, vilket motsvarar tillståndet för den nedtryckta knappen. Tidigare skulle vi ha använt följande notation:

if (PIND == 0b00000000)

(valfri kod)

Men med dess hjälp kontrollerar vi inte bara den 3:e biten, utan alla bitar i PIND-registret på en gång. Därför, även om knappen trycks ned och den önskade biten återställs, men vid denna tidpunkt en signal tas emot vid något annat stift på port D, kommer motsvarande värde att sättas till ett, och villkoret inom parentes kommer att vara falskt. Som ett resultat kommer koden inuti de lockiga hängslen inte att exekveras även när knappen trycks ned. Därför, för att kontrollera tillståndet för en individuell 3:e bit i PIND-registret, bör en bitvis operation användas:

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

(valfri kod)

För att arbeta med individuella bitar av mikrokontrollern har programmeringsspråket C verktyg som kan användas för att ändra eller kontrollera tillståndet för en eller flera enskilda bitar på en gång.

Ställer in en enda bit

För att ställa in en enstaka bit, såsom port D, används en bitvis ELLER-operation. Detta är vad vi använde i början av artikeln.

PORTD = 0b00011100; // ursprungligt värde

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

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

PORTD == 0b00011101; // resultat

Detta kommando ställer in nollbiten och lämnar resten oförändrad.

Till exempel, låt oss installera ytterligare en sjätte bit av port D.

PORTD = 0b00011100; // initialt porttillstånd

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

PORTD == 0b01011100; // resultat

Att skriva en till flera separata bitar samtidigt, till exempel noll-, sjätte- och sjundeporten B Följande notation gäller.

PORTB = 0b00011100; // ursprungligt värde

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

PORTB == 0b1011101; // resultat

Återställa (nollställa) enskilda bitar

För att återställa en enda bit används tre tidigare diskuterade kommandon samtidigt: .

Låt oss återställa den tredje biten i PORTC-registret och lämna resten oförändrad.

PORTC = 0b00011100;

PORTC &= ~(1<<3);

PORTC == 0b00010100;

Låt oss utföra liknande åtgärder för den andra och fjärde siffran:

PORTC = 0b00111110;

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

PORTC == 0b00101010;

Bitbyte

Förutom inställning och återställning används också ett användbart kommando som växlar en enstaka bit till motsatt tillstånd: en till noll och vice versa. Denna logiska operation används ofta för att skapa olika ljuseffekter, till exempel en nyårskrans. Låt oss titta på exemplet med PORTA

PORTA = 0b00011111;

PORTA ^= (1<<2);

PORTA == 0b00011011;

Låt oss ändra tillståndet för noll-, andra- och sjättebitarna:

PORTA = 0b00011111;

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

PORTA == 0b01011010;

Kontrollera tillståndet för en enskild bit. Låt mig påminna dig om att kontroll (i motsats till att skriva) en I/O-port utförs genom att läsa data från PIN-registret.

Oftast utförs testning av en av två loop-satser: if och while. Vi är redan bekanta med dessa operatörer tidigare.

Kontrollerar biten för närvaron av en logisk nolla (återställning) med om

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

Om den tredje biten i port D rensas, exekveras Code1. Annars exekveras Code2.

Liknande åtgärder utförs med denna form av inspelning:

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

Kontrollerar biten för närvaron av en logisk enhet (inställning) med om

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

om (PIND & (1<<3))

Ovanstående två slingor fungerar likadant, men kan, på grund av flexibiliteten i programmeringsspråket C, ha en annan form av notation. Operatorn != betyder inte lika. Om den tredje biten av PD I/O-porten är inställd (ett), så exekveras Code1, om inte, exekveras Code2.

Väntar på att en bit ska återställas medan

medan (PIND & (1<<5))

Kod1 kommer att exekveras så länge som den 5:e biten i PIND-registret är inställd. När du återställer den kommer Code2 att börja köras.

Väntar på att biten ska ställas in medan

Här låter C-syntaxen dig skriva kod på två av de vanligaste sätten. I praktiken används båda typerna av inspelning.

Mikrokontroller (nedan kallade MK) har kommit in i våra liv, på Internet kan du hitta många intressanta kretsar som körs på MK. Vad du inte kan montera på en MK: olika indikatorer, voltmetrar, hushållsapparater (skyddsanordningar, växlingsanordningar, termometrar ...), metalldetektorer, olika leksaker, robotar, etc. Listan kan ta väldigt lång tid. Jag såg den första kretsen på en mikrokontroller för 5-6 år sedan i en radiotidning och vände nästan omedelbart på sidan och tänkte för mig själv "Jag kommer fortfarande inte att kunna montera den." På den tiden var MKs en mycket komplex och missförstådd enhet för mig; jag hade ingen aning om hur de fungerade, hur man flashade dem och vad man skulle göra med dem i händelse av felaktig firmware. Men för ungefär ett år sedan satte jag ihop min första krets på en MK; det var en digital voltmeterkrets baserad på 7 segmentindikatorer och en ATmega8 mikrokontroller. Det hände så att jag köpte en mikrokontroller av en slump, när jag stod på radiokomponentavdelningen köpte killen framför mig en MK, och jag bestämde mig också för att köpa den och försöka sätta ihop något. I mina artiklar kommer jag att berätta om AVR mikrokontroller, jag ska lära dig hur du arbetar med dem, vi kommer att titta på program för firmware, vi kommer att göra en enkel och pålitlig programmerare, vi kommer att titta på firmwareprocessen och, viktigast av allt, de problem som inte kan uppstå endast för nybörjare.

Grundläggande parametrar för vissa mikrokontroller i AVR-familjen:

Mikrokontroller

Flashminne

RAM-minne

EEPROM-minne

I/O-portar

U makt

Ytterligare parametrar för AVR mega MK:

Drifttemperatur: -55…+125*С
Förvaringstemperatur: -65…+150*С
Spänning vid RESET-stiftet i förhållande till GND: max 13V
Max matningsspänning: 6,0V
Max I/O linjeström: 40mA
Maximal strömförsörjningsström VCC och GND: 200mA

ATmega 8X modell pinouts

Pinouts för ATmega48x, 88x, 168x modeller

Stiftlayout för ATmega8515x-modeller

Stiftlayout för ATmega8535x-modeller

Stiftlayout för ATmega16, 32x-modeller

Stiftlayout för ATtiny2313-modeller

Ett arkiv med datablad för vissa mikrokontroller bifogas i slutet av artikeln.

MK AVR installation FUSE bits

Kom ihåg att en programmerad säkring är 0, en oprogrammerad är 1. Du bör vara försiktig när du ställer in säkringar, en felaktigt programmerad säkring kan blockera mikrokontrollern. Om du inte är säker på vilken säkring du behöver programmera är det bättre att blinka MK utan säkringar för första gången.

De mest populära mikrokontrollerna bland radioamatörer är ATmega8, följt av ATmega48, 16, 32, ATtiny2313 och andra. Mikrokontroller säljs i TQFP- och DIP-paket; för nybörjare rekommenderar jag att köpa i DIP. Om du köper TQFP blir det mer problematiskt att flasha dem; du måste köpa eller löda brädan eftersom deras ben är placerade mycket nära varandra. Jag råder dig att installera mikrokontroller i DIP-paket på speciella uttag, det är bekvämt och praktiskt, du behöver inte löda upp MK om du vill återställa den eller använda den för en annan design.

Nästan alla moderna MKs har förmågan att in-circuit ISP-programmering, d.v.s. Om din mikrokontroller är lödd till kortet behöver vi inte avlöda den från kortet för att ändra firmware.

6 stift används för programmering:
ÅTERSTÄLLA- Logga in MK
VCC- Plus strömförsörjning, 3-5V, beror på MK
GND- Gemensam tråd, minus ström.
MOSI- MK-ingång (informationssignal i MK)
MISO- MK-utgång (informationssignal från MK)
SCK- MK-ingång (klocksignal i MK)

Ibland använder de också stiften XTAL 1 och XTAL2; kvarts är fäst på dessa stift om MK drivs av en extern oscillator; i ATmega 64 och 128 används inte MOSI- och MISO-stiften för ISP-programmering; istället är MOSI-stiften ansluten till stift PE0 och MISO till stift PE1. När du ansluter mikrokontrollern till programmeraren ska anslutningskablarna vara så korta som möjligt, och kabeln som går från programmeraren till LPT-porten bör inte heller vara för lång.

Mikrokontrollerns märkning kan innehålla konstiga bokstäver med siffror, till exempel Atmega 8L 16PU, 8 16AU, 8A PU etc. Bokstaven L betyder att MK:n arbetar med lägre spänning än MK utan bokstaven L, vanligtvis 2,7V. Siffrorna efter bindestrecket eller mellanslag 16PU eller 8AU indikerar den interna frekvensen för generatorn som finns i MK. Om säkringarna är inställda för att fungera från en extern kvarts, bör kvartsen ställas in på en frekvens som inte överstiger maxvärdet enligt databladet, detta är 20 MHz för ATmega48/88/168, och 16 MHz för andra atmegas.


Topp