AVR microcontroller tutorial

Gepost door Bastiaan Steenbergen op maandag 28 juli 2003 21:23

Inleiding

Bij deze microcontroller tutorial willen we je leren wat een microcontroller is en hoe je deze kunt programmeren en gebruiken. We hebben hiervoor een stuk theorie geschreven om je de basisbeginselen van de microcontrollers te leren. Daarnaast hebben we een praktijk gedeelte wat is opgebouwd rond een project, zodat je thuis zelf kunt experimenteren met een echte microcontroller. Het is wel vereist dat je al wat kennis hebt van digitale techniek. Ook ga ik er vanuit dat je het decimale, binaire en hexadecimale getallenstelsel kent. Als dit niet het geval is dan raad ik je aan om eerst hier wat over op te zoeken en te leren. Vooral in het begin zijn binaire getallen heel belangrijk.

Ik weet zeker dat er een wereld voor je open gaat en dat je na deze tutorial meer en meer erover wilt weten. Laat deze tutorial het begin zijn van een mooie basis voor toekomstige projecten.

Wat is een microcontroller

Een microcontroller is een digitaal IC dat volledig programmeerbaar is en taken kan verrichten. Intern bevat het vele geavanceerde hardware, zoals een ALU. Dit is een rekeneenheid die logische berekeningen kan uitvoeren. Ook bevat het een klein RAM geheugen om waardes in op te slaan. Daarnaast zit er ook vaak nog een EEPROM in. Dit is een geheugen wat zijn waardes behoud, ook zodra de spanning wordt weggehaald. Verder bevat het een ROM geheugen waarin je je eigen geschreven programma kunt laden. De chip zal, als die wordt ingeschakeld, het door jouw geschreven programma gaan uitvoeren. Om met de buitenwereld te kunnen communiceren zijn ze ook uitgerust met in- en uitgangspinnen, meestal word dit I/O genoemd (Input/Output). In het vervolg zal het woord microcontroller worden afgekort als C.

Wie maken ze

Er zijn verschillende fabrikanten die deze C's maken, om er een paar te noemen: Motorola, Atmel en Microchip. Maar er zijn er nog veel meer. Bij deze tutorial wordt er gebruik gemaakt van een Atmel controller. Zodra je redelijk bekent bent met deze C zul je weinig moeite ondervinden bij het leren van een andere, aangezien de techniek en werking van de meeste controllers op elkaar lijkt.

Welke types zijn er

Er bestaan veel verschillende types. Elk met hun eigen karakteristieken en functionaliteiten. Zo zijn erbij die alleen normale I/O poorten hebben, maar zijn er ook die speciale functies bezitten zoals, zoals A/D converters, RS232 ingebouwd protocol, PWM regeling, enz. Veel types kun je onderbrengen in een groep omdat ze dezelfde functies bevatten, deze groep noemen ze dan een familie. Elke chip in zo'n familie heeft dan bepaalde eigenschappen gemeen met de rest. Het verschil zit hem dan in de extra functies/opties die sommige dan weer bevatten. Zo kan binnen een groep alleen het aantal RAM geheugen dat beschikbaar is bijvoorbeeld verschillen. De C's zijn in vele verschillende behuizingen te verkrijgen. Enige voorbeelden, PDIP, TQFP, MLF, en SO.

Voordelen

Er zijn veel voordelen om een C te gaan gebruiken. Zo kun je volledig zelf bepalen wat een stukje elektronica moet doen, en in welke volgorde. Wil je later de uitvoering wijzigen dan hoef je alleen de chip eruit te halen, opnieuw te programmeren, en er weer in te plaatsten. Door gebruik te maken van de In-Circuit Programming mogelijkheid van vele AVR’s is het niet eens nodig de chip te verwijderen en kun je het programma updaten terwijl die in de schakeling blijft zitten. Ook het testen en simuleren van een programma is zeer gemakkelijk. Een ander voordeel is dat je veel functionaliteit krijgt en er weinig ruimte voor hoeft in te leveren op je printplaat. Dit geldt vooral bij het gebruik van de SMD versies.
Kijk je naar wat controllers kosten en vergelijkt met wat je allemaal ermee kan doen dan kosten ze zowat niks.

