Atmega8 mikrokontroller. Atmega8 programmering för nybörjare. AVR mikrokontroller. Programmering för nybörjare Mikrokontroller atmega8 träning

december 2015

1. Fördelar med den föreslagna metoden

Enhetskretsar baserade på mikrokontroller (MCU) kännetecknas vanligtvis av en kombination av två svårkombinerade egenskaper: maximal enkelhet och hög funktionalitet. Dessutom kan funktionaliteten ändras och utökas i framtiden utan att göra några ändringar i kretsen - bara genom att byta ut programmet (blinkar). Dessa funktioner förklaras av det faktum att skaparna av moderna MKs försökte placera på ett chip allt som en utvecklare kan behöva elektronisk anordning– åtminstone så mycket som möjligt. Som ett resultat av detta skedde en förskjutning i tyngdpunkten från kretsar och installation till mjukvara. Med användningen av MK är det nu mindre behov av att "ladda" kretsen med delar, och det finns färre kopplingar mellan komponenter. Detta gör naturligtvis kretsen mer attraktiv för upprepning av både erfarna och nybörjare elektronikingenjörer. Men som vanligt måste du betala för allt. Inte heller detta var utan svårigheter. Om du köper en ny MK, installerar den i en krets som är korrekt monterad av delar som kan repareras och sätter på ström, då kommer ingenting att fungera - enheten fungerar inte. Mikrokontrollern behöver ett program.

Det verkar som att allt är enkelt med detta också - på Internet kan du hitta många system med gratis firmware. Men här finns det en hake: den fasta programvaran måste på något sätt "laddas upp" till mikrokontrollern. För någon som aldrig har gjort detta förut blir en sådan uppgift ofta ett problem och den främsta avstötande faktorn, vilket ofta tvingar dem att överge nöjen med att använda MK och leta efter system baserade på "lös" och stel logik. Men allt är inte så komplicerat som det kan verka vid första anblicken.

Efter att ha analyserat publikationer på Internet kan du se att detta problem oftast löses på ett av två sätt: att köpa en färdig programmerare eller göra en hemmagjord. Samtidigt är publicerade kretsar av hemmagjorda programmerare väldigt ofta orimligt komplexa - mycket mer komplexa än vad som egentligen är nödvändigt. Naturligtvis, om du planerar att flasha MK varje dag, är det bättre att ha en "cool" programmerare. Men om behovet av en sådan procedur uppstår sällan, då och då, kan du klara dig utan en programmerare helt och hållet. Nej, vi pratar förstås inte om att lära oss göra detta med tankens kraft. Det betyder att genom att förstå hur programmeraren interagerar med mikrokontrollern när han skriver och läser information i dess programmeringsläge kan vi nöja oss med tillgängliga verktyg för ett bredare syfte. Dessa verktyg måste ersätta både mjukvaru- och hårdvarudelar av programmeraren. Hårdvaran måste tillhandahålla en fysisk anslutning till MK-mikrokretsen, förmågan att tillämpa logiska nivåer på dess ingångar och läsa data från dess utgångar. Mjukvarudelen måste säkerställa driften av algoritmen som kontrollerar alla nödvändiga processer. Vi noterar också att kvaliteten på inspelningsinformation i MK inte beror på hur "cool" din programmerare är. Det finns inget som heter "bättre inspelad" eller "sämre". Det finns bara två alternativ: "registrerad" och "ej registrerad". Detta förklaras av det faktum att inspelningsprocessen inuti kristallen styrs direkt av MK själv. Du behöver bara förse den med högkvalitativ ström (ingen störning eller krusning) och organisera gränssnittet ordentligt. Om resultaten av testavläsningen inte visar några fel, är allt i sin ordning - du kan använda styrenheten för dess avsedda syfte.

För att kunna skriva ett program i MK utan att ha en programmerare behöver vi en USB-RS232TTL portomvandlare och, likaså. USB-RS232TTL-omvandlaren låter dig använda en USB-port för att skapa en COM-port som skiljer sig från den "riktiga" endast genom att dess ingångar och utgångar använder logiska TTL-nivåer, det vill säga spänning i området från 0 till 5 volt ( du kan läsa mer i artikeln " "). I vilket fall som helst är en sådan omvandlare användbar att ha i ditt "hushåll", så om du inte redan har en, är den definitivt värd att köpa. När det gäller de logiska nivåerna är TTL i vårt fall till och med en fördel jämfört med en vanlig COM-port, eftersom ingångarna och utgångarna på en sådan port kan anslutas direkt till vilken mikrokontroller som helst som drivs av 5 V, inklusive ATtiny och ATmega. Men försök inte använda en vanlig COM-port - de använder spänningar i intervallet från -12 till +12 V (eller -15...+15V). I detta fall är direktanslutning till mikrokontrollern oacceptabel!!!

Idén att skapa ett skript för Perpetuum M-programmet, som implementerar programmerarens funktioner, uppstod efter att ha läst ett antal publikationer på Internet som erbjuder vissa lösningar för MK-firmware. I varje fall upptäcktes allvarliga brister eller alltför stora svårigheter. Ofta stötte jag på programmeringskretsar som innehöll en mikrokontroller, och samtidigt gavs råd på allvar som: "... och för att programmera mikrokontrollern för den här programmeraren kommer vi att behöva... det stämmer - en annan programmerare!" Därefter föreslogs det att gå till en vän och leta efter betaltjänst och så vidare. Kvaliteten på programvaran som distribuerades på nätverket för dessa ändamål var inte heller imponerande - många problem märktes både med funktionalitet och med "molnigheten" i användargränssnittet. Det tar ofta mycket tid att förstå hur man använder ett program - det måste studeras även för att utföra de enklaste åtgärderna. Ett annat program kan göra något under lång tid och flitigt, men användaren lär sig att ingenting skrivs till MK först efter att hela den fasta programvaran har slutförts helt och efterföljande testläsning. Följande problem uppstår också: användaren försöker välja sin MK från listan över kristaller som stöds, men den finns inte i listan. I det här fallet kommer du inte att kunna använda programmet - inkludering i listan över saknade MKs tillhandahålls som regel inte. Att manuellt välja en styrenhet från listan ser dessutom konstigt ut, med tanke på att programmeraren i många fall själv kan bestämma typen av MK. Allt detta sägs inte för att kasta lera på befintliga produkter, utan för att förklara orsaken till utseendet på manuset för Perpetuum M-programmet, som beskrivs i den här artikeln. Problemet finns verkligen, och det gäller framför allt nybörjare som inte alltid lyckas ta sig över denna "vägg" för att ta sitt första steg in i mikrokontrollernas värld. Det föreslagna manuset tar hänsyn till de brister som finns i andra program. Maximal "transparens" av algoritmens funktion har implementerats, ett extremt enkelt användargränssnitt som inte kräver inlärning och ger ingen chans att bli förvirrad och "klicka på fel sak." Om den nödvändiga MK inte är bland de som stöds kan du lägga till dess beskrivning själv, ta nödvändiga data från dokumentationen som laddats ner från MK-utvecklarens webbplats. Och, viktigast av allt, manuset är öppet för studier och modifiering. Vem som helst kan genom att öppna in textredigerare, studera och redigera den efter eget gottfinnande, ändra befintliga funktioner efter din smak och lägg till saknade.

Den första versionen av manuset skapades i juni 2015. Den här versionen ger endast stöd för Atmels ATtiny- och ATmega-mikrokontroller med funktioner för att skriva/läsa flashminne, ställa in konfigurationsbitar och automatiskt detektera styrenhetstypen. Skriva och läsa EEPROM är inte implementerat. Det fanns planer på att komplettera skriptets funktionalitet : lägg till att skriva och läsa EEPROM, implementera stöd för PIC-kontrollanter etc. Av denna anledning har manuset ännu inte publicerats.Men på grund av tidsbrist försenades genomförandet av planen, och för att det bästa inte ska bli fienden till det goda beslutades det att publicera den befintliga versionen. Om de redan implementerade funktionerna inte räcker, var snäll och bli inte upprörd. I det här fallet kan du försöka lägga till den önskade funktionen själv. Jag kommer inte att dölja: idén att skapa det här skriptet har till en början också en pedagogisk betydelse. Efter att ha förstått algoritmen och lagt till något eget till den, kommer du att kunna bättre förstå hur MK fungerar i programmeringsläge, så att i i framtiden kommer du inte att befinna dig i positionen som en tjej framför en trasig bil, eftertänksamt titta på dess insida och inte förstå varför det "inte fungerar".

2. MK-gränssnitt i programmeringsläge

Det finns flera olika sätt att försätta regulatorn i programmeringsläge och arbeta med den i detta läge. Det enklaste att implementera för styrenheter i ATtiny- och ATmega-serien är kanske SPI. Vi kommer att använda den.

Men innan vi börjar överväga de signaler som är nödvändiga för att generera SPI kommer vi att göra ett antal reservationer. Mikrokontrollern har konfigurationsbitar. Dessa är något som vippbrytare, omkoppling som låter dig ändra vissa egenskaper hos mikrokretsen i enlighet med projektets behov. Fysiskt sett är dessa icke-flyktiga minnesceller, som de som ett program skrivs in i. Skillnaden är att det finns väldigt få av dem (upp till tre byte för ATmega), och de är inte en del av adressutrymmet i något minne. Att skriva och läsa konfigurationsdata utförs av separata kommandon i MK-programmeringsläget. Nu är det viktigt att notera att vissa konfigurationsbitar påverkar själva förmågan att använda SPI. Med några av deras värden kan det visa sig att SPI inte kan användas. Om du stöter på en sådan mikrokontroller hjälper inte metoden som föreslås i den här artikeln. I det här fallet måste du antingen ändra inställningarna för konfigurationsbitarna i programmeraren, som stöder ett annat programmeringsläge, eller använda en annan mikrokontroller. Men det här problemet gäller bara begagnade MKs, eller de som någon redan utan framgång har "lekat med". Faktum är att nya MCU:er kommer med konfigurationsbitinställningar som inte hindrar användningen av SPI. Detta bekräftas av testresultaten av programmeringsskriptet för Perpetuum M-programmet, under vilket fyra olika MK:er (ATmega8, ATmega128, ATtiny13, ATtiny44) framgångsrikt flashades. De var alla nya. Den initiala inställningen av konfigurationsbitarna överensstämde med dokumentationen och störde inte användningen av SPI.

