Innlevering Rapport
Transcription
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