Nadelen

Ook zitten er natuurlijk nadelen aan C's. Zo moet je redelijk wat kennis hebben van hun werking wil je iets bruikbaars in elkaar zetten. Zowel op hard- als software gebied. Ook moet je moet beschikken over een stuk hardware waarmee je de C kunt programmeren. Afhankelijk van de programmeertal die je gaat gebruiken kan je ook nog eens veel geld kwijt zijn aan de benodigde ontwikkelsoftware.
Al met al zijn de nadelen te verwaarlozen als je ziet wat de voordelen zijn. Hierdoor maakt de professionele industrie al langer en steeds meer gebruik van C's. Microcontrollers zijn te vinden in bijna elk denkbaar apparaat dat tegenwoordig op de markt wordt gebracht. Enkele voorbeelden: GSM, koelkast, auto, alarmsysteem, wasmachine, pc, stereotoren, videorecorder, fotocamera’s, mp3speler, tv-afstandsbediening, joystick, horloge, enz.

Waarom Assembler

Bij deze tutorial wordt gebruik gemaakt van de programmeertaal assembler. Net zoals C, C++, Java, Basic, enz. ook programmeertalen zijn. Toch onderscheid assembler zich iets van de andere “hogere programmertalen” zoals C. Assembler noemt men een lagere programmeertaal omdat deze dichter bij de hardware staat. Je bedient vrijwel direct de hardware met assembler codes. Bij C is dit niet het geval. Een hogere programmeertaal moet worden gecompileerd. Dit proces maakt van bepaalde stukken C-code assembler instructies. En deze assembler instructies worden dan weer geassembleerd tot machinecode.
Het proces van hogere programmeertaal -> assembler heet, compileren.
Het proces van assembler -> machinecode heet, assembleren.

Het gaat de processor/controller uiteindelijk om de machinecode omdat dat het enigste is wat die begrijpt. Mensen begrijpen een taal zoals Nederlands, Engels, enz. Een processor praat alleen maar in machinecode welke bestaat uit een hexadecimale getallenrij. Iets wat voor ons totaal niet te lezen zou zijn.

Omdat wij geen machinecode kunnen lezen en dus ook niet kunnen schrijven is er assemblercode ontwikkelt. Zo kan de men via een soort mnemonics toch een programma schrijven in een taal die redelijk begrijpelijk is voor de mens. Door de steeds groter wordende programma’s en complexiteit kwam er de behoefte voor een taal die nog makkelijker was en dichter bij de menselijk taal stond. Hierdoor werd er een hogere programmeertaal ontwikkelt, zoals C, C++, enz. Deze taal staat, qua code gezien dichter, bij de menselijk taal en daardoor meer verwijdert van de processortaal. Dit is de reden van de toevoeging 'hogere' bij programmertaal.

Weergave van talenniveau'sWeergave van talenniveau's

Microcontrollers kunnen dus op verschillende manieren worden geprogrammeerd, waarbij C het makkelijkst is, of welk andere hogere taal dan ook. Toch is ervoor gekozen om bij deze tutorial gebruik te maken van assembler code. De reden hiervan is dat de code dichter bij de hardware staat en je dus ook meer betrokken bent bij de handelingen die de controller uitvoert op hardwareniveau. Iets wat belangrijk is aangezien de controller met andere hardware moet gaan communiceren/werken. Assembler is daarom een goede basis en mocht er behoefte aan zijn dan is de overstap naar een hogere taal niet groot.

Hardware

In dit hoofdstuk wordt de hardware toegelicht die van belang is. Aangezien C's zeer geavanceerde hardware bevatten is een uitgebreide uitleg nodig. De meest algemene zaken die van toepassing zijn op alle AVR types zullen hier worden besproken. Daarnaast zal ook nog wat extra info worden gegeven over wat meer specifieke hardware.
Zorg dat je altijd een datasheet bij de hand hebt als je gaat werken met C's. Stomweg zaken overnemen die je worden verteld is niet verstandig. Raadpleeg altijd de datasheet als het gaat om aansluitingen en voltageniveau’s.