Med tanke på ovanstående bör du vara uppmärksam på följande bitar. SPIEN-biten tillåter eller förnekar uttryckligen användningen av SPI, därför måste i vårt fall dess värde vara aktiverande. RSTDISBL-biten kan vända en av utgångarna på mikrokretsen (förutbestämd) till ingången för "återställnings"-signalen, eller inte vända den (beroende på värdet som skrivits till denna bit). I vårt fall är "återställning"-ingången nödvändig (om den saknas kommer det inte att vara möjligt att växla MK till programmeringsläge via SPI). Det finns också bitar i CKSEL-gruppen som specificerar källan för klocksignalen. De förhindrar inte användningen av SPI, men de måste också hållas i åtanke, för om det inte finns några klockpulser alls, eller om deras frekvens är lägre än vad som är acceptabelt för en given SPI-hastighet, kommer inget bra att hända heller. Vanligtvis har nya MCU:er som har en intern RC-oscillator CKSEL-gruppbitarna konfigurerade för att använda den. Detta passar oss ganska bra - klockning tillhandahålls utan extra ansträngning från vår sida. Det finns inget behov av att löda kvartsresonatorn eller ansluta en extern generator. Om de angivna bitarna innehåller en annan inställning måste du ta hand om klockningen i enlighet med inställningen. I det här fallet kan det vara nödvändigt att ansluta en kvartsresonator eller en extern klockgenerator till MCU:n. Men i den här artikeln kommer vi inte att överväga hur detta görs. Exemplen på att ansluta en MK för programmering i den här artikeln är utformade för det enklaste fallet.

Ris. 1. Datautbyte via SPI i programmeringsläge

Låt oss nu gå till figur 1, hämtad från dokumentationen för ATmega128A MK. Den visar processen att sända en byte till MK och samtidigt ta emot en byte från MK. Båda dessa processer, som vi ser, använder samma klockpulser som levereras från programmeraren till mikrokontrollern vid dess SCK-ingång - en av mikrokretsens stift, för vilken en sådan roll är tilldelad i SPI-programmeringsläget. Ytterligare två signallinjer ger datamottagning och överföring en bit per klockcykel. Genom MOSI-ingången kommer data in i mikrokontrollern och läsdata tas från MISO-utgången. Lägg märke till de två prickade linjerna från SCK till MISO och MOSI. De visar i vilket ögonblick mikrokontrollern "sväljer" databiten som ställts in på MOSI-ingången, och vid vilken tidpunkt den själv ställer in sin egen databit till MISO-utgången. Allt är ganska enkelt. Men för att föra in MK i programmeringsläge behöver vi fortfarande en RESET-signal. Låt oss inte heller glömma den vanliga GND-kabeln och VCC-strömförsörjningen. Totalt visar det sig att endast 6 ledningar behöver anslutas till mikrokontrollern för att flasha dess firmware via SPI. Nedan kommer vi att analysera detta mer i detalj, men för nu kommer vi att lägga till att datautbyte med MK i programmeringsläge via SPI utförs i paket om 4 byte. Den första byten av varje paket är i princip helt tillägnad instruktionskodning. Den andra byten, beroende på den första, kan vara en fortsättning på kommandokoden, eller en del av adressen, eller kan ha ett godtyckligt värde. Den tredje byten används främst för att överföra adresser, men kan ha ett godtyckligt värde i många instruktioner. Den fjärde byten sänder vanligtvis data eller har ett godtyckligt värde. Samtidigt med överföringen av den fjärde byten tar vissa kommandon emot data som kommer från mikrokontrollern. Detaljer för varje kommando finns i styrenhetens dokumentation i tabellen "SPI Serial Programming Instruction Set". För närvarande noterar vi bara att hela utbytet med styrenheten är byggt av en sekvens av 32-bitars paket, i vart och ett av vilka inte mer än en byte med användbar information överförs. Detta är inte särskilt optimalt, men överlag fungerar det bra.

3. Anslutning av MK för programmering

För att säkerställa att alla nödvändiga signaler tillförs mikrokontrollerns ingångar för att organisera SPI-gränssnittet och läsa data från dess MISO-utgång, är det inte nödvändigt att skapa en programmerare. Detta kan enkelt göras med den vanligaste USB-RS232TTL-omvandlaren.

På Internet kan man ofta hitta information om att sådana omvandlare är sämre och att inget allvarligt kan göras med dem. Men när det gäller de flesta omvandlarmodeller är denna åsikt felaktig. Ja, det finns omvandlare till försäljning som inte har alla ingångar och utgångar tillgängliga jämfört med en standard COM-port (till exempel endast TXD och RXD), samtidigt som de har en icke-separerbar design (mikrokretsen är fylld med plast - det är omöjligt att nå sina stift). Men dessa är inte värda att köpa. I vissa fall kan du få de saknade portingångarna och utgångarna genom att löda kablarna direkt till chippet. Ett exempel på en sådan "förbättrad" omvandlare visas i figur 2 (chip PL-2303 - mer information om syftet med dess stift i artikeln ""). Detta är en av de billigaste modellerna, men har sina egna fördelar när den används i hemlagad design. Fullständiga adapterkablar med en standard niostiftskontakt i änden, som en COM-port, är också utbredda. De skiljer sig från en vanlig COM-port endast i TTL-nivåer och inkompatibilitet med äldre programvara och lite gammal utrustning. Det kan också noteras att sladdarna på CH34x-chippet visar sig vara mycket mer pålitliga och stabila i olika extrema tester jämfört med omvandlare på PL-2303. Men vid normal användning är skillnaden inte märkbar.

När du väljer en USB-RS232TTL-omvandlare bör du också vara uppmärksam på dess drivrutins kompatibilitet med versionen av operativsystemet du använder.

Låt oss ta en närmare titt på principen för att ansluta en mikrokontroller och en USB-RS232TTL-omvandlare med hjälp av exemplet med fyra olika modeller MK: ATtiny13, ATtiny44, ATmega8 och ATmega128. Figur 3 visar det allmänna diagrammet för en sådan anslutning. Det kan förvåna dig att veta att RS232-signalerna (RTS, TXD, DTR och CTS) används på ett olämpligt sätt. Men oroa dig inte för det: Perpetuum M-programmet kan arbeta med dem direkt - ställ in utvärden och läs ingångstillstånd. I vilket fall som helst ger de mycket använda USB-RS232TTL-omvandlarna på CH34x- och PL-2303-chips denna förmåga - detta har verifierats. Det bör inte heller vara några problem med andra populära omvandlare, eftersom standard Windows-funktioner används för att komma åt porten.

Motstånden som visas i det allmänna diagrammet kan i princip inte installeras, men det är fortfarande bättre att installera dem. Vad är deras syfte? Genom att använda omvandlarens TTL-ingångar och -utgångar och mikrokontrollerns fem-volts strömförsörjning slipper vi därmed behovet av att koordinera logiska nivåer - allt är redan helt korrekt. Detta betyder att anslutningarna kan vara direkta. Men under experiment , allt kan hända. Till exempel, enligt elakhetens lag, kan en skruvmejsel falla precis på den plats där den omöjligt kunde falla och kortsluta något som inte i något fall bör kortslutas. Naturligtvis kan vad som helst visa sig vara en "skruvmejsel". Motstånd i det här fallet minskar ibland konsekvenserna. ett av deras syften är att eliminera en möjlig utgångskonflikt.Faktum är att efter att programmeringen är klar går mikrokontrollern in i normalt driftläge, och det kan hända att dess stift kopplat till omvandlarens utgång (RTS, TXD eller DTR) också blir en utgång, enligt programmet som just spelades in i MK. I det här fallet blir det mycket dåligt om två direktanslutna utgångar "bråkar" - försök att ställa in olika logiska nivåer. I en sådan "kamp" kan någon "förlora", men det vill vi inte.

Värdena för de tre motstånden väljs på nivån 4,3 KOhm. Detta gäller anslutningar mellan omvandlarens utgång och mikrokontrollerns ingång. Noggrannheten hos motstånden spelar ingen roll: du kan minska deras motstånd till 1 KOhm eller öka det till 10 KOhm (men i det andra fallet ökar risken för störningar när du använder långa ledningar på väg till MK). När det gäller kopplingen mellan omvandlaringången (CTS) och mikrokontrollerutgången (MISO) används här ett 100 Ohm motstånd. Detta förklaras av särdragen hos ingången på den använda omvandlaren. Under testerna användes en omvandlare på mikrokretsen PL-2303, vars ingångar uppenbarligen är anslutna till strömförsörjningen positiv med ett relativt lågt motstånd (i storleksordningen flera hundra ohm). För att "bryta uppdraget" var jag tvungen att installera ett motstånd med så litet motstånd. Du behöver dock inte installera det alls. På omvandlaren är detta alltid ingången. Det kan inte bli en utväg, vilket innebär att det inte kommer att uppstå någon konflikt mellan utgångar i någon händelseutveckling.

Om chipet har ett separat AVCC-stift för att driva analog-till-digital-omvandlaren (till exempel ATmega8 eller ATmega128), ska det anslutas till det gemensamma VCC-strömstiftet. Vissa IC:er har mer än ett VCC-strömstift eller mer än en GND. Till exempel har ATmega128 3 GND-stift och 2 VCC-stift. I en permanent design är det bättre att ansluta stift med samma namn till varandra. I vårt fall, under programmering, kan du använda en VCC- och GND-stift vardera.

Och här är hur ATtiny13-anslutningen ser ut. Figuren visar stifttilldelningarna som används vid programmering via SPI. Bredvid bilden ser du hur en tillfällig anslutning ser ut i verkligheten.


Vissa kanske säger att detta inte är allvarligt - anslutningar på ledningarna. Men du och jag är förnuftiga människor. Vårt mål är att programmera mikrokontrollern, spendera ett minimum av tid och andra resurser på den, och inte att visa upp sig inför någon. Kvaliteten blir inte lidande. Metoden "på ledningar" i det här fallet är ganska effektiv och motiverad. Att flasha styrenhetens firmware är en engångsprocedur, så det är ingen idé att täcka den med strass. Om det är avsett att ändra firmware i framtiden utan att ta bort styrenheten från kretsen (i den färdiga produkten), så tas detta i beaktande under installationen under tillverkningen av enheten. Vanligtvis installeras en kontakt (RESET, SCK, MOSI, MISO, GND) för detta ändamål, och MK kan blinka även efter installation på kortet. Men det här är kreativa nöjen. Vi överväger det enklaste fallet.

Låt oss nu gå vidare till ATtiny44 MK. Allt är ungefär sig likt här. Baserat på ritningen och fotot kommer inte ens en nybörjare att ha några svårigheter att ta reda på sambandet. Precis som ATtiny44 kan du ansluta ATtiny24 och ATtiny84 mikrokontroller - stifttilldelningarna för dessa tre är desamma.


Ett annat exempel på att tillfälligt ansluta en styrenhet för att programmera den är ATmega8. Det finns fler stift här, men principen är densamma - några ledningar, och nu är styrenheten redo att "fylla" information i den. Den extra svarta tråden på bilden som kommer från stift 13 deltar inte i programmeringen. Den är utformad för att ta bort en ljudsignal från den efter att MK lämnar programmeringsläget. Detta beror på det faktum att programmet laddades ner till MK under felsökning av skriptet för "Perpetuum M" speldosa.


Ofta finns en styrenhet tillgänglig i olika höljen. I det här fallet fördelas tilldelningen av stift för varje fall annorlunda. Om höljet på din kontroller inte liknar det som visas i figuren, kontrollera syftet med stiften i den tekniska dokumentationen, som kan laddas ner från MK-utvecklarens webbplats.

För att komplettera bilden, låt oss titta på att ansluta en MK-mikrokrets med ett stort antal "ben". Syftet med den extra svarta tråden på bilden som kommer från stift 15 är exakt samma som i fallet med ATmega8.


