Innlevering Rapport

Innlevering Rapport
Datamaskinarkitektur
Innhold
Introduksjon ........................................................................................................................................ 2
Debugger/Programmer ....................................................................................................................... 3
Software Platform ............................................................................................................................... 7
Atmega32 Mikrokontroller – Grunnleggende ..................................................................................... 9
Få LED til å lyse .................................................................................................................................. 14
Knapp Aktivering ............................................................................................................................... 18
Tidsinnstilling – Timere...................................................................................................................... 28
Avbrudd – Interrupt .......................................................................................................................... 32
LCD..................................................................................................................................................... 33
Analog til Digital Konvertering (ADC) ................................................................................................ 41
Seriekommunikasjon – UART ............................................................................................................ 44
Konklusjon ......................................................................................................................................... 50
Appendix A ........................................................................................................................................ 51
Introduksjon
En mikrokontroller er en enhet du kan programmere til å gjøre nesten hva som helst. Du kan rigge
den med diverse, temperatur, lyd eller lyssensorer og gjøre målinger. En kan programmere den til
gjøre en viss handling ved en viss temperatur eller f.eks styre rødt, oransje og grønt lys i et lyskryss.
De kan finnes overalt; i kjøleskapet ditt, i displayet på vekkerklokken din, i omtrent alle funksjoner
som har vært hos oss lenge, men i den siste tid er gjort smartere.
En mikrokontroller er mye enklere enn en datamaskin, en trenger ikke en stor samling av forskjellige
verktøy eller et veldig stort repertoar av kunnskaper for å kunne programmere og lage sine egne
funksjoner. Dette er kanskje den største fordelen med en mikrokontroller; en kan gjøre svært mye
med den, den krever ikke store mengder ekstrautstyr. En kjøper det en trenger og
brukervennligheten er god i forhold til hvor anvendelig den er.
Jeg har da igjennom denne rapporten brukt mikrokontoller Atmel AVR Atmega32. En mikrokontroller
er en nesten som en type datamaskin bare ikke like avansert. En kan programmere en
mikrokontroller til å utføre en viss handling ved hjelp forskjellige programmeringsapplikasjoner på en
datamaskin som f.eks. C++ eller C#.
Det som gjør en mikrokontoller så anvendelig er blant annet at en har kontroll over hvilke funksjoner
hvilke pins skal ha. Faktum at hver pin ikke er tildelt en funksjon: Eks; pin 1 og 2 er for temperatur,
pin 3 og 4 er for lydsensor gjør at den blir mye mindre, og mulighetene er mange flere.
En mikrokontroller er lit annerledes å programmere enn en datamaskin. Heller hendelsesorientert
enn steg for steg orientert. En kan la den være steg for steg orientert, men hendelsesorientert er
mye mer lettforståelig og greiere ved hjelp av en mikrokontroller. Eks i et kjøleskap: da temperaturen
blir over 20 grader, sett på kjøleelementene og vis bokstavene ALARM i led displayet. eller da det har
gått 20 minutter, sett på kjøleelementet i fem minutter.
I denne rapporten vil jeg ta for meg en mikrokontroller, dens arkitektur. Jeg vil fortelle litt om
hvordan du anvender den og hva du trenger for å kunne anvende den til forskjellige funksjoner. Det
vil bli forklart enkle prinsipper og detaljer rundt mikrokontrolleren som kan være relevante både i
forhold til læring og videre læring rundt mikrokontrolleren. Jeg vil begynne på det enkleste stadiet
hvor jeg stadig bygger opp i vanskelighetsgrad og kompleksitet. Forhåpentligvis vil dette kunne være
forståelig og kunnskapsgivende for enhver som har motivasjonen til å lære seg å gjøre mye gøy med
en mikrokontroller.
Debugger/Programmer
Vi bruker AVR Pocket Programmer som er en nokså robust, god programmer. Den funker svært godt
med AVRdude og ATmega sine mikrokontrollere. Det er også noen sikringer med buffer og
strømbeskyttelse, så den gir oss et trygt alternativ.
En mikrokontroller er en elektronisk enhet (hardware) som sammen med programvare kan bruker til
å overføre maskinspråkkode til en mikrokontroller fra en datamaskin. Kompilatoren konverterer
koden skrevet på språk som f.eks..c eller java til maskin språkkoden (som er forståelig for maskiner /
mikrokontrollere) og lagrer den i en hex-fil. En programmer er et grensesnitt (et mellomledd) mellom
PC og selve målet, altså mikrokontrolleren.
En USB programmer bruker USB tilgangen vi har på datamaskinen til å sende data fra en datamaskin.
Fordelen med å bruke en mikrokontroller med USB er at du ofte kan bruke strømmen fra
datamaskinen for å holde liv i mikrokontrolleren. Uten en programmer ville vi ikke kunne fått til å
programmere vår mikrokontroller siden vår datamaskin ikke har koblinger til strøm og direkte
dataoverføring til en mikrokontroller.
Selve programmer inneholder somregel en mikrokontroller som er programmert på forhånd til å
motta data fra en datamaskin og programmere selve målet; altså mikrokontrolleren. I vårt tilfelle
overføres denne informasjonen til mikrokontrolleren med en SPI kabel. Selve denne
programmeringen er det som på engelsk kalles en Burn, eller programming.
Hvordan koble programmer til mikrokontroller.
For å koble sammen din datamaskin via programmer til mikrokontroller er det flere forskjellige
løsninger.
Det letteste er å koble Usb mini kabel og SPI kabel i programmer som vist på bildet.
og USB kabel (regner med du kjenner denne fra før) inn i din datamaskin.
For å koble til programmer i mikrokontroller er det an annen regle.
Dette kan løses på flere forskjellige praktiske måter men jeg har valgt å gå for en løsning med en
tapebit.
På andre siden av SPI kabelen har du en kobling med seks hull og ser slik ut. (venste bilde)
Det som er cluet her er å få disse koblet inn i tilsvarende porter på mikrokontrolleren. (høyre bilde)
Dette kan med første blikk se litt avansert og klønete ut og du kan prøve å koble det inn med
enkelvisk kabling.
Slik jeg valgte å løse det var å holde SPI kabelen i min venste hånd med klumpen (høyre side på
venstre bilde) inntil tommelen min.
Så stakk jeg seks tråder inn i hvert av hullene og kikket på bildet til venstre.
Sorter kablene, ta kabelen som er koblet inn i MOSI øverst, MISO nest øverst. SCK tredje øverst.
RESET tredje nederst, VCC nest nederst og GRND helt nederst. Trekk så en tapebit over dem slik at de
holder denne rekkefølgen.
Sluttresultatet vil se noe slik ut:
Hvordan sjekke at den fungerer?
Koble den til datamaskinens USB inngang. Koble inn SPI kablen og koble sammen de 6 pinnene til
mikrokontrolleren på et breadboard fra pin 6 til 11.
Da den er koblet til vil vi bruke programmet AVRDUDE. Som er det faktiske programmet som sender
koden du skriver til mikrokontrolleren.
1. For å bruke AVRDUDE får man først opp CMD vinduet.
Dette gjør du ved å trykke
Windows + R.
Da får du opp et vindu
Som ser slik ut
2. Skriv her inn cmd og trykk enter.
Da vil du komme til et vindu som ser slik ut:
3. I kommandovinduet skriv følgende
avrdude –c usbtiny –p m32.
avrdude forklarer av vi skal bruke avrdude som er den kjørbare filen.
vi bruker –c for å spesifisere hvilken type programmer vi har, som da er usbtiny.
og så –p og m32 for å vise hvilken type mikrokontroller vi bruker.
Etter å ha skrevet dette vil du få opp kommandolinjene
Som forteller deg at alt er ok.
har du problemer eller lurer på noe om avrdudes kjørbare fil kan du enkelt skrive avrdude –
help i kommandolinjen her i cmd og du vil få opp alle funksjonene avrdude kan utføre for oss.
Har du problemer og ikke fikk opp svar fra avrdude likt den ovenfor, sjekk først fysisk kabling.
Software Platform
For at du skal programmere noe til en mikrokontroller må du kunne kommunisere med den på et vis.
En Software Platform er et program(en software) som gir deg tilgang til denne kommunikasjonen.
Herunder har en flere forskjellige typer språk. Noen bygger på andre, slik som C# er et veldig enkelt
språk ofte brukt i Visual studio hvor mange av ordene du bruker for å programmere noe ligger lagret.
C# er bygget på det første og mest simple programmeringsspråket som heter .c. En sier at en
programmerer i C. Da du har programmert ferdig et språk. I din menneske leselige skrift, må dette
oversettes til datamaskinen. C er bare en type skrift om du velger å se på det på den måten. Igjen, Da
du har skrevet ferdig din kode i C trenger du å formidle denne informasjonen til mikrokontrolleren
din. Det er her en Software Platform kommer inn i bildet. Software Platformen er ditt hjelpemiddel
som menneske for å programmere, slik at du som menneske kan sitte og lese OG forstå, hva du
programmerer mikrokontrolleren til.
En Software Platform er definert som et område eller en omgivelse hvor flere små funksjoner og
applikasjoner kan kjøre. Her for eksempel Windows er en slags Software Platform samtidig som det
er en Operating Platform hvor en kan gjøre flere forskjellige operasjoner. I vårt tilfelle snakker vi om
en programmeringsplatform og likt med et operativsystem f.eks. så kan flere forskjellige funksjoner
kjøre under dette. En Programmeringsplattform er en plattform (derav navnet) en omgivelse/ et
program hvor du kan kjøre flere forskjellige operasjoner, eller ha muligheten til kjøre flere forskjellige
språk om ønskelig. Flere språk og funksjoner innenfor programmering er samlet på et og samme
sted(en platform) og dermed blir det en Programmerings Plattform.
Fordelen med å ha en Programmerings Plattform er at det gjør brukervennligheten og
kompleksiteten bak programmering så mye mer anvendelig. Her kan hver og en bruke hver sin
plattform og gjøre forskjellige operasjoner på forskjellige språk, alle med hver sin hensikt, på et og
samme sted.
En Software Platform er et rammenett for programmering av programmer for å forenkle
kommunikasjonen mellom det du skriver som menneske og informasjonen som skal sendes til
Hardware. Det har en mengde funksjoner og protokoller som gjør implementasjonen av Software
applikasjoner enklere. Det er enkelt forklart en samling av forskjellige Software moduler, protokoller,
kompilatorer og operasjoner alt tilgjengelig for deg som menneske i source code også kjent som
språket du skriver inn. En Software Platform gir deg en stor mengde ferdiggjort Software moduler
som gjør det mye enklere for deg å utvikle et program eller en software. Det sparer deg for å måtte
vite alt om hvordan hardware fungerer og dens protokoller du ellers måtte ha kunne.
I denne rapporten har vi tatt i bruk programmerings plattformen winAVR Programmers Notepad som
er en enkel og brukervennlig løsning for deg som en ny til programmering. Vi vil fokusere på å skrive i
C. slik at det du lærer, vil være lettere å forstå enn hvis du skulle ha programmert i et helt annet
språk som java. Hvor svært mye mer enn du tror allerede er ferdiggjort. WinAVR er et lett program
for din datamaskin og tilbyr enkel kommunikasjon mellom oss mennesker -> software ->
hardware(mikrokontroller).
Hvordan installere winAVR.
1. Åpne en nettleser av ditt valg og skriv inn winavr i google sitt søkefelt.
Klikk enter og søkeresultatene vil komme listet opp.
Se etter den grønne skriften winavr.sourceforge.net/
Klikk inn på siden
2. Siden vil se noe slik ut. Klikk da på hurtiglinken midt på startsiden som sender deg videre
Klikk her.
3. Du blir da sendt videre til en side som ser slik ut.
*Går dette ikke prøv en annen nettleser som f.eks internett eksplorer. Dette er fordi noen
nettlesere har blokkert slik at en nettside ikke kan sende deg videre til potensielle usikre
kilder. [Dette er en trygg link]
Klikk videre her og du vil kort etter starte en nedlastning for installasjon av winavr.
(3). Skulle dette mot formodning ikke gå. Følg direktelinjen
http://downloads.sourceforge.net/project/winavr/WinAVR/20100110/WinAVR-20100110install.exe?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fwinavr%2F&ts=1401724985&
use_mirror=softlayer-ams (hold inne ctrl og klikk)
4. Får du opp at datamaskinen krever tilgang fra administrator for å installere dette
programmet, vennligst trykk Ja.
Da du får opp denne pop-up. Gratulerer. Du har nå lastet ned winavr og er klar for
installasjon.
Velg ønsket språk
i dropdownlisten.
Klikk deretter OK
5. Du vil nå forhåpentligvis ha en skjerm som dette.
Klikk Neste -> Godta -> Neste -> Installer.
eller som mer datakyndige og slappe mennesker.
Enter -> Enter -> Enter -> Enter.
6. Gratulerer, installasjonen er nå i gang.
Len deg tilbake eller hent deg en kaffe. Det tar deg kanskje 30 sekunder avhengig av hvor
rask datamaskin du har.
7. Klikk ferdig. Og du er ferdig.
‘
Bruk av WinAVR
1. For å bruke programmet. Klikk Windowstasten (eller bare windowstegnet nede til venstre i
menyen)
2. Søk opp mappen WinAVR-20100110 og klikk på Programmers Notepad. [WinAVR]
3. Du er nå klar for å begynne å programmere.
Her er selve tekstboksen hvor du skriver
koden din.
WinAVR Brukerflate. Hva er hva?
Output felt.
Informerer om errors etc.
Meny med forskjellige underkategorier.
FILE: save, open, new.
VEIW: Hvis du mangler et vindu eller vil endre brukerflaten
TOOLS: Blir brukt da du skal kompilere filen og sende den til mikrokontrolleren.
WINDOW: hvis du vil endre utseende på programmers notepad. F.eks stablingen av
vinduer.
HELP: Blir bruk om du ønsker å rapportere en feil, eller se hjelp fra Programmers Notepad
sin hjemmeside. Denne vil du ikke få bruk for her.
4. Det vi ønsker å gjøre nå er å trykke på dropdown-list som sier Plain Text fra standard settings.
her velger vi C / C++ ettersom det er dette språket vi ønsker å programmere.
5. vi er nå klare til å programmere. Dette vil vi komme tilbake til senere.
Atmega32 Mikrokontroller –
Grunnleggende
I denne rapporten bruker vi mikrokontrolleren Atmel Atmega32. Den er omtrent som en datamaskin
hvor den kan kjøre igjennom en mengde oppgaver du gir den i form av et program.
Den er bygget på Harvard-Arkitektur. Hardvard arkitekturen er en datamaskinarkitektur med fysisk
adskilte lagrings og signal områder for intruksjoner og lagring av data. Selve navnet kommer fra
Harvard Mark 1 relle-baserte datamaskin som lagret instruksjoner på en 24 bits bred papirrull den
stakk hull i, og data lagret i elektromekaniske tellere. Disse tidlige masikinene hadde et begrenset
antall lagringsplass fullstendig avlukket inni CPUen (Central prossession unit).
I dag er de fleste prosessorer implementert med separerte områder for ytelsesgrunner men stammer
egentlig fra en utbedret Harvard arkitektur, så de kan støtte oppgaver som f.eks laste et program fra
disklagringen som data og så kjøre programmet.
Den utbedrede Harvard arkitekturen er nokså lik den originale. Men den har ikke en slik definert
skille mellom instruksjoner og data og lar CPUen aksessere to eller flere minne buses. Den aller
vanligste modifikasjonen inkluderer separerte instruksjoner og data cashe sammen med adresse
rom. Mens CPUen kjører en fil fra cache, fungerer den som en ren harvard-arkitektur. Når den
aksesserer minne, fungerer den som en von Naumann maskin (hvor koden kan bli flyttet rundt som
data).
Atmel ATMEGA32
Atmega32 er en nokså lik chip som lillebroren sin ATmega16. ATmega32 er en 8-bit rask
mikrokontroller i Atmel’s Mega AVR familien. Atmega32 er basert på en forbedret EICS (Reduced
Instruction Set Computing) arkitektur med 131 forskjellige instruksjoner. Atmega32 kan jobbe til en
maks frekvens på 16Mhz – som vil si 16 millioner instruksjoner i sekundet.
Atmega32 har en 32KB programmerbart flash minne, en statisk RAM på 2KB og et EEPROM på 1 KB.
Atmega32 har flere forskjellige pins som fungerer som input/output og du gir den strøm via enten
batteri eller en datamaskin. Den har en total av 40 pins og de er delt opp i hovedsakelig fire grupper.
PB, PA, PC, PD. Merk; P står for Pin og A,B,C,D er ofte fulgt av et nummer; som her representerer en
viss pin. Disse A,B,C,D pin gruppene kan brukes enten som input eller output av fem volt. Gruppe A,
altså Pin A0-A7 er helt spesielle, disse kan konvertere analogt signal til digitalt signal. Herunder kan
du spesifikt programmere mikrokontrolleren til å lytte etter analoge signal på PA0-PA7 (input) og du
vil kunne få oppgitt en digital verdi fra -255 til 255 f.eks. Den har et programmeringsrom hvor det
faktiske programmet blir lagret på chippen. Den har et minne, en plass for data og variabler
programmet kommer til å bruke og det har også en klokke som teller inni chippen. Tellingen kan telle
i mange forskjellige farter og dette kan du velge selv.
Reset input. Et lavt signal på denne pinnen for lengre enn en minimum puls vil generere en reset, selv
om klokken ikke går.
XTAL1 er input til en invertert klokke forsterker og input for interne klokke.
XTAL2 er output fra den inverterende klokke forsterkeren.
AVCC er power supply til pins for Port A og Analog til digital Converter. Den burde utvendig først bli
konvertert til VCC selv om ADC ikke er brukt. Om ADC blir brukt, burde det strømmen bli konvertert
til Vcc igjennom et low-pass filter.
AREF er en analog referanse pin for analog til digital konverteren. GRD er Jord. Alle PIN B,C,D har
også alternative funksjoner, disse vil jeg ikke komme nærmere inn på ettersom disse ikke vil være
relevante.
Register
I mikrokontrolleren atmel32 finnes det tre registre blant annet: Data-, adresse- og kontrollregistre. Et
register er et allokert minne satt av produsenten som kan gjøre at mikrokontrolleren f.eks. forstår
programkoden, kontrollerer de spesielle oppgavene til de forskjellige pinene og mye mer. Registeret
er altså et minne som kjenner igjen tilstanden til hver enkelt bit og som på den måten gjør at
mikrokontrolleren f.eks. vet hva den skal gjøre eller hva pinen er satt til å gjøre.
Et register er et allokert minne satt av fra produsentens side slik at mikrokontrolleren skal kunne
forstå f.eks. programkode eller kontrollere de forskjellige oppgavene til de forskjellige pins.
Registeret er altså et minne som kjenner igjen bits som kommer inn som gjør slik at
mikrokontrolleren vet hva den skal gjøre da den får en instruksjon, eks. hva pinnen er satt til å gjøre.
DDRx & PortX
Som nevnt har mikrokontrolleren tre forskjellige registre, disse har navn DDRx (Data Direction
Register), PORTx og PINx. Disse registrene brukes til å bestemme retningen (DDR), sette outputverdi
eller input verdi. Disse registrene kan brukes på 32 av I/O (input/output) portene til
mikrokontrolleren. Disse I/O portene har evnen til å sende og motta data, men de har også sine egne
spesielle alternative oppgaver som du kan enable ved ønske.
For å kunne bruke en hvilken som helst operasjon med hvilke som helst av pins trenger en å
konfigurere disse tre. X I vårt tilfelle representerer enten A, B,C eller D.
DDRx bestemmer input eller output. Skal det komme inn info eller ut info.
PORTX bestemmer om det er volt på eller av fra start. Naturligvis hvis DDRx er satt til output, da har
det noe å si om den samme pin – ved hjelp av PORTx registeret skal sende ut strøm eller ikke.
Her er en oversikt over de forskjellige pins med beskrivelse og deres alternative funksjon.
Pin
Nummer.
Pin navn
Beskrivelse
Alternativ funksjon.
1
(XCK/T0) PB0
I/O PORTB, Pin 0
T0: Timer0 External Counter Input.
XCK : USART External Clock I/O
2
(T1) PB1
I/O PORTB, Pin 1
T1:Timer1 External Counter Input
3
(INT2/AIN0) PB2
I/O PORTB, Pin 2
4
(OC0/AIN1) PB3
I/O PORTB, Pin 3
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(SS) PB4
(MOSI) PB5
(MISO) PB6
(SCK) PB7
RESET
Vcc
GND
XTAL2
XTAL1
(RXD) PD0
(TXD) PD1
(INT0) PD2
(INT1) PD3
(OC1B) PD4
(OC1A) PD5
(ICP) PD6
PD7 (OC2)
PC0 (SCL)
PC1 (SDA)
PC2 (TCK)
PC3 (TMS)
PC4 (TDO)
PC5 (TDI)
PC6 (TOSC1)
I/O PORTB, Pin 4
I/O PORTB, Pin 5
In System Programmer (ISP)
Serial Peripheral Interface (SPI)
I/O PORTB, Pin 6
I/O PORTB, Pin 7
Reset Pin, Active Low Reset
Vcc = +5V
GROUND
Output to Inverting Oscillator Amplifier
Input to Inverting Oscillator Amplifier
I/O PORTD, Pin 0
USART Serial Communication Interface
I/O PORTD, Pin 1
I/O PORTD, Pin 2
External Interrupt INT0
I/O PORTD, Pin 3
External Interrupt INT1
I/O PORTD, Pin 4
PWM Channel Outputs
I/O PORTD, Pin 5
I/O PORTD, Pin 6
Timer/Counter1 Input Capture Pin
I/O PORTD, Pin 7
Timer/Counter2 Output Compare Match Output
I/O PORTC, Pin 0
TWI Interface
I/O PORTC, Pin 1
I/O PORTC, Pin 2
I/O PORTC, Pin 3
JTAG Interface
I/O PORTC, Pin 4
I/O PORTC, Pin 5
I/O PORTC, Pin 6
Timer Oscillator Pin 1
29
PC7 (TOSC2)
I/O PORTC, Pin 7
30
AVcc
Voltage Supply = Vcc for ADC
31
GND
GROUND
32
AREF
Analog Reference Pin for ADC
33
PA7 (ADC7)
I/O PORTA, Pin 7
ADC Channel 7
34
PA6 (ADC6)
I/O PORTA, Pin 6
ADC Channel 6
35
PA5 (ADC5)
I/O PORTA, Pin 5
ADC Channel 5
36
PA4 (ADC4)
I/O PORTA, Pin 4
ADC Channel 4
37
PA3 (ADC3)
I/O PORTA, Pin 3
ADC Channel 3
38
PA2 (ADC2)
I/O PORTA, Pin 2
ADC Channel 2
39
PA1 (ADC1)
I/O PORTA, Pin 1
ADC Channel 1
40
PA0 (ADC0)
I/O PORTA, Pin 0
ADC Channel 0
AIN0: Analog Comparator Positive I/P
INT2: External Interrupt 2 Input
AIN1: Analog Comparator Negative I/P
OC0 : Timer0 Output Compare Match Output
Timer Oscillator Pin 2
Få LED til å lyse
LED
Navnet LED kommer fra Light Emitting Diode. Noe som er et svært godt beskrivende navn.
En lys utsende diode – direkte oversatt.
*Monokromatisk lys;
En LED heter på norsk lysdiode og er en elektrisk komponent som gir fra seg lys
Lys med bestemt bølgelengde
da den tilføres elektrisk strøm. Helt nøyaktig er det en halvleder diode som
som ikke skiller seg når det
lyser et monokromatisk* lys da det går elektrisk strøm inn i anoden og ut av
går igjennom et prisme.
katoden til dioden.
Fargen på lysdioden avhenger av hvilket halvledermateriale som er brukt. Fordeler med en lysdiode
er at den bruker mye mindre strøm og har opptil 50 tusen levetimer sammenliknet med den
tradisjonelle gløde eller halogenlampe som vanligvis lever fra 2500-5000 timer. De nyeste modellene
er også ufølsomme for temperaturvariasjoner, fall, støt, vibrasjoner (ettersom det ikke er noen
glødetråd(se bilde).
Store spenningsvariasjoner derimot er noe som kan ødelegge lysdiodene fort.
Vanlig glødelampe.
LED
Motstand
Motstand eller engelsk «Resistor». Er en elektronisk komponent som gir resistans da en sender strøm
igjennom den. Vanlig symbol for resistans er «R» og Sl-enheten for resistans er Ohm
og er
igjennom fysikken definert som forholdet mellom elektronisk spenning over komponenten og
elektrisk strøm igjennom den.
Per definisjon er motstanden R gitt av:
Hvor
R er komponentens motstandsverdi i Ohm, [ ]
U er spenningen over komponenten i Volt [V]
I er strømmen gjennom komponenten i Ampere [A]
Når det kommer til den elektroniske komponenten resistor eller mostand.
Er dette en liten brikke satt på en tråd som ved hjelp av fargekoding forteller deg hvor mye resistans
akkurat denne motstanden har.
Slik ser en typisk motstand ut
(med variasjoner av fargekoder)
En motstand er videre en topolet elektronisk komponent.
En motstand kan være enten en lineær motstand eller en ulineær motstand.
En Lineær motstand karakteriseres som oftest ved at motstanden har to verdier; Motstandsverdien
og tillatt maksimal effektforbruk. I tillegg oppgir det som oftest nøyaktig hvor nøyaktig den oppgitte
motstandsverdien er. Lineære motstander følger Ohms lov ved at motstandsverdien er uavhengig av
hvor mye strøm eller spenning den får inn.
En ulineær motstand endrer motstandsverdien sin etter hvor mye strøm om spenning den får inn.
Disse vil vi ikke komme bort i.
En motstand har flere forskjellige bruksområder. De aller vanligste innenfor vårt fagfelt er for
strømbegrensning hvor vi setter den på inn og utganger av elektroniske kretser for å beskytte andre
komponenter mot for mye strøm, slik at de ikke skal bli ødelagt. Her kan vi i et enkelt eksempel bruke
en motstand før en LED, for å beskytte denne.
Potensiometer
Et potensiometer er egentlig bare en resistor, men du har muligheten til å variere motstanden.
Derfor er et potensiometer også kaldt for en variabel motstand. Denne fungerer med at den har en
motstand på innsiden, og en ledetråd. En kan fra utsiden bestemme posisjonen til ledetråden på
motstanden og derfor variere hvor mye motstand den skal gi. Eks sett potensiometeret i ett hakk og
du vil få 0.5 Ohm, og i et annet tilfelle et annet hakk og du vil få 5 Ohm. Som Newbiehack sier; a fancy
voltage divider. Hvor en da i forhold til hvilken strøm som sendes inn, kan variere motstanden for å
f.eks. dele volt ut og gjøre den mindre.
På et potensiometer har du minimum tre pins. To for hver ende av resistoren som står på innsiden og
en for lederen også kaldt «wiper» på engelsk. Det er en motstand og en viper du kan flytte på denne
motstanden for å variere hvor mye motstand som kommer frem. Setter du en ende på hver av pins
som hører til resistoren vil du ikke kunne variere, men kunne få en måling på den maksimale
resistansen dette potensiometeret kan tilby. Setter du en ende på lederen eller «viperen» og en på
den ene resistans pinnen. Vil du da kunne snu på et hjul for å bytte posisjon på lederen på innsiden.
Desto nærmere du snur wiperen til endepinnen på resistansen, desto mindre motstand vil du kunne
få, desto lengre ifra ende pinnen av resistansen, desto mer motstand vil du få.
Ved å variere hvor mye motstand du får kan du da se ved hjelp av ohms lov at du kan velge hvor mye
volt du får ut. Dette er greit hvis du vet at du har et fem volts batteri, men bare trenger 2.5 volt. Du
kan da stille potensiometeret til ønsket resistans for å få 2.5 volt ut. Et potensiometer kan også
brukes til å stille volumet på en høyttaler; du stiller da resistansen opp for å minske volt ut (lavere
lyd) og du stiller resistansen ned for å øke volt ut (høyere volum).
Hvordan få LED til å blinke
Vi har nå koblet opp programmeren til breadboard vårt og vi er nå klare for å skrive vårt første
program i Programmers Notepad.
Men først må vi koble opp ledlyset til mikrokontrolleren.
Dette gjør vi slik:
LED.
-
+
For å bestemme hva som er pluss og minus på LED se etter den lengste lederen og det er pluss.
Her har vi koblet programmeren vår inn i mikrokontrolleren og den vil allerede ha strøm i seg
ettersom den får strøm fra datamaskinen inn på VCC.
For å hindre at denne lysdioden blir ødelagt vil vi legge til en motstand mellom + og pin B0. Her
legger vi en 400 ohms motstand.
Programmeringen av det første programmet
Her skal vi bruke Programmers Notepad som tidligere forklart under Software Platform.
How-to-do.
1. Åpne Programmers Notepad som forklart under Bruk av WinAVR.
2. Bytt feltet Plain Text til C / C++ som forklart under Bruk av WinAVR.
3. da starter vi programmeringen.
3. 1. vi starter først med å inkludere et bibliotek til programmeringen vår
start med å skrive #include <avr/io.h>
Her legger vi til en headerfile. Noe du ser fra .h, denne inneholder en del kode som gjør det enklere
for oss. Herunder blant annet en del koder og definisjoner for akkurat AVR mikrokontrollerne.
3.2 skriv
void main(void)
{
}
Her setter du starten på programmeringen din og det er her selve koden du har kommer.
Det er starten på skjelettet vårt.
void før main betyr at vi ikke skal retunere noe informasjon fra denne main koden, og void inni
parantesen betyr at vi ikke skal hente noe informasjon fra utsiden av denne main koden. F.eks. fra en
annen funksjon evt kunne ha laget ovenfor. {} tegnene betyr avgrensning for hvor vi skal skrive. Alt
utenfor disse vil kunne skape errors og {} definerer start og slutt på main. På engesk kalles de code
blocks, ettersom alt av kode du skaper på innsiden her blir inni denne blokken.
3.3 det første vi nå gjør er å sette Pin B0 til output, ettersom vi har lyst til å sende strøm ut til
lysdioden som er koblet på pin B0.
Inni avgrensiningene for main.
Skriv:
DDRB = 0b00000001; // det dette vil si er at alle 8 B pins bortsett fra nr 0. (siste desimal, settes til
input) siste desimal, altså eneren vår. Er pin B0 og settes til output, dette markert med 1.
PORTB = 0b00000001; // her setter vi pin B0, med 5 volt ut. Hadde det stått 0 på siste ville vi sendt ut
0 volt.
Semikolon er svært viktig, dette markerer at linjen med kode vi nettopp har skrevet, ender her ved
semikolon.
så avslutter vi med å skrive
While(1)
{
}
Det vi gjør da er å bruke c språket og si mens(while) er 1. så gjør noe. I dette tilfellet vil vi lage en
uendelig løkke. Slik at ja, vi sender ut 5 volt på pin B0, og dette gjør vi uendelig lenge. While(1) er den
mest typiske og enkleste uendelige løkken vi kan få.
Koden din skal da se slik ut:
3.4 Vi går da videre til å lagre filen.
Dette gjør vi enkelt med å klikke på diskettikonet oppe i venstre hjørne.
Lagre filen som; main.c
- Husk hvor du lagrer den.
3.5 Så må vi fikse konfigurasjonene for avrdude slik at vi kan kompliere filen og så startet
programmet vårt. Disse konfigurasjonene gjør vi slik at avrdude skal forstå hvilken mikrokontroller
den skal snakke til og hvordan avrdude skal sende over programmet vårt til vår mikrokontroller.
3.5.1 Åpne mappen WinAVR-20100110 som vist under Bruk av WinAVR og åpne programmet
MFile[WinAVR] i stedet for Programmes Notepad som gjordt tidligere.
3.5.2 Du vil da få opp et liknende vindu som dette.
Klikk MakeFile i menyen oppe til venstre. Bla ned -> Klikk MCU type -> ATmega -> atmega32.
(Det er her viktig at du velger den mikrokontrolleren du har. Jeg bruker atmega32 og velger derfor
dette.)
3.5.3. Vi må nå velge hvilken type programmer vi har.
Klikk meny oppe til venstre -> MakeFile -> Programmer -> velg en tilfeldig.
Grunnen til vi velger en tilfeldig er for å bli sendt til det riktige området i MakeFile og endre vår
programmer til usbtiny manuelt ettersom den ikke er listet opp på denne listen.
Igjen, velg bare usbtiny hvis det er dette du bruker, jeg bruker usbtiny og vil derfor velge den i dette
eksemplet.
3.5.4. Klikk så Makefile igjen -> Enable Editing of Makefile (nederst på dropdownlist)
Dette er slik at vi kan gjøre endringene våre manuelt.
Du vil få merket et gult felt, og skriv der inn følgende: usbtiny. (se bilde under)
3.5.5. Sist men aller minst må vi endre porten til riktig enhet.
Klikk Makefile -> Port -> velg USB.
3.5.6. Så lagrer vi filen, gå til Menyen -> File -> Save as. (Finn adressen eller mappen du lagret
main.c under punkt 3.4) -> klikk Save.
3.6. Vi er nå klare for å programmere og kjøre det første programmet vårt.
Gå inn i Programmers Notepad.
1. Klikk [WinAVR] Make All
2. Klikk [WinAVR] Program
3.8 Du vil kunne se i Outputvinduet (forklart under WinAVR brukerflate) om du har noen errors.
Er det ingen errors. Gratulerer. Lyset skal nå lyse.
Så hvordan få det til å blinke?
3.9. Dette gjør vi med noen få endringer i .c fila vår.
og vil etter endringer se slik ut:
Vi har her lagt til et nytt bibliotek slik at vi kan bruke kommandoen
_delay_ms(100)
Vi har flyttet inn PORTB = 0b00000001; inn i den uendelige løkken
Og laget en forsinkelse (delay) på 100ms mellom dem
Som vi lærte tidligere så betyr den siste eneren Pin B0 på.
og hvis du bytter den til null slår den seg av.
Her vil det gå i en uendelig løkke mellom
Slå på pinb0
Koden leses nedover og da den når slutten av
vent 100ms
while løkken, vil den begynne på toppen igjen.
slå av pinb0
I uendeligheten.
vent 100ms
3.10. Klikk så Make All og Program som vist under 3.6 og gratulerer. Har du skrevet riktig som
står her, og koblet som vist i tutourial. Da har du et blinkende lys.
Føl deg fri til å endre tidsintervallene med å sette en høyere millisekund verdi inni parentesen for
å prøve deg litt frem. Husk etter koding. Make All & Program for å sende filen til
mikrokontrolleren.
Knapp Aktivering
En knapp eller også en bryter, er en svært enkel elektronisk krets.
Trykk en gang og du får tilkobling, trykk en gang til og du får frakopling. Dette vil i praksis si, strøm,
ikke strøm. Noen knapper er slik at du kun får strøm da du holder knappen inne, og noen skur seg av
og på for hvert dedikerte trykk. Dette er vår måte å kontrollere om en krets er lukket (fører strøm)
eller åpen (fører ikke strøm).
Knapper har du overalt, du bruker dem hver dag til å skru av og på lyset, men du bruker dem også
akkurat i øyeblikket hvor du sitter å skriver på datamaskinen.
Knapp aktivering
For å få en knapp til å fungere i kretsen vår må vi først koble opp.
La kretsen være som du har koblet tidligere, koble en kabel fra pin B1. (se mikrokontroller). Til det
ene beinet på knappen. Koble en kondensator mellom de to beinene og en kabel fra det andre beinet
til jord. La LED lyset stå som tidligere med et ben i pin B0 og et annet ben i Jord. La programeren
være koblet til.
Så, la oss programmere.
Endingene som er gjordt denne gangen:
Tilsvarende
#include <avr/io.h>
DDRB = 0b00000001;
#include <util/delay.h>
PinB1 settes til input med & not.
int main(void)
Da vi trykker, skal vi få 0 volt, og da
{
vi ikke trykker skal det være frem
DDRB |= 1 << PINB0;
volt.
DDRB &= ~(1 << PINB1);
Setter pin B1 til høy (ettersom det er
PORTB |= 1 << PINB1;
dette som skal skje da vi ikke
while (1)
trykker)
{
PORTB ^= 1 << PINB0;
if (bit_is_clear(PINB, 1))
{
_delay_ms(10);
}
else
{
_delay_ms(100);
}
}
}
Hvis knapp er trykket
gjør dette
ellers
gjør dette
Bit_is_clear er en fuksjon som sier. (hvis, bit er ingenting(altså, vi trykker) gjør dette.
Under hva vi gjør; er det enten rask blink hvis vi trykker.
Eller vanlig blink som tidligere hvis vi ikke trykker.
Da du som menneske trykker på en knapp, la oss si en knapp som kun er på da du holder den inne.
Får du ikke trykket hele knappen inn og gitt et klart symbol på at nå er den av, og nå er den på. Slik
som vi egentlig ville sett for oss. I teorien trykker du på, så glipper koblingen av og på noen ganger,
før den endelig har et klart og tydelig på signal. Hvis vi programmerer til at den skal 1 gang, skru seg
på idet du skur på lyset, deretter skru seg av. Ville den med denne hoppingen av signaler aldri få
rukket å skru seg på.
En illustrasjon vil gjøre det lettere å forstå:
Her ser du at ifra du går fra 1, eller
logisk høy. Som i vårt tilfelle ville
representert PÅ. Vil signalene hoppe
litt før de når lav. Dette er ugunsig
og det er her vi kunne trengt å ta en
Button Deboucning.
Button Debouncing kan gjøres på to forskjellige vis. Du kan gjøre det via Hardware eller Software.
La oss først se litt på hva vi ville gjort for software deboucning.
1
2
Samme scenario som i stad men vi legger til en delay på målingen. I stedet for å ha umiddelbar
måling, tar vi en måling i starten. Punkt 1. og en måling i slutten. Punkt 2. Da vil vi kunne se forbi
denne bounce i signaler og vi får en klar og tydelig måling. Software Debouncing er billigere men litt
mer avansert enn å sette inn en kondensator i kretsen.
Kondensator
Her er et bilde av hvordan en kondensator kan se ut:
Tidsinnstilling – Timere
Introdusere hva en timer er og hvordan den fungerer
Enhver mikrokontroller trenger en klokke, enten en utvendig eller innvendig klokke. I amtega32
mikrokontrolleren vår har vi en klokke internt, denne klokken teller. I atmega32 kan den interne
klokken telle med en fart på 1Mhz. Det vil si, 1,000,000 tikk i sekundet. Hver av disse tikkene
representerer en instruksjon. Altså, en mikrokontroller trenger en klokke for å kunne utføre
instruksjoner ved en viss rytme. En timer i en klokke teller samtidig med mikrokontolleren klokke.
Men, en counter kan bare telle opp til enten 256(8-bit) eller 65535(16-bit). Dette er langt ifra en
million instruksjoner som klokken vår tillater. Derfor har vi en ting som heter Prescaling. Prescaling er
en enkel måte for counteren å hoppe over noen tall hver gang klokken tikker. AVR mikrokontrolleren
tillater oss å hoppe over f.eks 8,64,256 eller 1024 tikk om gangen. Hvis vi setter prescaleren til 64 vil
counteren telle en gang for hver 64 tikk i klokken. En prescaler som gjør slik at du kan hoppe over
noen tall vil da i et eksempel si: hopp over 1 million tikk, og tell så en gang – da vil du telle i sekunder.
Dette kan være praktisk da vi for eksempel vil si at en klokke skal telle ned fra 10 sekunder, eller du
skriver en delay funksjon som vist tidligere.
De fleste timere har et register for å kontrollere counterene, disse registrene har noen forskjellige
funksjoner og en av dem er blant annet prescaler. Navnet på et slikt kontroll register er TCCR0 eller
TCCR1 (Timer/counter control register). TCCR0 er 8-bits, TCCR1 er 16 bits.
Hvordan få en timer til å virke?
La oss ta et enkelt eksempel hvor vi skal skru av og på en LED slik som tidligere.
Bruk oppkoblingen fra første del da vi testet at vi fikk en LED til å lyse og følg kodingen her:
Vi bruker den same koden, men gjør noen få endringer;
Vi vil her kunne bruke den interne klokken/timeren i mikrokontrolleren som en vanlig sekundteller.
Og vi kan kontrollere lyset vårt i forhold til å blinke en gang hvert sekund. Kjør make all & program
som vist tidligere. Og du burde nå ha et lys som blinker en gang i sekundet.
Det vi gjør her, er at vi utnytter den interne klokkens hastighet. Vi vet den gir 1MHz instruksjoner, og
vi kan ut i fra det (gjøre som over) altså be den gjøre noe hver gang den har gjort 1 million
instruksjoner.
Avbrudd – Interrupt
Et interupt eller et avbrudd. Er som i navnet; et avbrudd. Dette er en spesiell måte å skrive kode på
og kan også kalles hendelsesorientert kodeskrivning. Det interups går ut på er at hvis du har din main
kode og en uendelig løkke som vi har brukt tidligere. Så vil denne løkken fortsette og fortsette å gå.
Hvis du vil at den f.eks skal blinke da klokken har tellet til 1 milion, som i eksemplet over – så skriver
vi en if setning inni denne uendelige løkka.
Interupts, eller avbrudd er litt annerledes. Her vil vi ha en kode som er utenfor denne uendelige
løkka. La oss si; blink LED. Og inni løkka skriver vi den vanlige if setningen –(hvis counter har tellet til
en milion) gjør noe. I stedet for å skrive inni den uendelige løkken hva vi skal gjøre, gjør vi heller et
avbrudd -> dette vil si vi hopper ut av den uendelige løkka og går til en kode spesifikt skrevet utenfor
koden, for nettopp dette tilfellet. Da denne koden er kjørt, og mikrokontrolleren har jobbet seg
igjennom koden, går den tilbake i den uendelige løkken og fortsetter somvanlig.
Disse avbruddene kan du sette etter forskjellige premisser, en kan hoppe ut ifra den uendelige
løkken for å utføre et visst sett med instruksjoner av forskjellige grunner, la os si som nevnt tidligere;
at klokken har gått en viss lengde, eller telleren har tellet så høyt. Men den kan også fungere under
seriell kommunikasjon -> for eksempel du kan ta et Interupts da mikrokontrolleren oppdager at den
har fått inn informasjon på en av pins. Eller for eksempel at nå er en analog til digital konvertering
fullført.
Selve formålet med avbrudd er at du ikke trenger å gå igjennom like mye kode hver gang du går
igjennom en løkke. La oss si timer eksemplet hvor den skulle telle til en million, da vi har if setningen
og den fullstendige handlingen innenfor den uendelige løkka – vil mikrokontrolleren bruke klokkens
kapasitet på å lese igjennom hele, hver eneste gang, selv om den kun vil få bruk for å gjøre hva som
foregår inni if løkka da den faktisk har tellet til en million. Setter vi selve hendelsen utenfor, vil den
kunne kjøre den uendelige løkka, og kun dra til en spesifikk hendelse da premissene er oppfylt og det
faktisk vil være relevant.
Hvordan få interruptus til fungere.
Kretsen vi her skal bruke ser slik ut:
vi har en kabel fra Pin B0 til en lysdiode med en motstand imellom for å ikke overbelaste den. Så er
andre siden av LED lyset koblet til jord. Det er alt.
Når det kommer til koden
Starter vi først med den helt simple
koden vi alltid har startet med.
Skjelettet.
Vi legger så til et ekstra biliotek
#include <avr/interupt.h>
slik at vi kan bruke interupts i koden vår.
Så aktiverer vi globale interupts. Dete gjør vi ved å skrive
sei();
Øverst under main, en global variabel, eller noe som helst globalt i programmering vil si at det gjelder
for hele koden.
Slik vil det da se ut:
Så viser vi til at vi bruker pin B0, dette gjør vi som vi har lært tidligere ved å skrive
DDRB |=1<<PINB0;
Vi legger også til vår interupt service rutine nederst i koden. Det er her hva som skal gjøres ved et
interupt står forklart. Koden vil da se slik ut:
Vi legger så til vår Timer Control Switches, som lært tidligere. Denne gangen aktiverer vi både CS10
og CS11. Dette vil gi oss en prescaler på 64.
Vi legger også en ener på vår Wayform Generation Mode
Dette skrives GWM12 Eneren representerer at det er 16 bits, og 2 forteller oss at det er mer enn en
WGM
Vi legger også til vår timermaske.
Skrives TIMSK |=1<<OCIE1A;
vi har nå tilgang til vårt OCR register.
Skriver her
OCR1A = 15624;
med samme nummer som vi vil den skal sammenlikne med TCNT1.
OCR1A fungerer her i vårt tilfelle som et sammenlikningsregister.
Koden vil da tilslutt se slik ut:
Det vi har sagt her er at da TCNT vil treffe tallet 15624 vil koden hoppe rett til vår ISR.
Og hva skal skje her da?
her vil vi ha den til å blinke LED lyset som er koblet til Port B0. Vi skriver da
PORTB ^= 1<<PINB0;
Vi gir også navn til vektoren vår.
vi navngir den TIMER1_COMPA_vect
og da er vi ferdig. Siste ISR blokken vår vil se slik ut:
Versegod nå og Make all & program. Du burde nå få akkurat samme scenario som under timere, men
her kan du vite at du har lært å bruke interupts.
LCD
Hva er en LCD. En LCD er akkurat som en LED en output enhet, her for å gi oss mennesker
informasjon. Vi finner den overalt, vi finner den i datamaskinskjermen du kikker på nå, du finner den
på mobilen din. LCD står for «liquid crystal display». Og er bygget opp av flere lag. Et polariserende
filter for å polarisere lys da det kommer inn, klass til å trekke ut kontrasten litt flere filter av
forskjellige former og en reflektiv overflate for å sende lys tilbake til bruker. Starten på 50 tommers
(nå utdaterte) LCD skjermen du har hengene på veggen kom i 1888 da Friedrich Reinitzer oppdaget
liquid crystalline naturen til kolesterol tatt fra gulrøtter.
LCD skjermen v i arbeider med er en svært mye enklere versjon enn den du bruker til å se på tv, men
prinsippet er det samme. Du sender informasjon inn og informasjon i form av digitale signaler blir
omformet og vist til oss mennesker i form av tegn, bilder m.m.
Lett forklart er en LCD en skjerm med forskjellige pins og forskjellige funksjoner hvor du kan vise
forskjellige siffer, tall, figurer etc på skjermen.
LCD skjermen jeg kommer til å bruke er fra Sparkfun Electronics og kan kjøpes her:
https://www.sparkfun.com/products/255
Den har en 16 karakters system med 2 linjer. Det er sort tekst på en grønn skjerm og er 5 volt.
Datasheet kan du finne i Apendix. Den har 16 pins 1 for jord, 1 for strøm, 1 for kontrast justering, 8
data bus lines til å overføre informasjon, en for bakgrunnslys, en for read/write, en for register select
signal og en strøm for BKL.
En LCD skjerm kan gi deg en stor mengde informasjon, en av de største fordelene er at du kan få
alfabetet på den.
-
La oss begynne.
Hvordan få LCD til å vrike?
Her finnes det også mange smarte løsninger for å få LCD skjermen til å virke. Det letteste en kan
gjøre hvis en har et loddeaparat tilgjengelig er å få loddet på små ledere i hver av hullene til LCDen
slik at du lett kan koble den opp til mikrokontrolleren.
Slik vil det da se ut;
Dette gjør fra og tilkobling svært
enkelt og praktisk. Sørg bare for at
du ikke lar det være kontakt mellom
noen av lederne.
Da dette er gjort er det bare å koble det inn i en ledig plass i breadboardet.
Så kommer vi til den tidkrevende delen, oppkoblingen.
Hvis vi kikker på databladet vil vi kanskje få et litt lettere arbeid:
Hva du kan se her er at pin1, er pin
øverst på bildet mitt. Dette er jord.
Nummer til vil da gå til strøm i
breadboardet ditt.
Gjør dette først.
Da du har koblet strøm og jord fra pin 1 og to
som forklart over.
Pin3 representerer kontrast så denne kobler vi
via en motstand eller et potensiometer før vi
kobler det videre inn i jord. Så går vi videre på
koble kablene direkte inn til mikrokontrolleren.
Pin4 vil gå til pin16 på mikrokontrolleren altså
PD2.
PIN5 på LCD vil gå til VCC.
PIN6 på LCD går til pin 19 på mikrokontroller,
altså PD5.
PIN7 på LCD vil gå til pin 1 altså PINB0
PIN7 på LCD vil gå til pin2 altså PINB1
PIN8 på LCD vil gå til pin3 altså PINB2.
PIN9 på LCD vil gå til pin4 altså PINB3.
PIN10 på LCD vil gå til pin5 altså PINB4.
PIN11 på LCD vil gå til pin6 altså PINB5.
PIN12 på LCD vil gå til pin7 altså PINB6.
PIN13 på LCD vil gå til pin8 altså PINB7.
PIN15 på LCD vil gå til VCC:
PIN16 på LCD er ikke i bruk.
Da denne oppkoblingen er unnagjort kan vi begynne på programmeringen.
La meg først forklare hva #define er. #define kan brukes til å gi navn til viktige nummer. Den kan også
brukes til å omdefinere navnet på en ofte brukt variabel. For eksempel vi bruker port B igjennom
hele prosjektet vårt, hvis vi definerer port B med et navn, kan vi endre akkurat dette navnet et sted –
og det vil gjelde for hele prosjektet.
F.eks #Define MRLCDcrib PORTB vil da si at vi hvert sted vi bruker MRLCDcrib, vet vi at dette gjelder
PORTB. Dette er greit hvis vi for eksempel vil bytte fra port B til port A alle steder vi har brukt port B, i
stedet for å gå igjennom hele koden, kan vi da bare endre den globale instillningen for MRLCDcrib til
A, og alle andre steder hvor vi har brukt MRLCDcrib vil bli endret.
En commando er f.eks shift hele teksten høyre, eller venstre. La skriften danse venstre, eller flytt
pekeren til venstre for hvert tegn, rens skjermen osv.
her er liten liste på ofte brukte kommandoer. Det er også HEX
DECIMAL verdi oppgitt.
En karakter er et tegn, f.eks en bokstav, et tall eller liknende.
Under implementerer vi funksjoner for å sende forskjellige tegn og kommandoer.
Åpne Programmers Notepad og la oss begynne:
Vi begynner med skjelettet og så legger vi litt mer enn vanlig.
#include <avr/io.h>
#include <util/delay.h>
#define MrLCDsCrib PORTB
#define DataDir_MrLCDsCrib DDRB
#define MrLCDsControl PORTD
#define DataDir_MrLCDsControl DDRD
#define LightSwitch 5
#define ReadWrite 7
#define BiPolarMood 2
DefinererPORTB som MrLCDsCrib
definerer enable(port5) som Lightswitch
Definerer PortD som MrLCDcontrol
Definerer port 7 som ReadWrite
DefinererPort2 som BiPolarMood
void
void
void
void
void
Check_IF_MrLCD_isBusy(void);
Her informerer vi om: det finnes en void
Peek_A_Boo(void);
som er f.eks. Peek A Boo. Som vi skal
Send_A_Command(unsigned char command);
Send_A_Character(unsigned char character); bruke senere, det er her vi deklarerer dem
Send_A_String(char *string);
Vi definerer type, og gir navn, som f.eks
int main(void)
unsigned char, med navn command.
{
DataDir_MrLCDsControl |= 1<<LightSwitch |
1<<ReadWrite | 1<<BiPolarMood;
_delay_ms(15);
Setter på lyset. Ligthswtich = 1.
R/W = 1. altså alltid skrive
BiPolarMood = 1. alltid på
Send_A_Command(0x01); //Clear Screen
_delay_ms(2);
Her bruker vi send command
Send_A_Command(0x38);
_delay_us(50);
fuknsjonen. Vi sender en kommando
Send_A_Command(0b00001110);
_delay_us(50);
i HEX her med for eks CLEARSCREEN.
Send_A_Character(0x4E); //N
Under sender vi karakterer i HEX.
Send_A_Character(0x65); //e
Send_A_Character(0x77); //w
Slik som 0x4E som betyr N
Send_A_String("Patrick");
eller ox77 som betyr w
while(1)
{ }
}
Setter datadir til input.
void Check_IF_MrLCD_isBusy()
setter i read mode. (R/W = 1)
{
DataDir_MrLCDsCrib = 0;
BipolarMood = 0 = command modus. .
MrLCDsControl |= 1<<ReadWrite;
MrLCDsControl &= ~1<<BiPolarMood; while løkke sjekker om LCD er klar med å kjøre
PeekABoo intill den er klar. Den er ikke klar så lenge
while (MrLCDsCrib >= 0x80)
{
Pin7 = 1.
Peek_A_Boo();
}
DataDir_MrLCDsCrib = 0xFF;
}
void Peek_A_Boo()
{
MrLCDsControl |= 1<<LightSwitch;
asm volatile ("nop");
asm volatile ("nop");
MrLCDsControl &= ~1<<LightSwitch;
}
Setter
datadir for
til output
igjen.
Funksjon
å skru av
og på lys :
Skru på lightswitch
Setter
da
assembler
code (stopper kompiler)
Skru av Lightswtich
void Send_A_Command(unsigned char command)
{
Check_IF_MrLCD_isBusy();
MrLCDsCrib = command;
MrLCDsControl &= ~ ((1<<ReadWrite)|(1<<BiPolarMood));
Peek_A_Boo();
MrLCDsCrib = 0;
}
void Send_A_Character(unsigned char character)
{
Check_IF_MrLCD_isBusy();
MrLCDsCrib = character;
MrLCDsControl &= ~ (1<<ReadWrite);
MrLCDsControl |= 1<<BiPolarMood;
Peek_A_Boo();
MrLCDsCrib = 0;
}
Funksjon for å sende kommando:
Med LCDControl setter R/W off slik
den er i Write mode.
MrlcdsCrib 0 så vi ikke gir noe volt
der.
Funksjon for å sende tegn:
Her er akkurat samme, bare BiPolarMood
er 1, slik at den faktisk vil motta.
Flasher info med PeekABoo.
Så setter volt til null.
Da vil du kunne prøve å kjøre programmet med make all & program. Dette skal kunne fungere og du
vil få opp skriften New.
Det er ikke så spennende så du kan kikke på Hex kode og skrive inn din egen skrift.
Eller du kan lese på noen av kommandoene og prøve å sende noen kommandoer. (se appendix)
Om ønskelig har jeg også en ferdiglaget kode du kan kopiere og se hvordan den vil se ut på LCD
skjermen din. Denne ligger også i Appendix.
Analog til Digital
Konvertering (ADC)
Analog til Digital Konvertering er en form for å omgjøre en informasjons sendervei. Med dette mener
jeg at du kan sende noe informasjon med et signal- tolke det og omgjøre det til et annet signal. La oss
si; jeg sitter og gir deg morse-signaler, du hører morsesignalene og forteller vennene dine hva som
ble sagt i morsen ved hjelp av svensk, eller finsk for den saks skyld. Hovedpoenget med denne
analogien er at du plukker opp et signal i en form og gir den videre i en annen form. Slik er det også
med Analog til Digital konvertering. ADC, som står for «analog to digital converting» er begrepet vi
skal omhandle. Vi får da analoge signal inn på mikrokontrolleren vår, i form av volt. Spenning eller
ikke spenning. ADC omhandler å konvertere informasjonen en sender da en sender et forskjellig
spekter av forskjellige spenningen, la oss si. 0.5 volt av totalt 5 volt, for å så sende 1 volt av totalt 5
volt. Disse to spenningene har hver sin Digitale ekvivalent. Når vi bruker ADC velger vi mellom 8 og 10
bits, siden bits er digitale signaler. Inn i mikrokontrolleren sender du inn en verdi mellom 0 og 5 V og
mikrokontrolleren gjør ved hjelp av ADC om dette til en digital verdi. Eks i 8 bits, da har vi et spekter
fra 0-255 bits og disse 0-5V tilsvarer dette. Sender vi inn 0V blir dette den binære verdien 00000000,
og sender vi inn 5V som er maks vil vi med 8 bits få den binære verdien 11111111. Hvis vi da bruker
10 bits, vil vi kunne få informasjon opp til 1023 altså null volt kan konverteres til 0000000000 (10
nuller) og 5 volt kan konverteres til 1111111111(10enere) slik vil vi kunne få mye større nøyaktighet.
For å gi deg en følelse på hvordan ADC vil kunne fungere vil vi bruke kretsen fra forrige oppgave. LCD
skjermen. Vi kobler opp et potensiometer, som vi allerede vet kan variere spenningen, og vi bruker
LCD skjermen til å vise frem denne spenningen binært. Vi kobler først opp potensiometeret, den har
tre pins og de to som står sammen kobles til jord og spenning på breadboardet. Den ene pinnen som
står alene, kobles til PINA0 på mikrokontrolleren. Grunnen til at vi denne gangen bruker PINA
gruppen, noe vi ikke har gjort tidligere. Er fordi det er denne som har den alternative funksjonen
ADC. Det neste vi gjør er å koble til strøm og jord på mikrokontrollerens ADC port, (hvis du går opp i
rapporten og leser på pin oversikt på atmega32) vil du se at dette er pin nummer 11 og 10 ovenifra
på høyre side. Mellom mikrokontrolleren og VCC/GND setter vi en kondensator for å dempe
eventuell støy for å gjøre målingene så korrekt som mulig.
her ser du et bilde fra Newbiehack (hvor han har koblet til Programmer på B, og strøm +
potensiometer på PORTA gruppen)
La koblingen stå fra LCD, men legg til strøm og Jord som nevnt, med en kondensator imellom og fra
PINA0 til potensiometeret
Vi lager et nytt program denne gangen og vi bruker først 8 bits.
Programmet vil etter litt skrivning bli som dette:
Vi starter med skjelettet, legger til MrLCD.h som er en
headerfil vi laget ut ifra variablene og definisjonene vi satt
under LCD prosjektet. Vi legger også til interruptus
biblioteket sammen med standard bibliotek for å få litt
flere ord til disposisjon.
Headerfilen til mrLCD.h ser såleis ut:
Som vi har sett på så er det her brukt et interupt og det er under ISR (Interupt service rutine) det
skjer. Vi lager en string av typen char. Som inneholder tegn, [] representerer antall plasser, så i
adcResult er det da fire plasser. Hver av disse plassene bruker en av LCD skjermens plasser. Tallet vi
får er maksimalt 255(ettersom det er 8 bits) og vi bruker bare 4 plasser, for å være sikker.
Itoa(ADCH, acdResult) er kode for å konvertere resultatet fra ADC til en streng. Itoa er en standard
funksjonsnavn definert i stdlib. Itoa funksjonen bruker vi med tre parametere, den første er verdien
av resultatet, den andre er strengen vi skal sette verdien inn i. og en tredje definerer her at vi skal
bruke titallsystemet.
GotoMrLcds location er en funksjon som ligger i MrLCD headerfila, denne viser til at det første
sifferet skal stå på rad 1 og kolonne 1 på skjermen. Den neste kommandoen er for å sende tallene til
skjermen, denne har vi allerede sett under LCD projektet vårt.
ADCSRA |=1<<ADSC; betyr at vi skal repetere konverteringen kontinuerlig slik at vi hele tiden kan se
den kontinuerlige oppdateringen av verdier på skjermen.
Under main-funkjsonen har vi flere kommandoer, først initierer vi kontakt med LCD skjermen og de
fem neste kodelinjene setter ADC-funksjonene på. Disse funksjonene skal styre hvilken pin ADC
signalene skal gå til, aktivering av ADC interupts, og så si ifra om det er 8 eller 10 bits vi bruker. Vi
aktiverer også en prescaler som vi har lært tidligere.
Vi har valgt å bruke 8 bits ved å sette ADLAR til 1, dersom vi ønsket å bruke 10 bits ville vi satt denne
til 0. Vi har også initiert sei() igjen som tidligere vist er en global funksjon for interupts.
Hvordan bruke 10 bits og ikke 8?
Ettersom med ADLAR = 1. får vi en venstrejustering på 2, og vi mister 2 siffer. ADCH består da av de 8
siste bits av de totale 10 bits i ADC. Når ADLAR er satt til 0 har vi høydejustering der ADCH består av
bit 9 og 8 mens ADCL består av bit 7-0.
For å få 10 bits må vi lage en 16 bits variabel som skal inneholde alle ti bits fra ADCH og ADCL, denne
variabelen må være av typen int16_t som kan hete f.eks TenBitValue.
For å få denne til å inneholde alle bits fra ADCH og ADCL må vi bruke bitvise operatorer, disse brukes
for å flytte bits i retning høyre eller venstre. For eksemplet med ADLAR =0;
Vil vi flytte alle ADCH bits 8 plasser til venstre ved å bruke ADCH <<8.
Deretter setter vi denne variabelen i TenBitResult ved TenBitResult |= ADCH << 8;
For å sette inn ADCL bits på riktig plass i variabelen skriver vi TenBitResult |=ADCH << 8 | ADCL. Vi
har nå klart å lage en variabel som kan bruke 10 bits ADC. Koden er tilnærmet lik 8 bits koden og vil
se slik ut:
Seriekommunikasjon – UART
UART eller Universal Asynchronous Receiver/Transmitter er en nøkkelkomponent for den serielle
kommunikasjonen i et datasystem. UART tar bytes og bytes av data og sender hver individuelle bit
sekvensielt. I mottakende ende, er det ennå en UART som setter sammen disse bits den har mottatt
sammen til fulle bytes igjen. Seriekommunikasjon er vanligvis brukt i modemer og for ikke
vettverksbasert kommunikasjon mellom datamaskiner, terminaler og andre enheter.
For å starte på toppen. Seriekommunikasjon er rett å slett en måte å få to eller flere enheter til å
snakke sammen, i dette tilfellet to mikrokontrollere. AtMega32 har to pins, nr. 14 og 15 telt ovenfra
på venstre side, som står for mottaking og overføring av data. Disse brukes til å koble
mikrokontrollerene sammen for å få overført data seg i mellom.
Over til UART og USART. Navnene deres
forklarer mye av hvordan de fungerer. UART
(Universal Asyncronous Reciever Transmitter) er
en asynkron seriekommunikasjon. Dette betyr at
de to mikrokontrollerene ikke kjører på samme
klokkefrekvens og det kan dermed være en delay
eller at ting ikke skjer samtidig. USART (Universal
Syncronous Asyncronous Reciever Transmitter)
vil sende over en klokkefrekvens fra senderen til
mottakeren slik at de kan begge bruke den
samme frekvensen, dette kan ofte øke
hastigheten slik at ting skjer fortere. Når man
kjører synkront er man altså nødt til å sende
over en klokkefrekvens samt data, mens ved
asynkron seriekommunikasjon trenger man ikke
klokke, bare data. Dette betyr også at ved
asynkron seriekommunikasjon trenger ikke data
å sendes over kontinuerlig, men det trenger man ved synkron seriekommunikasjon. En annen ting
som er viktig å få med seg når det gjelder UART og USART er «baud rate». Baud rate er den klokken
som dytter data ut på linken. Hvis man bruker UART må denne baud raten være kjent og samtykket
av både sender og mottaker, mens ved USART vil denne baud raten komme fra klokken som begge
mikrokontrollerene bruker og dermed være lik uansett.
Når du skal programmere to mikrokontrollere til å snakke sammen er du også nødt til å endre
makefilen til programmet ditt. Programmet til mikrokontrolleren som sender informasjon er nødt til
å ha en makefile med MCU-type «atmega324p». Dette gjøres ved å åpne makefilen i notepad for
redigering og endre navnet der det står «#MCU name». Makefilen vil da se slik ut:
I programmet til den mottagende mikrokontrolleren må du endre navnet til «atmega644».
Disse endringene kan gjøres manuelt idet du skal programmere mikrokontrolleren, eller du kan lagre
makefilen med endringene.
Hvordan få UART til å virke.
For å få seriekommunikasjon til å virke trenger vi en mottakende og en sendene part. Her bruker vi to
mikrokontrollere for å kunne kommunisere imellom dem.
Jeg samarbeider her med Håkon Collet og vi skal prøve å kommunisere mellom hverandres
mikrokontroller.
Først plasserer vi begge mikrokontrollerene på et breadboard.
Bruker min mikrokontroller til å sende signalet og si ifra til Collet’s mikrokontroller.
Vi kobler på en knapp og vi kobler på en lysdiode.
Lysdioden vil vi bruke til å diagnosere mikrokontrolleren, slik at da vi trykker knappen så skrur lyset
seg på vet vi at vi har satt i gang en overføring.
VI vil også ha en LED på pinB0 på den mottakende mikrokontrolleren, slik at vi kan bestemme om vi
faktisk får informasjonen korrekt.
Målet vårt er at LED lyset på den første mikrokontrolleren skal skru seg av og på da vi trykker på
knappen, slik at vi vet at knappen fungerer. Men samtidig, så vil vi også at LED lyset på den andre
mikrokontrolleren skal skru seg på og av likt med den første mikrokontrollerens LED. Dette er fordi vi
sender kode over, og slik kan vi se at kommunikasjonen mellom dem fungerer.
Blinker LED lyset på den mottakende mikrokontrolleren likt med LED lyset på den sendene
mikrokontrolleren etter hvert som vi klikker, vet vi at vi har gjort noe riktig.
Vi kobler en ledning fra TX pin på den sendende mikrokontrolleren inn i RX pin på mottakende
mikrokontroller. TX pin er pin nummer femten og T står for Transmitting. RX pin er på pin 14 og R står
for Reciving. Vi bruker bare en ledning i dette tilfellet fordi den første mikrokontrolleren kun skal
fungere som sendende, altså den trenger bare å bruke sin Transmitting Pin. Og den andre
mikrokontrolleren skal kun fungere som mottakende dvs. den trenger bare sin Reciving pin.
Hadde vi skulle sendt informasjon begge veier og ikke bare fra den første til den andre. Så ville vi
trengt to kabler, her fra TX på den første og RX på den andre, samt fra TX på den andre til RX på den
første.
Vi kobler naturligvis strøm og jord til på den andre mikrokontrolleren. Og ved den sendende
mikrokontrolleren, som vi skal programmere til å sende kode til den mottakende, kobler vi til
programmerer som tidligere, slik at vi faktisk kan få overført noen instruksjoner til den.
Koblingen vil se slik ut:
Vi kan nå bevege oss videre til programmeringen;
Vi starter opp programmers notepad og skriver en skjelettkode med en uendelig løkke i.
Vi starter med å skrive programmet til den sendende mikrokontrolleren.
Det vi trenger å programmere er LED, knapp og kommunikasjons spesifikasjoner.
Vi har en uendelig løkke som vist tidligere, og inni denne uendelige løkka vil det bli instruert om;
Sjekk hvilken status knappen har, er den trykket eller ikke + button debouncing.
Hvis knappen er trykket, skru på LED og send informasjonen til den mottakende mikrokontrolleren.
Koden for UART kommer etter denne lille koden, du som programmerer – burde jo allerede syntes
dette er morsomt.
#include
#include
#include
#include
<wilde>
"shampoo.h"
"shower.h"
"towel.h"
using namespace non_std;
int main(int argc, char* argv[]) {
User u;
u.name = argv;
Shower s;
Shampoo o;
Towel t;
s.adjust_taps(u.temp_preference);
s.adjust_taps_again_after_burning_winkle(
SYSTEM.find_what_user_really_wants(u.temp_preference));
s << u;
for(int i = 0; i < 2; ++i) {
s.wet_hair();
s.apply_shampoo(o);
s.lather(o);
s.rinse();
}
s.complete_shower();
s.taps = off;
u.exit_shower();
u.dry(t);
return EXIT_WASHED;
}
Sluttproduktet vårt for UART vil se slik ut:
Her setter vi DDRB |=1<<PINB1; som tidligere. Vi
setter pin B1 til output. Led trenger strøm,
derfor PINB1 output.
Vi setter PINB0 til input. Det er her knappen skal
være.
En knapp gir signaler, ikke får.
Setter PINB1 til 0, altså ledlyset til å være av fra
start.
Vi kobler knapen fra Jord til mikrokontrolleren
og vi setter da PINB0 til høy. Da knappen ikke er
trykket, vil da pinB0 være høy.
Så button debouncing start.
Her deklarerer vi en integrer Pressed og setter
denne til 0, her vet vi om knappen er trykket
eller ikke.
Deklarerer Pressed_Confidence_level = 0;
Deklarerer Released_Confidence_level = 0;
Oppretter UBRR_value til 25;
Setter baud rate med UBRRH og UBRRL
UCSRB =(1<<RXEN) | (1<<TXEN);
Enabler TX og RX pin.
Vil sende 8 bit. Så bruker UCSRO = (1<<USBS) |
(3 <<UCSZ)
Vi legger en if løkke iden uendelige while løkka.
Denne if-setningen sjekker om knappen er
trykket.
er den trykket (Pin B0 er lav);
Sett Pressed-confidence_level opp 1.
Sett Released_confidence_level til 0;
Ny if(hvis løkka som sjekker om PinB0 er lav, har
satt Pressed_confidence_level, til mer enn
hundre)
NY IF(sjekk at vi har sluppet knappen igjen)
Sett Pressed = 1;
PORTB ^=(1<<PINB1); skru LED av om på, skru
på om av.
først, vente til senderen er klar.
dette gjør vi ved while (! (UCSRA & (1<<UDRE)));
Så mens UDRE er null, da er den opptattt. Vent
da.
Da UDRE er 1, da kan vi sende.
Vi setter dataen inn i UDR registeret.
UDR = 0b111000; (den mottakende siden må
motta dette tallet) i mottakende side sjekker vi
etter dette nummeret, hvis det er der, gjør
funkjsonen den har blitt gitt.
else (hvis ikke)(da må den ikke være trykket)
(Hvis pin B0 da er høy)
sett Released_confidence_level opp 1. )
Sett også Pressed_confidence_level = 0;
(ettersom den ikke blir trykket).
NY IF(hvis løkka hundre ganger har sagt at
knappen ikke er trykket, da må den ikke være
trykket)
Sett Pressed til 0;
Sett released til 0;
Du kan nå teste om LED lyset på den sendende siden blinker da du klikker knappen, gjør den det. Alt
ok.
La oss bevege oss til den mottakende mikrokontrollerens kode.
Deklarere LED og kommunikasjon.
Setter pinBO til output, siden denne skal til
LED.
UART kommunikasjonen har vi deklarert i
forrige og vi vil at de de samme
parameterne, derfor kopierer vi UART
feltet.
Deklarerer recivedata som vi bruker
senere.
Uendelig løkke, I denne ser vi om recive er
klar for å motta data. Altså hvis Recive
Buffer er fullt, dette ser vi ved hjelp av en
indikator som heter RXC flag.
Her bruker vi samme begrep som i TX for å
se om denne er klar. While(mens)(RXC
flagget er 0, ikke send)
Da RXC er 1, går vi videre for å motta data:
Deklarerer reciveData = UDR.
her bruker vi UDR til å motta data, akkurat
som vi brukte UDR til sende data i forrige.
Så skjekker vi om Recivedata som vi hentet
fra UDR er det samme som vi opprinnelig
skulle ha.
Er den det;
Skru på LED hvis på, skru av hvis av.
Konklusjon
Da har vi startet med litt info om hva en mikrokontroller er. Vi har hatt litt om hvordan du skal bruke
denne sammen med en datamaskin ved hjelp av en debugger/programmer. Vi har gått igjennom
bruken av en mikrokontroller og en programmer, vi har gått igjennom installering og opprettelse av
våre første projektor.
Jeg har gått igjennom forskjellige komponenter som Motstander, LED, Potensiometer, kondensator
osv. Du har fått tildelt de forskjellige verktøyene du skal bruke og du har lært å bruke dem.
Jeg har også gått i detalj på forskjellige funksjoner som Interruptus, registrere og
seriekommunikasjon.
Oppbygningen har vært gradvis enkelt og generelt til mer og mer spesifikt hvor du gradvis har blitt
tildelt nye verktøy.
En mikrokontroller kan som innledningsvis brukes til så mangt og nå som du har lært du
grunnleggende prinsippene på hvordan en mikrokontroller liker å bli behandlet, hva du må fortelle
den slik at den skjønner hva den skal gjøre. Hvordan du bruker tilbehøret, andre komponenter og du
har også lært hvordan tankegangen bak programmering er.
Da en først har programmeringen og tankegangen bak den, da du har komponentene og funksjonene
i hånd. Da du forstår hvordan en mikrokontroller tenker, og hvordan en datamaskin tenker – det er
da du virkelig kan begynne å jobbe videre. Forhåpentligvis vil du ila dette prosjektet ha dannet en
grundigere forståelse og en vilje til å kunne prøve deg på egenhånd. Lurer du på noe, er det så klart
bare å bla opp i dette lille databladet som har blitt laget her.
Appendix A
Kommandoer for LCD.
Kode til morro på LCD.
DEL1.
DEL2.
<avr/io.h>
#include <util/delay.h>
MrLCDsCrib PORTB
#define DataDir_MrLCDsCrib DDRB
#define MrLCDsControl PORTD
#define DataDir_MrLCDsControl DDRD
#define LightSwitch 5
#define ReadWrite 7
#define BiPolarMood 2
void Check_IF_MrLCD_isBusy(void);
void Peek_A_Boo(void);
void Send_A_Command(unsigned char
command);
void Send_A_Character(unsigned char
character);
void Send_A_String(char *string);
int main(void)
{
DataDir_MrLCDsControl |= 1<<LightSwitch |
1<<ReadWrite | 1<<BiPolarMood;
_delay_ms(15);
Send_A_Command(0x01); //Clear Screen
0x01 = 00000001
_delay_ms(2);
Send_A_Command(0x38);
_delay_us(50);
Send_A_Command(0b00001110);
_delay_us(50);
Send_A_Character(0x49); //N
_delay_ms(50);
Send_A_Character(0x20); //e
_delay_ms(50);
Send_A_Character(0x6C); //w
_delay_ms(50);
Send_A_Character(0x6F); //b
_delay_ms(50);
Send_A_Character(0x76); //i
_delay_ms(50);
Send_A_Character(0x65); //e
_delay_ms(50);
Send_A_Character(0x20); //H
_delay_ms(50);
Send_A_Character(0x63); //a
_delay_ms(50);
Send_A_Character(0x6F); //c
_delay_ms(50);
Send_A_Character(0x63); //k
_delay_ms(50);
Send_A_Character(0x61); //.
_delay_ms(50);
Send_A_Character(0x69); //c
_delay_ms(50);
Send_A_Character(0x6E); //o
_delay_ms(50);
Send_A_Character(0x65); //m
_delay_ms(50);
_delay_ms(50);
Send_A_Command(0x01);
_delay_ms(50);
Send_A_Character(0x42); //N
_delay_ms(50);
Send_A_Character(0x69); //e
_delay_ms(50);
Send_A_Character(0x74); //w
_delay_ms(50);
Send_A_Character(0x63); //b
_delay_ms(50);
Send_A_Character(0x68); //i
_delay_ms(50);
Send_A_Character(0x65); //e
_delay_ms(50);
Send_A_Character(0x73); //H
_delay_ms(50);
Send_A_Character(0x20); //a
_delay_ms(50);
Send_A_Character(0x6c); //c
_delay_ms(50);
Send_A_Character(0x6f); //k
_delay_ms(50);
Send_A_Character(0x76); //.
_delay_ms(50); Send_A_Character(0x65); //c
_delay_ms(50);
Send_A_Character(0x20); //o
_delay_ms(50); Send_A_Character(0x6d); //m
_delay_ms(50); Send_A_Character(0x65); //m
Send_A_Character(0x20); Send_A_Character(0x20);
Send_A_Character(0x20); Send_A_Character(0x20);
Send_A_Character(0x20); Send_A_Character(0x20);
Send_A_Character(0x20);
Send_A_Character(0x63); Send_A_Character(0x75);
Send_A_Character(0x7a); Send_A_Character(0x20);
Send_A_Character(0x49); Send_A_Character(0x20);
_delay_ms(50); Send_A_Character(0x61);
Send_A_Character(0x6d);
_delay_ms(50);
Send_A_Character(0x20); Send_A_Character(0x66);
Send_A_Character(0x61); Send_A_Character(0x62);
Send_A_Character(0x75); Send_A_Character(0x6c);
Send_A_Character(0x6f); Send_A_Character(0x75);
Send_A_Character(0x73); Send_A_Character(0x20);
Send_A_Character(0x20); Send_A_Character(0x20);
while (1)
{Send_A_Command(0x18);
_delay_ms(30);
} while(1)
{}
} void Check_IF_MrLCD_isBusy()
{
DataDir_MrLCDsCrib = 0;
MrLCDsControl |= 1<<ReadWrite;
MrLCDsControl &= ~1<<BiPolarMood;
while (MrLCDsCrib >= 0x80)
{
Peek_A_Boo();
}
DataDir_MrLCDsCrib = 0xFF; //0xFF means
0b11111111
}
void Peek_A_Boo()
{
MrLCDsControl |= 1<<LightSwitch;
asm volatile ("nop");
asm volatile ("nop");
MrLCDsControl &= ~1<<LightSwitch;
}
void Send_A_Command(unsigned char command)
{
Check_IF_MrLCD_isBusy();
MrLCDsCrib = command;
MrLCDsControl &= ~
((1<<ReadWrite)|(1<<BiPolarMood));
Peek_A_Boo();
MrLCDsCrib = 0;
}
void Send_A_Character(unsigned char character)
{
Check_IF_MrLCD_isBusy();
MrLCDsCrib = character;
MrLCDsControl &= ~ (1<<ReadWrite);
MrLCDsControl |= 1<<BiPolarMood;
Peek_A_Boo();
MrLCDsCrib = 0;
}
KILDER