Behuizing

C's bestaan er in vele soorten en maten. Vrijwel elke controller van Atmel is er in DIP en SMD uitvoering te verkrijgen, maar TQFP en PLCC komen ook veel voor.

Voeding

De voeding van een C geschiet op dezelfde wijze als bij elk ander IC, ze hebben een gnd en een positieve voedingsspanning nodig. De meeste types hebben +5v nodig, maar er bestaan ook varianten die op +3v draaien.
C's trekken zelden een constante stroom omdat ze namelijk veel schakelen, zowel intern als extern. Om te zorgen dat de voedingsspanning constant blijft is een condensator van 100nF dicht bij de voeding van de C aan te raden.

Heb je geen gestabiliseerde 5v dan kun je dit schema gebruiken om een spanning tussen de 18v en 7v om te zetten naar een mooie 5v voor de voeding.

Stabiele voedingStabiele voeding

Klok

Een C is een minicomputer. Hij bevat een rekencentrum en eromheen geheugens en andere hardwarecomponenten. Net zoals een PC loopt ook een C op een clocksignaal. Dit clocksignaal bepaalt de snelheid waarmee de controller kan werken. De meest voorkomende frequenties van de clock zijn: 1, 4, 8 en 16MHz. De meeste AVR controllers hebben een intern circuit wat die frequentie op kan wekken, men spreekt dan van een interne clock. Bevalt je die clocksnelheid niet dan kun je extern vaak ook nog een clock aansluiten door middel van een pulsgenerator of een kristal. Hieronder zie je een voorbeeld van hoe een kristal moet worden aangesloten. Raadpleeg de datasheet voor verdere gegevens en aansluitingen.

Kristal aansluitenKristal aansluiten

Reset

Net zoals je veel bij digitale IC’s aantreft zit er ook op een C een reset pin. Door deze pin te verbinden met de gnd kun je de controller resetten. Resetten wil zeggen dat alle interne variabelen hun beginwaarde krijgen en het programma vanaf het begin weer gaat starten. Deze mogelijkheid is vooral handig als de controller door programmabugs of externe signalen niet meer correct functioneerd of zelfs volledig is gestopt.
Door dus via een button de reset pin met de ground te verbinden kun je hiervan tijdens je applicatie gebruik maken.

ALU

Het hart van de controller is de ALU. Dit staat voor Arithmetic Logical Unit. Deze ALU kan logische berekeningen uitvoeren op maximaal twee binaire getallen. Zo kun je optellen, aftrekken, shiften, delen, vermenigvuldigen, AND, OR, XOR, enz.

De ALU is verbonden met 32 geheugengebieden, die registers heten. In de volgende paragraaf worden deze registers uitgelegd.

Registers

Elke AVR controller bezit een aantal geheugenplekken van 8 bits breed, die registers worden genoemd. 32 hiervan heten Special Purpose Registers (SFR), en elk van deze registers is direct met de ALU verbonden. Zowel met de 2 ingangen van de ALU als met de enkelvoudige uitgang ervan. Deze SFR’s hebben de naam Rx met op de plek van de x het nummer van het register. Dus je hebt de naam R1 tot en met R32. Om een SFR te gebruiken moet je hem aan spreken met zijn naam.

ALU & RegistersALU & Registers

Op het bovenstaande plaatje kun je dat duidelijk zien. Als er berekeningen moeten worden uitgevoerd dan gaan er (maximaal)2 getallen van 2 van de register de ALU in. Deze voert dan de gevraagde bewerking uit en spuugt die vervolgens aan de onderkant eruit. Via de 8-bits brede databus kan die uitkomst naar 1 van de 32 registers worden geschreven of ergens anders heengaan. Bijvoorbeeld een uitgangspoort, welke later aan bod komt en daarom nog niet op de tekening staat. Met deze 32 SFR’s werk je het meeste tijdens je programma. Vrijwel elke dataverplaatsing gaat via deze registers.