Du är förmodligen redan övertygad om att allt är ganska enkelt. Alla som vet hur man räknar stiften på mikrokretsar (från märket i en cirkel moturs) kommer att räkna ut det. Och glöm inte noggrannheten. Mikrokretsar älskar snygga människor och förlåter inte slarvig behandling.

Innan du går vidare till mjukvarudelen, se till att USB-RS232TTL-omvandlardrivrutinen är korrekt installerad (kontrollera Windows Enhetshanteraren). Kom ihåg eller skriv ner numret på den virtuella COM-porten som visas när du ansluter omvandlaren. Detta nummer kommer att behöva skrivas in i texten i manuset, som du kan läsa om nedan.

4. Script - programmerare för "Perpetuum M"

Vi kom på hårdvarudelen av "programmeraren". Detta är redan halva striden. Nu återstår det att ta itu med mjukvarudelen. Dess roll kommer att utföras av Perpetuum M-programmet under kontroll av ett skript, som implementerar alla nödvändiga funktioner för att interagera med mikrokontrollern.

Arkivet med skriptet ska packas upp i samma mapp där programmet perpetuum.exe finns. I det här fallet, när du kör filen perpetuum.exe, kommer en meny att visas på skärmen med en lista över installerade skript, bland vilka det kommer att finnas raden "AVR MK Programmer" (det kan vara den enda). Det här är linjen vi behöver.

Skriptet finns i PMS-mappen i filen "MK Programmer AVR.pms". Den här filen kan ses, studeras och redigeras vid behov i en vanlig textredigerare som Windows Notepad. Innan du använder skriptet kommer du troligen behöva göra ändringar i texten som är relaterad till portinställningar. För att göra detta, kontrollera namnet på porten som används i Windows Device Manager och, om nödvändigt, gör lämpliga ändringar på raden "PortName="COM4";" - istället för siffran 4 kan det finnas ett annat nummer. När du använder en annan USB-RS232TTL-omvandlarmodell kan du också behöva ändra inställningarna för signalinvertering (skriptrader som börjar med ordet "Hög"). Du kan kontrollera inverteringen av signaler med USB-RS232TTL-omvandlaren med hjälp av ett av exemplen i instruktionerna för Perpetuum M-programmet (avsnitt med funktioner för att arbeta med porten).

Undermappen MK_AVR innehåller filer med beskrivningar av styrenheter som stöds. Om kontrollern du behöver inte finns bland dem kan du lägga till den du behöver själv, enligt en analogi. Ta en av filerna som ett exempel och använd en textredigerare för att ange nödvändiga data, ta dem från dokumentationen för din mikrokontroller. Det viktigaste är att vara försiktig, ange data utan fel, annars kommer MK inte att programmeras eller programmeras felaktigt. Den ursprungliga versionen stöder 6 mikrokontroller: ATtiny13, ATtiny24, ATtiny44, ATtiny84, ATmega8 och ATmega128. Skriptet implementerar automatisk igenkänning av den anslutna styrenheten - du behöver inte specificera det manuellt. Om identifieraren som lästs från MK inte finns bland de tillgängliga beskrivningarna visas ett meddelande om att styrenheten inte kunde kännas igen.

Arkivet med manuset innehåller också ytterligare information. Mappen AVR controller inc files innehåller en mycket användbar och omfattande samling av controller definitionsfiler. Dessa filer används när du skriver dina egna program för MK. Ytterligare fyra mappar "MusicBox_..." innehåller filer med ett program i Assembly-språk och firmware redo för nedladdning till MK separat för ATtiny13, ATtiny44, ATmega8 och ATmega128. Om du redan har anslutit en av dessa MKs för programmering, som föreslås i den här artikeln, kan du flasha den just nu - du kommer att få en speldosa. Mer om detta nedan.

När du väljer raden "MK AVR Programmer" i skriptmenyn börjar skriptet att köras. Samtidigt öppnar den porten, skickar ett kommando till MK att byta till programmeringsläge, får bekräftelse från MK om den lyckade övergången, begär MK-identifierare och söker efter en beskrivning av denna MK med dess identifierare bland de tillgängliga filer med beskrivningar. Om den inte hittar den önskade beskrivningen visar den ett motsvarande meddelande. Om en beskrivning hittas öppnas programmerarens huvudmeny. Du kan se dess skärmdump i figur 8. Ytterligare förståelse är inte svårt - menyn är mycket enkel.

I den första versionen av skriptet är vissa funktioner hos en fullfjädrad programmerare inte implementerade. Det finns till exempel inget sätt att läsa och skriva till EEPROM. Men om du öppnar skriptet i en textredigerare kommer du att se att det är väldigt litet, trots att det viktigaste redan är implementerat i det. Detta tyder på att det inte är så svårt att lägga till de saknade funktionerna - språket är väldigt flexibelt, det låter dig implementera rik funktionalitet i ett litet program. Men i de flesta fall räcker även de befintliga funktionerna.

Vissa funktionsbegränsningar beskrivs direkt i skripttexten:
//implementerade inspelning endast från nolladressen (Utökad segmentadresspost ignoreras, LOAD OFFSET - också)
//ordningen och kontinuiteten för poster i HEX-filen kontrolleras inte
//kontrollsumma är inte markerad
Detta gäller att arbeta med en HEX-fil, från vilken firmwarekoden för MK:n är hämtad. Om den här filen inte är skadad kommer det inte att ha någon effekt att kontrollera kontrollsumman. Om det är förvrängt kommer det inte att vara möjligt att upptäcka det med skriptet. I de flesta fall kommer de återstående begränsningarna inte att skada, men du måste fortfarande ha dem i åtanke.

5. Speldosa - ett enkelt hantverk för nybörjare

Om du har en av dessa mikrokontroller: ATtiny13, ATtiny44, ATmega8 eller ATmega128, kan du enkelt förvandla den till en speldosa eller musikkort. För att göra detta räcker det att skriva motsvarande firmware i MK - en av de fyra som finns i mapparna "MusicBox_..." i samma arkiv med skriptet. Firmware-koder lagras i filer med tillägget ".hex". Att använda ATmega128 för ett sådant hantverk är naturligtvis "fett", precis som ATmega8. Men detta kan vara användbart för att testa eller experimentera, med andra ord i utbildningssyfte. Texterna till programmen i Assembler bifogas också. Programmen skapades inte från grunden - speldosans program från boken av A.V. Belov togs som grund. AVR mikrokontroller i amatörradiopraxis." Det ursprungliga programmet har genomgått ett antal betydande förändringar:
1. anpassad för var och en av de fyra MK:erna: ATtiny13, ATtiny44, ATmega8 och ATmega128
2. knappar har tagits bort - ingenting behöver anslutas till kontrollern förutom ström och en ljudsändare (melodierna spelas en efter en i en oändlig loop)
3. varaktigheten för varje ton reduceras med varaktigheten av pausen mellan tonerna för att eliminera störningar i musikalisk rytm
4. den åttonde melodin är kopplad, används inte i bokversionen
5. från det subjektiva: några "förbättringar" för att optimera och göra algoritmen lättare att förstå

I vissa melodier kan man höra falskhet och till och med grova fel, speciellt i "Smile" - i mitten. Ringsignalkoderna togs från boken (eller snarare, laddades ner från bokens författares webbplats tillsammans med den ursprungliga asm-filen) och har inte ändrats. Tydligen finns det fel i kodningen av melodierna. Men det här är inget problem - alla som är "vänliga" med musik kan enkelt lista ut det och fixa allt.

I ATtiny13, på grund av avsaknaden av en 16-bitarsräknare, var en 8-bitarsräknare tvungen att användas för att reproducera toner, vilket ledde till en liten minskning av tonernas noggrannhet. Men detta märks knappt på gehör.

Om konfigurationsbitarna. Deras inställningar måste motsvara tillståndet för den nya mikrokontrollern. Om din MK har använts någonstans tidigare måste du kontrollera tillståndet för dess konfigurationsbitar och, om nödvändigt, anpassa dem till inställningarna för den nya mikrokontrollern. Du kan ta reda på tillståndet för konfigurationsbitarna för den nya mikrokontrollern från dokumentationen för denna MK (avsnittet "Säkringsbitar"). Undantaget är ATmega128. Denna MCU har M103C-biten, som möjliggör kompatibilitetsläge med den äldre ATmega103. Aktivering av M103C-biten minskar avsevärt kapaciteten hos ATmega128, och denna bit är aktiv på den nya MK. Du måste återställa M103C till ett inaktivt tillstånd. För att manipulera konfigurationsbitar, använd motsvarande sektion av programmerarens skriptmeny.

Det är ingen idé att ge ett diagram över speldosan: den innehåller bara en mikrokontroller, strömförsörjning och en piezo-ljudsändare. Strömförsörjningen sker på exakt samma sätt som vi gjorde vid programmering av MK. Ljudsändaren ansluts mellan den gemensamma ledningen (regulatorns GND-stift) och en av MK-stiften, vars nummer finns i filen med programsammansättningskoden (*.asm). I början av programtexten för varje MK i kommentarerna finns en rad: " ljudsignal bildas vid stift XX." När programmeringsskriptet har slutfört sitt arbete, lämnar mikrokontrollern programmeringsläget och går in i normalt driftläge. Spelning av melodier börjar omedelbart. Genom att ansluta ljudsändaren kan du kontrollera detta. Du kan lämna ljudsändaren ansluten under programmering av kristallen endast om ljudet kommer från ett stift som inte används av SPI, annars kan den extra kapacitansen på stiftet störa programmeringen.

Uppgift: Låt oss utveckla ett program för att styra en lysdiod. När knappen trycks in tänds lysdioden och när den släpps slocknar den.

Låt oss först utveckla ett schematiskt diagram av enheten. I/O-portar används för att ansluta externa enheter till mikrokontrollern. Var och en av portarna kan fungera som både ingång och utgång. Låt oss ansluta lysdioden till en av portarna och knappen till den andra. För detta experiment kommer vi att använda en styrenhet Atmega8. Detta chip innehåller 3 I/O-portar, har 2 åtta-bitars och 1 sexton-bitars timer/räknare. Även ombord finns en 3-kanals PWM, 6-kanals 10-bitars analog-till-digital-omvandlare och mycket mer. Enligt min mening är en mikrokontroller bra för att lära sig grunderna i programmering.

För att ansluta lysdioden kommer vi att använda linje PB0, och för att läsa information från knappen använder vi linje PD0. Diagrammet visas i fig. 1.

Ris. 1

Genom motstånd R2 tillförs plus matningsspänning till ingången PD0, vilket motsvarar en logisk ettasignal. När knappen stängs sjunker spänningen till noll, vilket motsvarar en logisk noll. I framtiden kan R2 uteslutas från kretsen, ersätta den med ett internt belastningsmotstånd, ange de nödvändiga inställningarna i programmet. Lysdioden är ansluten till utgången på port PB0 genom strömbegränsande motstånd R3. För att tända lysdioden måste du lägga på en logisk ettsignal på PB0-linjen. Vi kommer att använda en intern masterklockgenerator på 4 MHz, eftersom enheten inte har höga krav på frekvensstabilitet.