https://newbiehack.com/MicrocontrollerIntroductionABeginnersGuidetotheAt
melAVRAtmega32.aspx

https://newbiehack.com/MicrocontrollerProgramTransferPart1ABeginnersGuid
etotheAtmelAVRAtmega32.aspx

https://newbiehack.com/MicrocontrollerProgramTransferPart2Drivers.aspx

https://newbiehack.com/MicrocontrollerProgramTransferPart2Drivers.aspx

http://en.wikipedia.org/wiki/Atmel_AVR

http://en.wikipedia.org/wiki/Harvard_architecture

https://www.google.no/

http://www.carlitoscontraptions.com/2007/03/switch-debouncer/

https://newbiehack.com/MCUTestandCircuit.aspx

https://newbiehack.com/MicrocontrollerWritingthefirstprogramandtransfer.as
px

https://newbiehack.com/MicrocontrollerLEDblink.aspx

https://newbiehack.com/MicrocontrollerAddingabutton.aspx

https://newbiehack.com/UnderstandingButtonDebouncing.aspx

https://newbiehack.com/TimersandCountersDefaultandBasicUsage.aspx

https://newbiehack.com/IntroductiontoInterrupts.aspx

https://newbiehack.com/MicrocontrollersABeginnersGuideIntroductionandInte
rfacinganLCD.aspx

https://newbiehack.com/MicrocontrollersABeginnersGuideOurFirstLCDProgra
m.aspx

https://newbiehack.com/MicrocontrollersIntroductiontoADCAnalogtoDigitalC
onversion.aspx

https://newbiehack.com/MicrocontrollersAVRAtmega32FirstADCProgram.aspx

https://newbiehack.com/MicrocontrollersADC10Bits.aspx

https://newbiehack.com/USARTDetailed.aspx

https://newbiehack.com/UART-OneWay-ChipToChip.aspx

http://www.engineersgarage.com/contribution/expert/avr-io-ports

http://playwithrobots.com/robotics-pool/avr/basic-input-output