I/O registers

De rest van de registers, die gezamenlijk I/O registers worden genoemd, hebben elk hun eigen naam en vervullen aparte functies. Deze registers zijn er voor de hardware in de controller en bevatten instellingen en gegevens die nodig zijn voor de interne functies. Behalve een naam hebben deze registers ook een adres. Hier zal er eentje kort worden besproken zodat je weet wat het inhoud. Bij het hoofdstuk software word er veel dieper op ingegaan.
Het Status register, meestal afgekort tot SREG, is direct verbonden met de ALU zoals je kunt zien op het plaatje. Het bevat gegevens over de laatste berekening/bewerking die de ALU heeft uitgevoerd. Het werkt als volgt:
Dit SREG is 1 byte, dus 8 bits breed. Elk bitje in dit register heeft een eigen betekenis en een eigen naam. Zo bevat bitnummer 0, dus dat is de 1e vanaf rechts geteld, de betekenis van een wel of niet ontstane carry. De naam van dit bitje in het SREG is dus ook C als afkorting van Carry. Na elke bewerking die de ALU heeft uitgevoerd wordt dit bitje ge-update en hieraan kan men zien of de bewerking voor een carry heeft gezorgt. Is het ene getal in de ALU bijvoorbeeld binair gezien 1000.1111 en het andere getal 1111.0001 en de opdracht luid: 'tel op', dan komt er aan de uitgang van de ALU het getal 1000.0000. De 1 die er officieel voor hoort is natuurlijk te groot voor de 8 bits uitkomst dus komt er op de Carry plek in het SREG een 1 te staan welke eigenlijk zegt: JA, de bewerking heeft voor een carry gezorgt. Zou er nu een 0 staan dan betekent dit: NEE, er is geen carry.

Misschien is dit allemaal wat vreemd voor je er snap je het nog niet. Niet getreurt, het komt allemaal wel goed. Hieronder is een plaatje waar je ziet hoe het SREG eruit ziet, zodat je het wat beter kunt voorstellen.

Status Register (SREG)Status Register (SREG)

Hier zie je dus dat bitje 0 de C voorstelt. Zou de berekening/bewerking een carry veroorzaken dan komt er daar een 1 te staan, in het andere geval een 0.

RAM Geheugen

Een C bezit verschillende soorten geheugens. Hier is het RAM geheugen er eentje van. RAM geheugen is geheugen waarin data kan worden gelezen en geschreven. Deze waardes blijven alleen tijdens run-time aanwezig. Hiermee wordt bedoelt dat ze alleen hun waarde behouden zolang de C runt en dus een voedingsspanning heeft. Zodra deze spanning eraf gaat zijn de waardes die in het geheugen aanwezig zijn niet te voorspellen en dus volledig random.

Het RAM geheugen bestaat uit n grote kolom die is opgedeelt in allemaal rijen. Elke rij(geheugenplek) heeft zijn eigen adres en kan maximaal 8 bits aan data bevatten. Door middel van deze adressen kun je een stukje geheugen aanspreken en er wat in opslaan of vanaf halen. Je kunt dit dus gebruiken als tijdelijke opslag van getallen die maximaal 1 byte groot zijn, zoals tellerwaardes, uitkomsten, vergelijkingswaardes, enz.

Data Memory (RAM)Data Memory (RAM)

Alle registers zijn eigenlijk ook RAM plekken, zoals je kunt zien op bovenstaande plaatje. Dit is een afbeelding van het RAM geheugen van een AT90S2313 zoals het intern is geregelt. De adrestelling is altijd hexadecimaal. Het bovenste gedeelte van het geheugen bevat de 32 Special Function Registers zijn en de daaropvolgende de I/O registers, pas daarna komt het eigenlijk RAM gebied wat ze SRAM noemen.
Als je de 1e plek van het SRAM wilt gebruiken moet je dus adres $60 gebruiken. (let op, dit geldt voor de controller waar deze datasheet van is, elk type controller kan een andere memorygrootte hebben zodat het SRAM pas later of eerder begint)