Nu skriver vi programmet. Jag använder programmeringsmiljön för att skriva program AVR Studio Och WinAvr.Öppna AVR Studio, ett välkomstfönster dyker upp, klicka på knappen "Skapa ett nytt projekt", välj sedan projekttyp - AVR GCC, skriv projektnamnet till exempel "cod1", kontrollera både "Skapa projektmapp" och "Skapa" initialiseringsfil" kryssrutor, klicka på knappen "Nästa", välj "AVR Simulator" i det vänstra fönstret och "Atmega8" mikrokontroller skriv i det högra fönstret, klicka på knappen "Slutför", redigeraren och projektkategoriträdet öppnas - initiala inställningar är klara.

Låt oss först lägga till standardbeskrivningstext för Atmega8 med operatören för att bifoga externa filer: #omfatta

direktivsyntax #omfatta

#omfatta<имя_файла.h>
#inkludera "filnamn.h"

Vinkelfästen< и >ange för kompilatorn att inkluderade filer först måste letas efter i WinAvr standardmappen med namnet include. Dubbla citattecken " och " talar om för kompilatorn att börja söka i katalogen där projektet är lagrat.

Varje typ av mikrokontroller har sin egen rubrikfil. För ATMega8 kallas denna fil iom8.h, för ATtiny2313 - iotn2313.h. I början av varje program måste vi inkludera rubrikfilen för mikrokontrollern vi använder. Men det finns också en vanlig rubrikfil io.h. Förprocessorn bearbetar denna fil och inkluderar, beroende på projektinställningarna, den erforderliga huvudfilen i vårt program.

För oss kommer den första raden i programmet att se ut så här:

#omfatta

Alla C-program måste innehålla en huvudfunktion. Den heter main. Programexekveringen börjar alltid med exekveringen av huvudfunktionen. En funktion har en header - int main(void) och en body - den är begränsad lockiga hängslen {}.

int main(void)
{
funktionskropp
}

Vi kommer att lägga till vår kod i funktionens kropp. Returtypen anges före funktionsnamnet. Om funktionen inte returnerar ett värde, används nyckeln tomhet.

int- detta är ett 2-byte heltal, värdeintervallet är från - 32768 till 32767

Efter funktionsnamnet anges parametrarna som skickas till funktionen när den anropas inom parentes (). Om funktionen inte har några parametrar används nyckelordet tomhet. Fungera huvud innehåller en uppsättning kommandon, systeminställningar och huvudprogramslingan.

Därefter konfigurerar vi porten D vid ingången. Portens driftläge bestäms av innehållet i registret DDRD(informationsöverföringsriktningsregister). Vi skriver numret "0x00" (0b0000000 - i binär form) i detta register; ingenting är anslutet till denna port förutom knappen, så vi konfigurerar hela port D som en ingång. Du kan konfigurera porten bit för bit genom att skriva siffrorna 0 eller 1 i varje bit i registret (0-ingång, 1-utgång), till exempel DDRD = 0x81 (0b10000001) - den första och sista raden i port D fungerar som output, resten som input. Det interna belastningsmotståndet måste också anslutas. PORTx-registret styr om de interna motstånden slås på eller av när porten är i ingångsläge. Låt oss skriva enheter där.

Konfigurera porten B till utgången. Portens driftläge bestäms av innehållet i registret DDRB. Inget annat än en LED till porten B inte ansluten, så hela porten kan konfigureras som utgång. Detta görs genom att skriva till registret DDRB siffrorna "0xFF". För att förhindra att lysdioden tänds när du slår på den första gången, skriv till porten B logiska nollor. Detta görs genom att spela in PORTB= 0x00;

För att tilldela värden används symbolen "=" och kallas för tilldelningsoperatorn, inte att förväxla med tecknet "lika".

Portkonfigurationen kommer att se ut så här:

DDRD = 0x00;
PORTD = 0xFF;
DDRB = 0xFF;
PORTB = 0x00;

Vi skriver programmets huvudslinga. medan("while" från engelska) - detta kommando organiserar en loop, upprepar slingans kropp många gånger tills villkoret är uppfyllt, det vill säga medan uttrycket inom parentes är sant. I C anses ett uttryck vara sant om det inte är lika med noll, och falskt om det är det.

Kommandot ser ut så här:

medan (skick)
{
öglekropp
}

I vårt fall kommer huvudslingan att bestå av endast ett kommando. Detta kommando tilldelar register PORTB registervärde som ska inverteras PORTD.

PORTB = ~PIND; //ta värdet från port D, invertera det och tilldela det till PORTB (skriv till PORTB)

// C-uttryck läses från höger till vänster

PIND informationsinmatningsregister. För att kunna läsa information från styrenhetens externa utgång måste du först växla önskad bit av porten till ingångsläge. Det vill säga skriv till motsvarande bit i registret DDRx noll. Först efter detta kan en digital signal från en extern enhet matas till detta stift. Därefter kommer mikrokontrollern att läsa byten från registret PINx. Innehållet i motsvarande bit motsvarar signalen på portens externa stift. Vårt program är klart och ser ut så här:

#omfatta int main (void) ( DDRD = 0x00; //port D - ingång PORTD = 0xFF; //anslut belastningsmotståndet DDRB = 0xFF; //port B - utgång PORTB = 0x00; //ställ utgången till 0 while(1 ) ( PORTB = ~PIND; //~ bitvis inversionstecken ) )

Kommentarer används ofta i C-språket. Det finns två sätt att skriva.

/*En kommentar*/
//En kommentar

I det här fallet kommer kompilatorn inte att uppmärksamma vad som skrivs i kommentaren.

Om du använder samma program och ansluter 8 knappar och 8 lysdioder till mikrokontrollern, som visas i figur 2, kommer det att vara tydligt att varje bit av porten D matchar dess portbit B. Genom att trycka på SB1-knappen tänds HL1, genom att trycka på SB2-knappen tänds HL2 osv.

figur 2

Artikeln använde material från boken av A.V. Belov. "Handledning för AVR-enhetsutvecklare"

Jag har sagt mer än en eller två gånger att studera MK ska börja med assembler. En hel kurs på webbplatsen ägnades åt detta (även om det inte är särskilt konsekvent, men efter hand kammar jag det till ett adekvat utseende). Ja, det är svårt, resultatet kommer inte att vara den första dagen, men du kommer att lära dig att förstå vad som händer i din kontroller. Du kommer att veta hur det fungerar, och inte kopiera andras källor som en apa och försöka förstå varför det plötsligt slutade fungera. Dessutom är det mycket lättare för C att skapa redneck-kod som kommer ut med en höggaffel vid det mest olämpliga ögonblicket.

Tyvärr vill alla ha resultat direkt. Så jag bestämde mig för att gå åt andra hållet - göra en tutorial på C, men med att visa hans underkläder. En bra inbäddningsprogrammerare håller alltid sin hårdvara hårt vid bulten, så att den inte kan ta ett enda steg utan tillstånd. Så först blir det C-koden, sedan vad kompilatorn producerade och hur det hela faktiskt fungerar :)

Å andra sidan är C:s starka sida kodportabilitet. Om du förstås skriver allt rätt. Separera arbetsalgoritmerna och deras hårdvaruimplementationer i olika delar av projektet. Sedan, för att överföra algoritmen till en annan mikrokontroller, räcker det att endast skriva om gränssnittslagret, där alla anrop till hårdvaran skrivs, och lämna all arbetskod som den är. Och förstås läsbarhet. C-källkoden är lättare att förstå vid första anblicken (även om ... till exempel, jag bryr mig inte om vad jag ska peka på - vare sig det är C eller ASM :)), men återigen, om allt är skrivet korrekt. Jag kommer också att uppmärksamma dessa punkter.

Mitt felsökningskort kommer att fungera som den experimentella hårdvaran på vilken lejonparten av alla exempel kommer att installeras.

Det första C-programmet för AVR

Att välja en kompilator och ställa in miljön
Det finns många olika C-kompilatorer för AVR:
Först av allt detta IAR AVR C- är nästan definitivt erkänd som den bästa kompilatorn för AVR, eftersom själva styrenheten skapades i nära samarbete mellan Atmel och specialister från IAR. Men du måste betala för allt. Och den här kompilatorn är inte bara en dyr kommersiell programvara, utan har också så många inställningar att det tar mycket ansträngning att helt enkelt kompilera den i den. Jag utvecklade verkligen ingen vänskap med honom; projektet ruttnade på grund av konstiga fel vid länkningsstadiet (senare fick jag reda på att det var en sned spricka).

Andra kommer WinAVR GCC- en kraftfull optimeringskompilator. Helt öppen källkod, plattformsoberoende, i allmänhet, alla glädjeämnen i livet. Den integreras också perfekt i AVR Studio, så att du kan felsöka direkt där, vilket är jävligt bekvämt. I allmänhet valde jag det.

Det finns också CodeVision AVR Cär en mycket populär kompilator. Det blev populärt på grund av sin enkelhet. Du kan få ett fungerande program i den på bara några minuter - startkodsguiden underlättar detta avsevärt genom att stämpla ut standarder för initiering av alla möjliga saker. För att vara ärlig är jag lite misstänksam mot det - när jag väl var tvungen att demontera ett program skrivet av den här kompilatorn visade det sig vara någon form av röra och inte kod. En fruktansvärd mängd onödiga rörelser och operationer, vilket resulterade i en ansenlig mängd kod och långsam prestanda. Men det kanske fanns ett fel i DNA:t hos personen som skrev den ursprungliga firmwaren. Plus att han vill ha pengar. Inte lika mycket som IAR, men märkbart. Och i demoläge låter den dig inte skriva mer än 2kb kod.
Naturligtvis finns det en spricka, men om du ska stjäla är det en miljon, i IAR-bemärkelse :)

Det finns också Image Craft AVR C Och MicroC från mikroelektronik. Jag behövde inte använda någondera, men S.W.G. mycket berömmande MicroPascal, säger de, en fruktansvärt bekväm programmeringsmiljö och bibliotek. Jag tror att MicroC inte kommer att vara sämre, men det är också betalt.

Jag valde som sagt WinAVR av tre anledningar: det är gratis, det integreras i AVR Studio och det finns bara massor av färdig kod skriven för den för alla tillfällen.

Så ladda ner WinAVR-installationen med AVR Studio. Därefter installeras studion först, sedan rullas WinAVR ovanpå och kopplas till studion i form av en plugin. Jag rekommenderar starkt att du installerar WinAVR på en kort väg, ungefär som C:\WinAVR, på så sätt slipper du många problem med sökvägar.

Skapa ett projekt
Så, studion är installerad, C är fastskruvad, det är dags att försöka programmera något. Låt oss börja med det enkla, det enklaste. Starta studion, välj ett nytt projekt där, som AVR GCC-kompilator och ange namnet på projektet.

Ett arbetsfält öppnas med en tom *.c-fil.

Nu kommer det inte att skada att konfigurera visningen av vägar i studiobokmärkena. För att göra detta, gå till:
Meny Verktyg - Alternativ - Allmänt - Filflikar och välj "Endast filnamn" från rullgardinsmenyn. Annars kommer det att vara omöjligt att fungera - fliken kommer att innehålla hela sökvägen till filen och det kommer inte att finnas mer än två eller tre flikar på skärmen.

Projektuppsättning
I allmänhet anses det vara klassiskt att skapa en make-fil där alla beroenden beskrivs. Och det är nog rätt. Men för mig, som växte upp med helt integrerade IDE som uVision eller AVR Studio detta tillvägagångssätt är djupt främmande. Därför kommer jag att göra det på mitt sätt, allt med hjälp av studiomedel.

Peka på knappen med kugghjulet.


Det här är dina projektinställningar och mer exakta inställningar automatisk generering av makefile. På den första sidan behöver du bara ange den frekvens med vilken din MK kommer att fungera. Detta beror på säkringsbitarna, så vi antar att vår frekvens är 8000000Hz.
Var också uppmärksam på optimeringslinjen. Nu finns det -Os - detta är storleksoptimering. Lämna det som det är nu, så kan du försöka spela med den här parametern. -O0 är ingen optimering alls.

Nästa steg är att konfigurera sökvägarna. Först av allt, lägg till din projektkatalog där - du kommer att lägga till tredjepartsbibliotek där. Sökvägen ".\" visas i listan.

Make-filen har skapats, du kan titta på den i standardmappen i ditt projekt, ta bara en titt och se vad som finns där.


Det var allt tills vidare. Klicka på OK överallt och gå till källan.

Formulering av problemet
Ett tomt pappersark är frestande att implementera någon listig idé, eftersom det banala blinkandet av en diod inte längre fungerar. Låt oss omedelbart ta tjuren vid hornen och implementera kopplingen till datorn - det här är det första jag gör.

Det kommer att fungera så här:
När en etta (kod 0x31) kommer genom COM-porten kommer vi att slå på dioden, och när en nolla kommer (kod 0x30) stängs den av. Dessutom kommer allt att göras på avbrott, och bakgrundsuppgiften kommer att blinka en annan diod. Enkelt och meningsfullt.

Montering av kretsen
Vi måste ansluta USB-USART-omvandlarmodulen till USART-stiften på mikrokontrollern. För att göra detta, ta en bygel från två ledningar och placera den på stiften korsvis. Det vill säga, vi ansluter styrenhetens Rx till omvandlarens Tx och omvandlarens Tx till styrenhetens Rx.

I slutändan är detta diagrammet:


Jag överväger inte att ansluta de återstående stiften, ström eller återställa, det är standard.

Skriver kod

Låt mig genast göra en reservation för att jag inte kommer att fördjupa mig specifikt i beskrivningen av själva C-språket. Det finns helt enkelt en kolossal mängd material för detta, allt från det klassiska "C Programming Language" från K&R till olika manualer.

Jag hittade en sådan metod i mitt förråd, jag använde den en gång för att studera detta språk. Allt där är kort, tydligt och rakt på sak. Jag sätter gradvis ihop det och drar det till min hemsida.

Det är sant att inte alla kapitel har överförts än, men jag tror att det inte kommer att dröja länge.

Det är osannolikt att jag kan beskriva det bättre, så från utbildningskursen, istället för en detaljerad förklaring av subtiliteterna, kommer jag helt enkelt att tillhandahålla direktlänkar till enskilda sidor i den här manualen.

Lägger till bibliotek.
Först och främst lägger vi till de nödvändiga biblioteken och rubrikerna med definitioner. När allt kommer omkring är C ett universellt språk och vi måste förklara för honom att vi arbetar specifikt med AVR, så skriv raden i källkoden:

1 #omfatta

#omfatta

Denna fil finns i mappen WinAVR och den innehåller en beskrivning av alla register och portar på styrenheten. Dessutom är allt där listigt, med bindning till en specifik styrenhet, som överförs av kompilatorn via göra fil i parameter MCU och baserat på denna variabel kopplas en header-fil till ditt projekt med en beskrivning av adresserna till alla portar och register för just denna styrenhet. Wow! Utan det är det också möjligt, men då kommer du inte att kunna använda symboliska registernamn som SREG eller UDR och du måste komma ihåg adressen till var och en som "0xC1", vilket kommer att vara en huvudvärk.

Själva laget #omfatta<имя файла> låter dig lägga till innehåll av alla slag till ditt projekt textfil, till exempel en fil med en beskrivning av funktioner eller en bit annan kod. Och för att direktivet skulle kunna hitta den här filen angav vi sökvägen till vårt projekt (WinAVR-katalogen är redan registrerad där som standard).

Huvudfunktion.
Ett C-program består helt av funktioner. De kan kapslas och anropas från varandra i valfri ordning och olika sätt. Varje funktion har tre nödvändiga parametrar:

  • Returvärdet är t.ex. sin(x) returnerar värdet på sinus av x. Som i matematik, kort och gott.
  • De överförda parametrarna är samma X.
  • Funktionskropp.

Alla värden som överförs och returneras måste vara av någon typ, beroende på data.

Alla C-program måste innehålla en funktion huvud som en ingång till huvudprogrammet, annars är det inte alls C :). Genom närvaron av main i någon annans källkod från en miljon filer kan du förstå att detta är huvuddelen av programmet, där allt börjar. Så låt oss fråga:

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

int main(void) ( return 0; )

Det var allt, först enklaste programmet skrivet, det spelar ingen roll att det inte gör någonting, vi har precis börjat.

Låt oss ta reda på vad vi gjorde.
int Detta är den datatyp som huvudfunktionen returnerar.

Naturligtvis i en mikrokontroller huvud i princip ingenting kan returneras och i teorin borde det vara det void main(void), men GCC designades ursprungligen för PC och där kan programmet returnera värdet operativ system vid färdigställande. Därför GCC på void main(void) svär vid varning.

Detta är inte ett fel, det kommer att fungera, men jag gillar inte varningar.

tomhet detta är den typ av data som vi skickar till funktionen, i det här fallet huvud kan därför inte heller acceptera något utifrån tomhet- en dummy. En stubb används när det inte finns något behov av att sända eller returnera något.

Här är de { } lockiga hängslen är ett programblock, i detta fall kroppen av en funktion huvud, kommer koden att finnas där.

lämna tillbaka- det här är returvärdet som huvudfunktionen kommer att returnera vid slutförandet, eftersom vi har en int, det vill säga ett tal, då måste vi returnera ett tal. Även om detta fortfarande inte är meningsfullt, eftersom... på mikrokontrollern kan vi bara gå ingenstans från main. Jag returnerar null. För det spelar ingen roll. Men kompilatorn är vanligtvis smart och genererar inte kod för det här fallet.
Även om, om pervers, då från huvud Du kan gå till MK - till exempel falla in i bootloader-sektionen och köra den, men detta kommer att kräva att du manipulerar på låg nivå med firmwaren för att korrigera övergångsadresserna. Nedan ser du själv och förstår hur du gör. För vad? Detta är en annan fråga, i 99,999% av fallen är detta inte nödvändigt :)

Vi gjorde det och gick vidare. Låt oss lägga till en variabel, vi behöver den egentligen inte och det är ingen idé att introducera variabler utan den, men vi lär oss. Om variabler läggs till inuti kroppen av en funktion, är de lokala och existerar endast i den här funktionen. När du avslutar funktionen raderas dessa variabler och RAM-minnet allokeras för viktigare behov. .

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

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

osignerad betyder osignerad. Faktum är att i den binära representationen allokeras den mest signifikanta biten till tecknet, vilket innebär att talet +127/-128 passar in i en byte (char), men om tecknet kasseras kommer det att passa från 0 till 255. Vanligtvis behövs inte skylten. Så osignerad.
iär bara ett variabelnamn. Inte mer.

Nu måste vi initiera portarna och UART. Naturligtvis kan du ta och ansluta biblioteket och anropa någon form av UartInit(9600); men då vet du inte vad som egentligen hände.

Vi gör så här:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main(void) (osignerad char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider) ; UBRRH = HI(bauddivider) ; UCSRA = 0; UCSRB = 1<< RXEN| 1 << TXEN| 1 << RXCIE| 0 << TXCIE; UCSRC = 1 << URSEL| 1 << UCSZ0| 1 << UCSZ1; }