ROM geheugen

Naast het handige RAM geheugen bezit de controller ook nog ROM geheugen. Dit is te vergelijken met je RAM alleen zijn de plekken niet 8 maar 16 bits breed en dit geheugen blijft zijn waardes altijd behouden, zelfs als de spanning wegvalt. In dit geheugen staat je zelfgeschreven programma. Een programma bestaat uit losse opdrachten die men instructies noemt. Elke instructie is 16 bits breed vandaar die breedte van dit geheugen.
Tijdens het flashen/programmeren van je C worden al die commando’s die je op de computer hebt geschreven in dit ROM neergezet.

Program counter

Zodra je de controller zijn voedingsspanning geeft begint die direct op plek 000h (van het ROM) de opdracht te lezen en uit te voeren. Zodra deze opdracht klaar is springt die naar adres 001h in het ROM en gaat die die opdracht lezen en uitvoeren, enz. enz. Telkens weer een stap verder in het geheugen. Om nou bij te houden waar die is gebleven is er een teller. Deze teller heet de Program Counter, dus de programma teller, logisch toch?! Vaak afgekort als PC.
Deze Program Counter is gewoon een teller die de waarde bevat van het ROM gebied dat de eerstvolgende uit te voeren instructie bevat. Deze counter zelf bevind zich in het I/O register gebied. Zodra de C wordt opgestart (door deze te resetten of door aan te sluiten op een spanning) wordt er 000h in de Program Counter gezet en begint de controller dus zijn 1e instructie op te halen van plek 000h. Nadat er een instructie is gelezen wordt de counter meteen met 1 verhoogt.
Om je nog even een totaal beeld te geven staat hieronder een samenvatting in de vorm van een plaatje

Geheugen indelingen en functiesGeheugen indelingen en functies

Inputs/Outputs

Behalve een ALU, RAM en ROM geheugen zit er nog veel meer in een C. Elk type bezit weer wat anders. Zo zijn er controllers die I2C, PWM, USART, Comparator, 8bit ADC, 10bit ADC, SPI en een Real Time Counter bevatten. Genoeg om wat leuks mee te doen dus. Daarnaast zijn er ook nog een aantal gewone I/O pinnen die je naar eigen wens kunt schakelen.
Elke functie heeft zijn eigen instellingen nodig en bezit daarom n of meerdere registers in het RAM geheugen. Door deze in te stellen kun je de functies gebruiken.

Na al deze theorie weet je grotendeels hoe de hardware in elkaar zit. Zoals je zelf hebt kunnen lezen is een C niet zomaar een klein zwart chipje, het bezit juist veel power en functies. Zelf blijf ik het onvoorstelbaar vinden dat het allemaal in zo’n klein ding past, prachtig gewoon.

Het flashen van een AVR controller

Als het programma is geschreven en om is gezet via een assembler/compiler dan rolt hier een file uit die machinecode’s bevat. Dit is de taal die de microcontroller spreekt en deze bestaat alleen uit hexadecimale getallen. Zo’n file heeft daarom ook vrijwel altijd de extensie .hex
Deze file moet nu in de controller worden geladen zodat deze de taken kan gaan verrichten die we van hem verlangen. Om dit te kunnen doen hebben we een hardwarematige interface nodig. Hier kun je het benodigde schema vinden. De software om deze hardware aan te sturen heet Ponyprog en is hier te downloaden. Ponyprog is een programma wat de microcontroller kan wissen, uitlezen en programmeren. Hieronder word uitgelegd hoe dit in zijn werk gaat.

Open Ponyprog en kies voor ‘Setup’ -> ‘Interface Setup…’. Kies in het scherm dat volgt voor, ‘Parallel’ en ‘AVR ISP I/O’ Selecteer dan de LPT poort waaraan de programmer hardware is aangesloten. Sluit dit scherm daarna door op OK te klikken.