int main(void) (osignerad char i; #define XTAL 8000000L #define baudrate 9600L #define baudvider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO(bauddivider); UBRRH = HI(bauddivider); UCSRA = 0; UCSRB = 1<

Skrämmande? Faktum är att det bara finns fem sista raderna med riktig kod. Allt som #definiera det är ett förbehandlare makrospråk. Nästan samma saker som i Assembly, men syntaxen är något annorlunda.

De kommer att underlätta dina rutinoperationer för att beräkna de nödvändiga koefficienterna. I första raden säger vi det istället XTAL du kan säkert ersätta 8000000, och L- indikering av typen, som säger att lång är processorns klockfrekvens. Det samma baudrate— Frekvens för dataöverföring via UART.

bauddivider redan mer komplicerat, istället för det kommer uttrycket som beräknats med formeln från de två föregående att ersättas.
Bra och L.O. Och HEJ de låga och höga byten kommer att tas från detta resultat, eftersom Det kanske uppenbarligen inte passar in i en byte. I HEJ X (makroingångsparametern) förskjuts åtta gånger åt höger, vilket resulterar i att endast den mest signifikanta byten återstår. Och i L.O. vi gör bitvis OCH med siffran 00FF, som ett resultat kommer bara den låga byten att finnas kvar.

Så allt som är gjort är som #definiera du kan säkert slänga det och beräkna de nödvändiga siffrorna på en miniräknare och omedelbart skriva in dem på raderna UBBRL = …. och UBBRH = …..

Burk. Men! Gör det här ABSOLUT OMÖJLIGT!

Det kommer att fungera så eller så, men du kommer att ha sk magiska siffror- värderingar hämtade från ingenstans och av okända anledningar, och om man öppnar ett sådant projekt om ett par år så blir det jävligt svårt att förstå vad dessa värderingar är. Även nu, om du vill ändra hastigheten eller ändra kvartsfrekvensen, måste allt räknas om igen, men du ändrade ett par siffror i koden och det är allt. I allmänhet, om du inte vill bli stämplad som en kodare, gör sedan din kod så att den är lätt att läsa, förståelig och lätt att ändra.

Då är allt enkelt:
Alla dessa "UBRRL och Co" är konfigurationsregister för UART-sändaren med hjälp av vilka vi kommer att kommunicera med världen. Och nu har vi tilldelat dem de nödvändiga värdena, ställt in dem till önskad hastighet och läge.

Inspelningstyp 1< Betyder följande: ta 1 och sätt den på plats RXEN i byte. RXEN detta är den fjärde biten i registret UCSRB, Alltså 1< bildar det binära talet 00010000, TXEN- det här är den 3:e biten, och 1< ger 00001000. Singel "|" det är bitvis ELLER, alltså 00010000 | 00001000 = 00011000. På samma sätt ställs de återstående nödvändiga konfigurationsbitarna in och läggs till den allmänna högen. Som ett resultat registreras det insamlade numret i UCSRB. Mer detaljer beskrivs i databladet om MK i avsnittet USART. Så låt oss inte distraheras av tekniska detaljer.

Klart, dags att se vad som hände. Klicka på kompilering och starta emulering (Ctrl+F7).

Felsökning
Alla möjliga förloppsstaplar sprang igenom, studion ändrades och en gul pil dök upp nära ingången till huvudfunktionen. Det är här processorn körs för närvarande och simuleringen är pausad.

Faktum är att det från början faktiskt var på raden UBRRL = LO(bauddivider); Det vi har i definition är trots allt inte kod, utan bara preliminära beräkningar, varför simulatorn är lite tråkig. Men nu insåg han, den första instruktionen är klar och om du klättrar upp i trädet I/O-vy, till USART-sektionen och titta på UBBRL-byten där, kommer du att se att värdet redan finns där! 0x33.

Ta det ett steg längre. Se hur innehållet i det andra registret förändras. Så gå igenom dem alla, var uppmärksam på att alla angivna bitar är inställda som jag sa till dig, och de är inställda samtidigt för hela byten. Det går inte längre än till Return – programmet är över.

Öppning
Återställ nu simuleringen till noll. Klicka där Återställ (Skift+F5). Öppna den demonterade listan, nu kommer du att se vad som faktiskt händer i kontrollern. Visa -> Demonterare. Och inte YYAAAAAA!!! Assemblerare!!! SKRÄCK!!! OCH DET ÄR NÖDVÄNDIGT. Så att du senare, när något går fel, inte är dum i koden och inte ställer lata frågor på forumen, utan omedelbart sätter dig i magen och ser var du har fastnat. Det finns inget läskigt där.

Först kommer toppar från serien:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +00000000: 940C002A JMP 0x0000002A Hoppa +00000002: 940C0034 JMP 0x00000034 Hoppa +00000004: 940C0034 JMP 0x00000 +4C000000 +4C34 JMP 0x00000 +4C 0x00000034 Hopp +00000008: 940C0034 JMP 0x00000034 Hopp +0000000A: 940C0034 JMP 0x00000034 Hopp +0000000C: 34 J0C000x04 J0C0004 0000000E: 940C0034 JMP 0x00000034 Hopp +00000010: 940C0034 JMP 0x00000034 Hopp +00000012: 940C0034 JMP 0x00000 +400000 +4000 JMP 940C0000 0x00000034 Hopp +00000016: 940C0034 JMP 0x00000034 Hopp +00000018: 940C0034 JMP 0x00000034 Hopp +0000001A: 940 J0C000x4 : 940C0034 JMP 0x00000034 Hopp +0000001E: 940C0034 JMP 0x00000034 Hopp +000000020: 940C0034 JMP 0x00000030 9 JMP 020000034 0200000034 0200000034 JMP 020000034 JMP 020000034 0200000030 34 Hopp +00000024: 940C0034 JMP 0x00000034 Hopp +00000026: 940C0034 JMP 0x00000034 Hopp +00000028: 940C0030 Hopp 00304 JMP 00304

00000000: 940C002A JMP 0x0000002A Hopp +00000002: 940C0034 JMP 0x00000034 Hopp +00000004: 940C0034 JMP 0x00000 +4C34 JMP 0x00000 +40000 0x00000034 Hopp +00000008: 940C0034 JMP 0x00000034 Hopp +0000000A: 940C0034 JMP 0x00000034 Hopp +0000000C: 940 J0C0000000000E440 : 940C0034 JMP 0x00000034 Hopp +00000010: 940C0034 JMP 0x00000034 Hopp +00000012: 940C0034 JMP 0x00000030 9 JMP 000000034 Hopp +000000012: 940C0034 JMP 0x00000030 9 JMP 000000030 0400000034 JMP 010000034 0400000034 JMP 010000034 34 Hopp +00000016: 940C0034 JMP 0x00000034 Hopp +00000018: 940C0034 JMP 0x00000034 Hopp +0000001A: 940C0034 JMP +000040 JMP 00004 : 940C0034 JMP 0x00000034 Hopp +0000001E: 940C0034 JMP 0x00000034 Hopp +000000020: 940C0034 JMP 0x00000030 9 JMP 020000034 0200000034 0200000034 JMP 020000034 JMP 020000034 0200000030 34 Hopp +00000024: 940C0034 JMP 0x00000034 Hopp +00000026: 940C0034 JMP 0x00000034 Hopp +00000028: 940C0030 Hopp 00304 JMP 00304

Detta är avbrottsvektortabellen. Vi återkommer till det senare, men för nu är det bara att titta och komma ihåg att det finns. Den första kolumnen är adressen till flashcellen i vilken kommandot ligger, den andra är kommandokoden, den tredje är kommandot mnemonic, samma monteringsinstruktion, den tredje är kommandots operander. Tja, automatisk kommentar.
Så, om du tittar, finns det kontinuerliga övergångar. Och JMP-kommandokoden är fyra byte, den innehåller hoppadressen skriven bakåt - den låga byten vid den låga adressen och hoppkommandokoden 940C

0000002B: BE1F OUT 0x3F,R1 Ut till I/O-plats

Spelar in denna nolla på adress 0x3F. Om du tittar på I/O-vykolumnen kommer du att se att adress 0x3F är adressen till SREG-registret - kontrollenhetens flaggregister. De där. vi återställer SREG för att köra programmet på nollvillkor.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Ladda omedelbart +0000002D: E0D4 LDI R29,0x04 Ladda omedelbart +0000002E: BFDE OUT 0x3E,R29 Ut till I/O plats +0000002F:/8 Ut till I/O plats +00000002F:/8000002F

0000002C: E5CF LDI R28,0x5F Ladda omedelbart +0000002D: E0D4 LDI R29,0x04 Ladda omedelbart +0000002E: BFDE OUT 0x3E,R29 Ut till I/O plats +0000002F:/8 Ut till I/O plats +00000002F:/8 Ut till I/O plats

Detta laddar stackpekaren. Du kan inte ladda direkt i I/O-register, endast genom ett mellanregister. Därför först LDI till mellanliggande, och sedan därifrån OUT till I/O. Jag kommer också att berätta mer om stacken senare. För nu, vet att detta är ett dynamiskt minnesområde som hänger i slutet av RAM och lagrar adresser och mellanliggande variabler. Nu har vi angett var vår stack ska börja från.

00000032: 940C0041 JMP 0x00000041 Hopp

Hoppa till slutet av programmet, och där har vi ett förbud mot avbrott och looping tätt på sig själv:

1 2 +00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relativt hopp

00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relativt hopp

Detta är vid oförutsedda omständigheter, som att avsluta huvudfunktionen. Styrenheten kan tas ut ur en sådan slinga antingen genom en hårdvaruåterställning eller, mer troligt, genom en återställning från en vakthund. Tja, eller, som jag sa ovan, korrigera detta i hex-editorn och galoppera iväg dit vårt hjärta vill. Observera också att det finns två typer av övergångar: JMP och RJMP; den första är en direkt övergång till en adress. Den upptar fyra byte och kan direkt hoppa genom hela minnesområdet. Den andra typen av övergång är RJMP - relativ. Hans kommando tar två byte, men han flyttar sig från den aktuella positionen (adressen) 1024 steg framåt eller bakåt. Och dess parametrar indikerar offset från den aktuella punkten. Det används oftare pga tar upp halva utrymmet i en spolning, och långa övergångar behövs sällan.

1 +00000034: 940C0000 JMP 0x00000000 Hopp

00000034: 940C0000 JMP 0x00000000 Jump

Och detta är ett hopp till början av koden. En sorts omstart. Du kan kontrollera att alla vektorer hoppar här. Slutsatsen från detta är att om du nu aktiverar avbrott (de är inaktiverade som standard) och ditt avbrott inträffar men det finns ingen hanterare, så kommer det att ske en mjukvaruåterställning - programmet kommer att kastas tillbaka till början.

Funktion huvud. Allt är likt, du behöver inte ens beskriva det. Se bara på det redan beräknade antalet som förs in i registren. Kompilatorns förprocessor rockar!!! Så inga "magiska" siffror!

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

00000036: E383 LDI R24,0x33 Ladda omedelbart +00000037: B989 OUT 0x09,R24 Ut till I/O plats 15: UBRRH = HI(bauddivider); +00000038: BC10 UT 0x20,R1 Ut till I/O-plats 16: UCSRA = 0; +00000039: B81B UT 0x0B,R1 Ut till I/O-plats 17: UCSRB = 1<

Och här är buggen:

1 2 3 +0000003E: E080 LDI R24.0x00 Ladda omedelbart +0000003F: E090 LDI R25.0x00 Ladda omedelbart +00000040: 9508 RET Subrutin retur

0000003E: E080 LDI R24.0x00 Ladda omedelbart +0000003F: E090 LDI R25.0x00 Ladda omedelbart +00000040: 9508 RET Subrutin retur

Frågan är varför kompilatorn lägger till sådana toppar? Och det här är inget annat än Return 0, vi definierade funktionen som int main(void) och så slösade vi ytterligare fyra byte för ingenting :) Och om du gör void main(void) kommer bara RET att finnas kvar, men en varning kommer att visas , att vår huvudfunktion inte returnerar något. I allmänhet, gör som du vill :)

Svår? Uppenbarligen inte. Klicka steg-för-steg-exekvering i disassembler-läge och se hur processorn utför individuella instruktioner, vad som händer med registren. Hur sker rörelse genom kommandon och slutlig looping?

Fortsättning om ett par dagar...

Offtop:
Alexei78 Jag skapade ett plugin för Firefox som gör det lättare att navigera på min webbplats och mitt forum.
Diskussion och nedladdning,


Modern amatörradio kan inte föreställas utan mikrokontroller, och detta är uppenbart. Under de senaste decennierna har mikrokontroller från olika tillverkare blivit utbredda inom olika områden av mänsklig aktivitet. De kan ofta hittas i de mest oväntade enheter och design. Du och jag bevittnar datoriseringen och automatiseringen av processerna runt omkring oss. Sanningen är att utan kunskap om grunderna i programmering har det blivit nästan omöjligt att skapa moderna konkurrenskraftiga enheter...

Om du läser den här artikeln har du förmodligen en önskan om att förstå hur mikrokontroller fungerar, och har troligen frågor:

4. Vilken litteratur bör jag studera?

Låt oss försöka svara på dessa frågor.

1. Vilken mikrokontroller ska jag välja för jobbet?

8-bitars mikrokontroller är mycket populära bland radioamatörer. BILD Microchip Technology och AVR Atmel, 16-bitars MSP430 från TI, såväl som 32-bitars mikrokontroller, arkitekturer ÄRM.

Inom industrin, något annorlunda, är förstaplatsen med stor marginal upptagen av Renesas Electronics på den andra Freescale, på den tredje Samsung, gå då Mikrochip Och T.I., sedan allt annat.
Populariteten bestäms av pris och tillgänglighet, tillgången på teknisk information och kostnaden för mjukvarusupport spelar en viktig roll.