interface setupinterface setup

Stel nu Ponyprog in op de controller die je wilt flashen. Dit gebeurt bovenin bij de drop-down buttons. Kies bij de linker voor AVR micro. De zojuist gemaakte instellingen hoeven maar eenmalig te geschieden en worden onthouden door Ponyprog voor volgende keren.

Nu gaan we ons richten op het flashen van onze specifieke file. Kies bij de rechter drop-down button het juiste AVR type dat word geflashed. Laad vervolgens de machinecode door te kiezen voor: ‘file’ -> ‘Open Program(FLASH) File …’ Zet bestandstypen op .hex want anders zie je je eigen machinecode file niet omdat Ponyprog standaard op .e2p staat. Open nu de .hex file die je in de controller wilt flashen. Eenmaal geopend zie je alle hexgetallen in het grote veld verschijnen.

de juiste AVR instellende juiste AVR instellen

Nu kan het flashen beginnen. Zorg ervoor dat de AVR in zijn voetje zit, en dat de programmerinterface aan de juiste parallele poort is aangesloten. Controleer ook of er +5v aanwezig is op de print, want deze is nodig om de interface zijn werk te laten doen. Je kunt nu op twee manieren het flashen starten, door middel van de sneltoetsen CTRL+W, en door te kiezen voor ‘Command’ -> ‘Write All’. Zodra er om een bevestiging wordt gevraagt kun je gewoon voor OK kiezen. Het verloop van het flashen wordt nu getoond. Eenmaal klaar geeft Ponyprog een melding van het succesvol programmeren.

Geeft Ponyprog een fout aan dan kan men het beste alle aansluitingen nagaan. Controleer of er wel +5v aanwezig is en of de AVR juist is geplaatst. Hierna kan meestal wel een succesvolle tweede poging worden ondernomen.

AVR ontwikkelboard

Om verder te kunnen met deze theorie en om het gebruik ervan in de praktijk toe te juichen zijn we bezig met het maken van een AVR ontwikkelboard. De voorbereidingen hiervoor zijn in volle gang. Het AVR board zal te koop zijn voor een zeer gunstige prijs en zal door vele kunnen worden gebruikt, zowel beginners als de wat meer gevorderde personen. Zodra er meer over bekend is kun je dat hier lezen.

Testbordje

Een testbordje is erg handig om je geschreven programma te testen. Of om bijvoorbeeld te leren hoe een microcontroller kan worden toegepast in een schakeling. Je kunt deze bordjes onder andere kopen bij Conrad. Je kunt er je onderdelen in 'prikken' en gemakkelijk weer uit verwijderen. Ze zitten vast in een soort klemmetjes. Hieronder zie je een plaatje van zo'n bordje. Op de voorkant kun je onderdelen zetten. Voor het gemak heb ik ook even de achterkant getekend zodat je ziet hoe de doorverbindingen lopen.

Een testbordjeEen testbordje

Slot

Meer info/Links

Op internet is nog veel meer te vinden over AVR's. In de meeste gevallen alleen in het Engels. Hier staan een aantal handige links:

Er zijn ook een aantal boeken geschreven over AVR controllers in zowel Engels als Nederlands. Zo heeft Elektuur bijvoorbeeld het boek: "AVR microcontrollers". Antratek verkoopt het boek AVR-microcontrollers van Volpe.
Voor meer titels verwijs ik je door naar Amerikaanse boekhandels zoals Amazon, enz.

Dankbetuiging

Dit artikel is mede tot stond gekomen door de leuke reacties op de PIC microcontroller tutorial. Ik hoop dat jullie dit artikel net zo goed vinden als mijn andere. Veel plezier met de opgedane kennis, en ik hoor graag van je wat je ervan vond.
Indien je opmerkingen, tips of wat anders kwijt wilt over dit artikel dan kun je dat doen door hieronder te reageren of door een topic te openen in het forum.