Vi kommer att studera 8-bitars AVR-mikrokontroller, familjer ATMEGA 8 och 16-serien. Valet bestämdes, återigen, av tillgänglighet, närvaron av många amatörutvecklingar och en enorm mängd utbildningsmaterial. Närvaron av en mängd olika inbyggda komponenter och funktionalitet i denna familj.

2. Vilken utvecklingsmiljö ska jag använda för att programmera den valda mikrokontrollern?

Olika integrerade utvecklingsmiljöer (IDE, Integrated Development Environment) har skapats för AVR.
IDär ett mjukvarusystem som används av programmerare för att utveckla programvara, vilket inkluderar:
textredigerare,
kompilator och/eller tolk,
monteringsautomationsverktyg,
felsökare

De vanligaste AVRStudio, ATmelStudio, WINAVR, CodeVision, IAR Embedded Workbench.
För att skriva program kommer vi att använda gratis IDE ATmelStudio version 6 och högre.
Du kan ladda ner Atmel Studio från den officiella webbplatsen efter registrering (registrering är helt gratis och förpliktar dig inte till någonting!)

ATmelStudio låter dig skapa projekt och skriva program både i assembler och i SI.

Inledningsvis är frågan alltid: vilket programmeringsspråk ska jag välja för att skriva effektiva program?

Mitt svar är enkelt: du måste kunna skriva på minst två språk: assembly och SI. Assembly-språk är helt enkelt nödvändigt när du behöver skriva snabba och kompakta subrutiner och makron, och olika drivrutiner. Men när du behöver skapa ett stort projekt byggt på komplexa algoritmer, utan kunskap om SI, kan mycket tid spenderas, särskilt i felsökningsprocessen, och om det finns en önskan att överföra det till en annan plattform, till exempel PIC18 , eller STM, kan det bli ett olösligt problem.
Dessutom har det nu dykt upp hårdvaruplattformar Arduino, arbete med vilket kräver kunskaper i SI++-språket.
Därför kommer vi att skriva program både i assembler och i SI.

För att tydligt se resultatet av ditt arbete utan att använda en lödkolv eller brödbräda, installera bara programmet Proteus.

3. Hur man flashar kontrollern, och vilka ytterligare enheter och tillbehör behövs för bekvämt arbete med dem?

Vi använder Datagorian. Dessutom måste du köpa breadboards och en strömkälla med en utspänning på 5 volt. Du kan använda den som en strömförsörjning med låg rippel genom att använda en 5-volts zenerdiod.
Kanske kommer Igor och jag med tiden att föreslå ett projekt för att montera ett felsökningskort.

4. Vilken litteratur bör jag studera?

Men till exempel:
Praktisk programmering av AVR i assembler. Revich, 2011
1000 och en mikrokontrollerkrets Vol. 1-2. Ryumik, 2010-2011
10 praktiska enheter på AVR MK Book 1-2. Kravchenko, 2008-2009
En handledning för en enhetsutvecklare som använder AVR MK. Belov, 2008
MK AVR-familjerna Tiny och Atmega. Efstifeev, 2008
CodeVisionAVR. En guide för nybörjare. Lebedev, 2008
Mikroprocessorstyrning av enheter, tyristorer, reläer. Belov, 2008
Analoga gränssnitt MK. Steward, Ball, 2007
Vi skapar enheter på AVR MK. Belov, 2007
MK AVR i amatörradioövning. Fullständig analys av ATTINY2313. Belov, 2007
Nätverk och internetarbete datautbyte med MK. Gå, 2007
MK AVR. workshop för nybörjare. Hartov, 2007
Tillämpning av AVR-scheman, algoritmer, program. Baranov, 2006
AVR mikrokontroller. Introduktionskurs. Morton, 2006
Mätning, styrning och reglering med hjälp av AVR. Trumpert, 2006
Programmering i C-språk för AVR och PIC MK. Shpak, 2006
Design av enheter på MK. Belov, 2005
MK - det är enkelt, volymerna 1-3. Frunze, 2002-2003
The C Programming Language, 2:a upplagan. Kernighan, Ritchie, 2009
Programmering av ATMEL-mikrokontroller på språket S. Prokopenko, 2012

5. Var på Internet kan du ställa frågor och få specifika svar?

Du kan ställa frågor på vårt eller något annat forum där ämnen om mikrokontroller berörs på ett eller annat sätt. Huvudsaken på forum är att formulera frågor korrekt för att tydligt få svar. Abstrakta frågor är inte välkomna, och med största sannolikhet kommer du att få hård kritik istället för ett svar, eller så förblir din fråga obesvarad!

Låt oss nu ta en närmare titt på vår favorit, ATMEGA 8 mikrokontroller

8-bitars AVR-mikrokontroller med hög prestanda och låg effekt
Progressiv RISC-arkitektur
130 högpresterande instruktioner, de flesta instruktioner exekveras i en klockcykel
32 8-bitars arbetsregister för allmänna ändamål
Helt statisk drift
Närmar sig 16 MIPS (vid 16 MHz) prestanda
Inbyggd 2-takts multiplikator

Icke-flyktigt program och dataminne
8 KB självprogrammerbart flashminne i systemet
Ger 1000 raderings-/skrivcykler
Ytterligare startkodsektor med oberoende låsbitar
Ger samtidigt läs/skrivläge (Read-While-Write)
512 bytes EEPROM
Ger 100 000 raderings-/skrivcykler
1 KB on-chip SRAM
Programmerbar låsning för att skydda användarprogramvara

Inbäddad kringutrustning
Två 8-bitars timer/räknare med separat förskalare, en med jämförelseläge
En 16-bitars timer/räknare med separat förskalare och fånga och jämföra lägen
Realtidsräknare med separat generator
Tre PWM-kanaler
8-kanals A/D-omvandlare (TQFP och MLF)
6 kanaler med 10-bitars precision
6-kanals analog-till-digital-omvandlare (i PDIP-paket)
4 kanaler med 10-bitars precision
2 kanaler med 8-bitars precision
Byteorienterat seriellt 2-trådsgränssnitt
Programmerbar seriell USART
Seriellt gränssnitt SPI (master/slav)
Programmerbar watchdog-timer med separat inbyggd oscillator
Inbyggd analog komparator

Speciella mikrokontrollerfunktioner
Startåterställning och programmerbar brownout-detektering
Inbyggd kalibrerad RC-oscillator
Interna och externa avbrottskällor
Fem lågförbrukningslägen: Idle, Power-save, Power-down, Standby och ADC-brusreducering

I/O-stift och hus
23 programmerbara I/O-linjer
28-stifts PDIP-paket, 32-stifts TQFP-paket och 32-stifts MLF-paket

Driftspänningar
2,7–5,5 V (ATmega8L)
4,5–5,5 V (ATmega8)

Arbetsfrekvens
0–8 MHz (ATmega8L)
0–16 MHz (ATmega8)

skillnader mellan ATMEGA16 och 8
16 KB självprogrammerbart flashminne i systemet

JTAG-gränssnitt (IEEE 1149.1-kompatibelt)
Perifer skanningskapacitet som är kompatibel med JTAG-standarden
Utökat stöd för inbäddad felsökning
Programmering via JTAG-gränssnitt: Flash, EEPROM-minne, byglar och låsbitar

Fyra kanaler PWM/PWM

8-kanals 10-bitars analog-till-digital-omvandlare
8 obalanserade kanaler
7 differentialkanaler (endast TQFP-paket)
2 differentialkanaler med programmerbar förstärkning på 1x, 10x eller 200x (endast TQFP-paket)

Sex lågförbrukningslägen: Idle, Power-save, Power-down, Standby, Extended Standby och ADC-brusreducering

32 programmerbara I/O-linjer

40-stifts PDIP-paket och 44-stifts TQFP-paket

AtmelStudio

Om du precis har börjat, måste du ladda ner och installera AtmelStudio-programmet från den officiella sidan atmel.com
När du har installerat programmet AtmelStudio kan du börja skapa ett projekt.
Projekt- det här är ditt program som du kommer att skriva, felsöka och flasha, efter kompilering, i minnet på mikrokontrollern.

För att skapa ett projekt måste du öppna programmet, följande skärmsläckare visas:

och sidan för att skapa projekt öppnas

För att skapa ett nytt projekt måste du klicka på "Nytt projekt..."
I det här fallet öppnas ett nytt fönster där du kan välja programmeringsspråk, namnet på projektet, dess plats, namnet på paketet med projektfilerna och möjligheten att skapa en katalog för vidare användning i andra tvärprojekt . För att skapa ett projekt där vi ska programmera i assembler måste vi välja - Assemblerare, efter det ändrar vi namnet på projektet, dess plats och väljer OK.

Följande fönster visas

Välja "megaAVR, 8-bitars" och hitta den mikrokontroller vi behöver, vi valde ATmega8. På höger sida av skärmsläckaren visas en lista över enheter som fungerar med denna mikrokontroller, varav en kan vi ansluta. Välja OK.

Textredigeringssidan visas, där du kan redigera och felsöka programmet. När sidan är tom anges tid och datum för skapande och namnet på projektfilen, användarnamn. Det finns ytterligare fönster för I/O-enheter och fönster för programsammanställningsrapporter. nu vi


Vi kan programmera i assembler.
Ett projekt för programmering i SI-språk skapas på samma sätt.

Hej, MySku-bor! Hjälten i vår recension är Atmega8A-16PU mikrokontroller. Jag kommer att berätta om programmering av denna mikrokontroller i CodeVisionAvr integrerade utvecklingsmiljö, vi kommer att blinka med lysdioden och vi kommer att överväga fördelarna och nackdelarna med att arbeta i den här miljön. Kanske kommer detta i framtiden att fungera som ett alternativ för dig till den redan "populära" Arduino. Om du är intresserad, gå till cut.

Inledning.
Det råkade bara vara så att jag började min bekantskap med MK med Arduino. Jag blinkade med lysdioden, kopplade in olika sensorer och sköldar och gjorde olika projekt. Allt fungerade, jag var nöjd, men jag ville ha något mer. Jag stötte på ett projekt där Atmega8A är involverat, för vilket jag måste skriva firmware själv. Det var han som pushade mig att studera processen att programmera en "naken" MK.
Så vi har en mikrokontroller från Atmel, AVR Atmega8A-familjen.

Specifikationer:


Pinout:


Här är
Nu för drift och programmering måste du ansluta den till programmeraren enligt diagrammet:

Tyvärr är jag som en skomakare - utan stövlar, nu har jag ingen programmerare till hands, så jag använder Arduino UNO för att ladda den färdiga firmwaren i mikrokontrollern och konfigurera säkringarna. Du behöver bara ladda ner "Arduinoisp"-skissen från mappen Arduino IDE-exempel och ansluta den enligt diagrammet:


Denna lösning har dock en betydande nackdel, som jag kommer att prata om lite senare. Innan vi börjar skriva ett program i CodeVisionAvr (nedan kallat CvAvr), måste vi bestämma vid vilken frekvens vår mikrokontroller ska fungera. Som standard, från fabriken, arbetar vår hjälte från en intern rc-generator med en frekvens på 1 MHz (med möjlighet att konfigurera om till 2, 4 och 8 MHz). Eftersom den interna rc-generatorn är kalibrerad på fabriken under vissa förhållanden (exakt spänning, temperatur), kan noggrannheten för dess drift under "fält"-förhållanden skilja sig från 3% till 10%. För uppgifter där hög timingnoggrannhet inte behövs kan detta försummas, i andra fall är det bättre att använda extern kvarts. I mitt projekt använde jag en extern kvarts med en frekvens på 8 MHz. Nu måste vi "förklara" för MC att den måste arbeta från extern kvarts. Detta görs genom att byta säkringar. För att uttrycka det i enkla termer är detta något som en BIOS, som på ett moderkort, där du anger dess driftslägen; på samma sätt berättar vi för MK i vilka lägen, förutom frekvensen, den ska fungera. All information kommer att lagras i ett icke-flyktigt minne.
Jag ska berätta om att fixera firmware under spoilern; de som vet hur man gör det själva kan scrolla vidare.

ytterligare information

Hur registrerar man samma säkringar?! Till detta använde jag programmet AvrDude, det är gratis och kan lätt hittas på Internet. För att korrekt ställa in säkringarna i enlighet med önskad frekvens, titta på databladet, eller så kan du använda en enkel.
Vi ställer in parametrarna som på bilden.


Allt är enkelt här:
Klockkälla - ställ in frekvensen (extern kristall 3 - 16 Mhz) från den externa kvartsen.
Starttid - MC-starthastighet efter att RESET har tagits bort eller ström är påslagen (16K CK + 4,1ms snabbt).
Markera rutan: Ext. Klocka/RC Osc./Lågfrekvens. Kristall: aktivera interna kondensatorer (36 pF)
Intern R/C Osc.: lämna omarkerad! Extern kristall: aktivera full swing (nödvändigt för >8 MHz).
Således fick vi Low Fuse 0xEF och High Fuse 0xC9. Bra, halva jobbet gjort. Nu ansluter vi mikrokontrollern till Arduino UNO respektive Arduino till datorn. Starta kommandoraden, gå till mappen med AvrDude. Ange sedan raden: avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U lfuse:w:0xef:m -U hfuse:w:0xc9:m
Så här ser det ut på bilden:


Låt oss analysera raden du angav:
avrisp är en typ av vår Arduino-liknande programmerare
COM13 är com-portnumret som identifierar vår Arduino i systemet (i ditt fall måste du slå upp det i enhetshanteraren)
19200 - com port hastighet, lämna som den är
m8 - indikerar att vår MK är Atmega8
-U säkring:w:0xef:m -U hsäkring:w:0xc9:m - vår låg säkring 0xEF och hög säkring 0xC9 anges här
Vara VAR FÖRSIKTIG!!, Felaktigt specificerad säkring kan leda till att MK blir murad (vi behöver inte dansa med en tamburin för att återställa den).
Vi trycker på "Enter" och vid utgången får vi resultatet, som på bilden:


Om inga fel uppstår under processen, då är arbetet klart, vår mikrokontroller kommer nu att arbeta från extern kvarts.
Du kan läsa om säkringar i detalj och även genom att söka på Google.


Nu är vi redo att börja programmera. För mig själv valde jag utvecklingsmiljön CvAvr. Programmeringsspråket kommer att skilja sig från Arduino, i CvAvr är det C-liknande. Låt oss skriva vår första Blink.
Efter installation och start av miljön kommer vi att använda guiden för att skapa projekt. Välj "Arkiv" - "Ny" - "Projekt". På frågan om vi kommer att använda guiden svarar vi jakande. Mål-AVR-chiptyp: AT90, ATtity, ATmega.
Så här ser projektguiden ut:


På fliken Chip, välj ATmega8A, Clock 8,000000 Mhz. Gå till fliken Portar. Vår LED kommer att anslutas till stift 14 på mikrokontrollern, enligt stiftet - PB0. På fliken väljer du Port B, Bit 0 byter från IN till OUT, dvs. Vi byter driftläge för det 14:e benet på vår mikrokontroller till utgången.


Detta avslutar mästarens arbete. Välj "Program" - "Generera, spara och avsluta". Vi sparar vårt projekt till exempel under namnet Blink.

Låt oss skaffa en sådan här fotduk

/*******************************************************
Detta program skapades av
CodeWizardAVR V3.12 Avancerat
Automatisk programgenerator
Chiptyp: ATmega8A
Programtyp: Ansökan
AVR Core Klockfrekvens: 8,000000 MHz
Minnesmodell: Liten
Storlek på extern RAM: 0
Datastapelstorlek: 256
*******************************************************/
#omfatta
#omfatta
// Deklarera dina globala variabler här

Void main(void)
{
// Deklarera dina lokala variabler här

// Input/Output Ports initiering
// Port B-initiering
// Funktion: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Ut
DDRB=(0<// Tillstånd: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PORTB=(0<

// Port C-initiering
// Funktion: Bit6=I Bit5=I Bit4=I Bit3=I Bit2=I Bit1=I Bit0=I
DDRC=(0<// Tillstånd: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<

// Port D-initiering
// Funktion: Bit7=I Bit6=I Bit5=I Bit4=I Bit3=I Bit2=I Bit1=I Bit0=I
DDRD=(0<// Tillstånd: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<

// Timer/Counter 0-initiering

// Klockvärde: Timer 0 Stoppad
TCCR0=(0<TCNT0=0x00;

// Timer/Counter 1-initiering
// Klockkälla: Systemklocka
// Klockvärde: Timer1 Stoppad
// Läge: Normal topp=0xFFFF
// OC1A-utgång: Frånkopplad
// OC1B-utgång: Frånkopplad
// Brusreducerare: Av
// Input Capture on Falling Edge
// Timer1 Bräddavbrott: Av
// Input Capture Interrupt: Av
// Jämför ett matchavbrott: Av
// Jämför B Match Avbrott: Av
TCCR1A=(0<TCCR1B=(0<TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2-initiering
// Klockkälla: Systemklocka
// Klockvärde: Timer2 Stoppad
// Läge: Normal topp=0xFF
// OC2-utgång: Frånkopplad
ASSR=0<TCCR2=(0<TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Räknare(r) Avbrott(ar) initiering
TIMSK=(0<

// Initiering av externa avbrott
// INT0: Av
// INT1: Av
MCUCR=(0<

// USART-initiering
// USART inaktiverad
UCSRB=(0<

// Analog Comparator-initiering
// Analog komparator: Av
// Den analoga komparatorns positiva ingång är
// ansluten till AIN0-stiftet
// Den analoga komparatorns negativa ingång är
// ansluten till AIN1-stiftet
ACSR=(1<SFIOR=(0<

//ADC-initiering
//ADC inaktiverad
ADCSRA=(0<

// SPI-initiering
// SPI inaktiverad
SPCR=(0<

// TWI-initiering
// TWI inaktiverad
TWCR=(0<

Medan (1)
{


Det finns inget att oroa sig för här; projektet specificerar driftlägen för portar, timers, avbrott, USART, Analog Comparator, ADC, SPI och anslutna bibliotek. Kort sagt, alla parametrar som vi angav i guiden, allt utom portarna och chippet, är konfigurerade som standard. Vi kommer att skriva huvudprogramslingan i while (1) (programtext). Därför att vi arbetar med PB0 (14 ben), i programslingan kommer vi att skriva:
medan (1)
{
PORTB.0=1;
delay_ms(1000);
PORTB.0=0;
delay_ms(1000);
}
Här sätter vi PB0 högt, väntar 1 sekund och sätter lågt, sedan upprepas cykeln. Glöm inte att inkludera biblioteket i början av projektet #inkludera . Vårt program är klart!!! Som du kan se är allt väldigt enkelt. Välj nu "Projekt" - "Bygg alla". Om inga fel gjordes kommer vi att se guidens rapport:

Storleken på vårt program var 198 byte och tog upp 2,4 % av mikronens minne.
Därefter sätter vi ihop diagrammet:


Gå nu till mappen med vårt projekt, gå till mappen "Debug", sedan "Exe", det finns en fil med en hex-förlängning. I mitt fall är det blink.hex.
Det är ett sista steg kvar. Kopiera den här filen till mappen med AvrDude. Vi startar kommandoraden igen, gå till vår mapp. Ange raden avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U flash:w:blink.hex
Så här ser det ut på bilden:


Om allt har skrivits in korrekt, tryck på "Enter"


Grattis! Jobbet är klart, lysdioden ska blinka glatt för dig :)
Slutsats.
Sammanfattningsvis vill jag säga om nackdelen med den Arduino-liknande programmeraren; CvAvr stöder det helt enkelt inte. Med till exempel AVRISP mkII i handen kan du flasha säkringarna och ladda ner programmet direkt från CodeVisionAvr. Förresten, den hembryggade programmeraren vägrade också att använda AvrDudes grafiska gränssnitt och arbetade bara från kommandoraden.
Jag kom på CodeVisionAvr ganska snabbt; Internet är fullt av text- och videolektioner. På ett par veckor behärskade jag driften av hårdvaru-PWM, avbrott, timers, arbeta med knappar och ansluta en grafisk display. Specifikt var jag tvungen att göra en del av mitt projekt: organisera en hårdvaru 16-bitars PWM på Atmega8, ansluta 2 knappar för att styra den och även visa dess driftslägen på en grafisk display, vilket jag gjorde med lätthet :) Här är en ett par bilder:

ytterligare information





Resultat i jämförelse med Arduino:
+ Att förstå CvArv är inte svårt eftersom det finns en guide för att skapa projekt;
+ Tillgänglighet för plugin-bibliotek, det finns tillräckligt med dem;
+ Snabb sammanställning;
+ Möjligheten att simulera ett projekt i Proteus, samt att felsöka det med den inbyggda debuggern;
+ Storleken på programmet är flera gånger mindre. Standard Blink tog oss 198 byte, en liknande skiss i Arduino IDE 1084 byte + 2 KB bootloader;
+ Möjlighet att implementera lägen som inte kan göras på Arduino. Till exempel, 16-bitars PWM (i allmänhet är det möjligt på Arduino, men bara med "kryckor");
+ Möjligheten att använda ATtiny, ATmega mikrokontroller för dina projekt där Arduino skulle vara redundant;
- Ändå är det bättre för en nybörjare att börja bemästra MK med Arduino;
- Programmeringsspråket skiljer sig från Arduino-behandling;
- Det finns fortfarande fler bibliotek för Arduino;
- CodeVisionAvr är ett betalprogram, det finns gratisversioner med begränsningar;
Genom att programmera den "nakna" mikrokontrollern i CodeVisionAvr fick jag mycket erfarenhet. Att studera timers, register, driftlägen, arkitektur, läsa datablad kommer att öka dina färdigheter, vidga dina vyer och öppna upp för nya aspekter av att arbeta med mikrokontroller.
Som en bonus bifogar jag ett par bilder när jag kom på den grafiska LCD-skärmen och lekte lite.





P.s. Det finns mycket mer jag ville skriva om, men det här kommer inte att vara en recension, utan en stor artikel. Jag är redo att svara på frågor inom min kompetens, privat eller i kommentarer. Du kan se många lektioner på AVR.

Topp