Sunteți pe pagina 1din 22

Tutorial

Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Cuprins
Partea 1 - Hello world! ................................................................................................................. 3 Introducere ................................................................................................................................... 3 De ce ai nevoie? ........................................................................................................................... 4 Programarea uC-ului .................................................................................................................... 5 Cum scriu cod pentru uC? ............................................................................................................ 8 Cum transfer programul n uC? .................................................................................................... 9 Leduri clipitoare...................................................................................................................... 10 Tema 1 ........................................................................................................................................ 11 Partea 2 Push the button .............................................................................................................. 12 De ce ai nevoie? ......................................................................................................................... 12 Cum folosesc butoanele n cod? ................................................................................................. 13 Exemple...................................................................................................................................... 13 Tema 2 ........................................................................................................................................ 14 Partea 3 The clock is ticking ....................................................................................................... 15 Exemple...................................................................................................................................... 16 Partea 4 Fade to black ................................................................................................................. 18 Cum se folosete? ....................................................................................................................... 18 Exemple...................................................................................................................................... 18

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Partea 1 - Hello world!


Introducere
n aceast prim parte a tutorialului vei face cunotin cu lumea microcontrolerelor folosind un Atmel ATMega8 i nite leduri. Cu toate ca ceea ce ine de microcontrollere este explicat la nivel de absolut ncepator sunt necesare cunotine cel puin medii de programare n C. n mare parte totul va fi explicat n limba romn dar sunt necesare cunotine de limba englez pentru a nelege anumite lucruri. Ce este ATMega8? Este un microcontroller cu 8KB memorie Flash (e suficient pentru un program destul de complex), 1KB memorie RAM(acolo sunt allocate variabilele folosite in program), 512B EEPROM (aici poi stoca date; spaiul e cam mic) i muli pini pentru intrri / ieiri. Cam aa arat:

La acest microcontroller vei conecta cteva leduri cu care ne vom juca mai trziu. n cazul n care ai uitat cum arata un led i cum se conecteaz arunca o privire pe imaginea de mai jos:

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

De ce ai nevoie?
Ca s te poi apuca de programarea propriu-zis ai nevoie nti de un circuit care s poat ndeplini funciile implementate n program (program la care m voi referi n continuare ca soft sau firmware - FW). Pentru realizarea circuitului ai nevoie de urmtoarele: Letcon, fludor, sacz (colofoniu) pentru lipirea componentelor (dac foloseti breadboard nu sunt necesare). n cazul n care nu ai mai lipit pn acum componente uit-te la filmuleul din link-ul urmator: http://www.youtube.com/watch?v=AOdnGUMi7lQ Cablaj de test sau breadboard 8 leduri 8 rezistene (100ohm sunt ok) 7805 regulator de tensiune pentru a putea alimenta circuitul de la cam orice alimentator gsit prin cas cu tensiune DC mai mare de 7V. ATMega8 microcontrollerul folosit n acest tutorial Fire de legatur USBasp programatorul folosit n acest tutorial. Poi folosi orice programator cu programele adecvate. Pe lng resursele hardware mai ai nevoie i de nite programe cu care s scrii / compilezi codul i cu care s transferi softul rezultat n microcontroller (cuvntul e destul de lung aa c n continuare voi folosi notaia uC). Programele necesare sunt urmatoarele: AVR Studio 4.18 mediul de dezvoltare a codului. Conine i un simulator foarte util. (http://en.stkshop.com/download--download_id-65.html) AVR Studio SP3 se instaleaz mpreun cu AVR Studio 4.18. l gseti aici: http://www.atmel.com/dyn/resources/prod_documents/AVRStudio4.18 SP3.exe WinAVR compilatorul de C care se folosete mpreun cu AVR Studio 4 (http://sourceforge.net/projects/winavr/files/WinAVR/20100110/WinA VR-20100110-install.exe/download) Khazama Programmer programul cu care se transfer softul n uC (http://khazama.com/project/programmer/) Circuitul pe care l vei folosi n aceast prim parte a tutorialului este cel din imaginea de mai jos. Va trebui ca folosind uneltele descrise mai sus s conectezi componentele ntre ele ca n schema. Recomandat este ca toate ledurile sa fie montate ntr-un singur rnd pentru a nelege mai bine exemplele de cod prezentate. Lng leduri se vor monta (vertical - pentru a face economie de spaiu pe plcu; orizontal n cazul n care spaiul nu e o problem) rezistenele. Conexiunile pn la uC se vor face folosind fire de legtur. Poziia conectorului pentru programare nu este critic dar ncearc s aranjezi componentele n aa fel ncat s ocupi ct mai puin spaiu. Pe msura ce vei parcurge tutorialul plcua se va umple cu componente!

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Programarea uC-ului
Pentru a nelege ceea ce urmeaz este necesar s citeti din datasheet-ul uC-ului (http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf) urmtoarele: Pag. 2 Pin configurations Pag. 5 Port B Pag. 51 I/O Ports pn la Table 20 (Pag. 53) Pag. 55 pn la Digital Input Enable and Sleep Modes AVR Studio 4 Dupa ce ai citit ce este indicat mai sus te poi apuca de programarea propriu-zis. AVR Studio 4 este programul n care vei dezvolta, compila i simula codul. Pentru crearea unui proiect nou deschide AVR Studio 4. n fereastra care i apare selecteaz New Project apoi AVR GCC. 5

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

D un nume proiectului i selecteaz unde vrei sa fie salvat apoi apas Next.

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Selecteaz AVR Simulator iar n dreapta ATMega8 apoi apas Finish.

n fereastra care i apare vei scrie codul.

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Cum scriu cod pentru uC?


Poate prea complicat la nceput ns este n mare acelai C pe care poate c l-ai facut la informatic n liceu. Ca i n liceu codul ncepe cu headerele necesare. Acum vei folosi doar #include <avr/io.h> pentru accesarea pinilor. Urmeaz venicul void main() n care apare codul propriuzis. Pn s ajungi s scrii cod trebuie s tii cteva noiuni mai puin folosite n programarea PC-ului: Familia de uC AVR lucreaza pe 8bii. Asta nseamn ca toi registri au lungime de 8 biti putnd stoca o valoare ntre 0 255 0 x00 0 xFF 0b00000000 0b11111111 . 1 logic = VCC (n cazul de fa 5V); 0 logic = GND (0V) (1<<X) nseamn c reprezentarea lui 1 n baza doi (0b00000001) o deplasez n stnga cu X poziii ( 1 X 7 ). Pentru X=2 rezultatul este 0b00000100. Toat operaia are ca rezultat setarea bitului X ca 1. ~(1<<X) nseamn c la toat operaia descris cu un pas mai sus se aplic complementul lui 1. Altfel spus: ce este 1 devine 0 si ce e 0 devine 1. Exemplu: ~(1<<3)=~(0b00001000)=0b1111011. Toat operaia are ca efect setarea bitului X ca 0 iar a celorlali ca 1. A|=B; - nseamn A=A|B, adic A ia valoarea rezultat din aplicarea operatiei logice SAU ntre A i B. La fel e pentru A&=B; nainte de a ncepe s scrii codul trebuie s te asiguri c proiectul are setrile corecte. Apas butonul pentru a deschide fereastra de configurare. Pentru tutorialul acesta AVR Studio este configurat ca n imaginea de mai jos:

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR Acum poi ncepe s scrii primul tu cod pentru uC. Exemplul urmator demonstreaz cum poi aprinde dou din cele opt leduri conectate pe PORTB, respectiv ledul 0 i 7. Poi alege orice led i oricte leduri.
#include <avr/io.h> void main() { DDRB|=(1<<DDB0)|(1<<DDB7); PORTB|=(1<<PB0)|(1<<PB7); while(1); } //header necesar pt a putea accesa pinii uC-ului

//seteaz pinul 0 i 7 ca ieire //seteaz pinul 0 i 7 ca 1 logic //bucla infinit

Cum transfer programul n uC?


Dup ce ai terminat de scris codul va trebui sa-l compilezi apsnd tasta F7. Dac totul a decurs bine ar trebui s vezi ceva asemntor cu imaginea de mai jos:

Deschide programul Khazama Programmer i selecteaz Load FLASH File (marcat cu rou).

n fereastra care i apare mergi la locaia unde ai salvat proiectul, folderul default. Acolo gseti fiierul .hex rezultat n urma compilrii codului. Selecteaz fiierul, apoi Open. Asigur-te c programatorul e conectat att la calculator ct i la montaj iar montajul este alimentat. Selecteaz Command ->Read Chip Signature. Dac rezultatul este 0x1E9307 poi trece la programarea propriu-zis a uC-ului apasnd butonul Write FLASH to Chip marcat cu albastru

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR n imaginea de mai sus. Presupunnd c scrierea s-a fcut cu success acum ar trebui ca cele dou leduri despre care am vorbit mai sus s fie aprinse.

Leduri clipitoare
Hai acum s ncercm s facem ledurile s clipeasc. Deoarece uC-ul funcionez la frecven foarte mare (1MHz n cazul celui folosit n acest tutorial) i execut o instruciune/ciclu ledurile i vor schimba starea mult prea repede ca ochiul uman s sesizeze ceva. Avem nevoie de o modalitate de a mri timpul ct ledul se afl ntr-o stare. Pentru asta avem la dispozitie funciile _delay_us(double __us) (ntrzie execuia urmatoarei intruciuni cu numrul cerut de microsecunde) i _delay_ms(double __ms) (ntrzie execuia urmtoarei instruciuni cu un anumit numr de milisecunde) incluznd headerul util/delay.h. Noi ne vom folosi de funcia _delay_ms() pentru a obine ntrzieri vizibile iar instruciunile necesare vor fi plasate n bucla infinit while(1) codul urmnd a fi executat repetitiv att timp ct montajul este alimentat.
#include <avr/io.h> #include <util/delay.h> void main() { DDRB|=(1<<DDB0)|(1<<DDB7); while(1) {PORTB|=(1<<PB0); _delay_ms(500); PORTB&=~(1<<PB0); PORTB|=(1<<PB7); _delay_ms(500); PORTB&=~(1<<PB7); } } //header necesar pt a putea accesa pinii uC-ului //header necesar pentru delay

//seteaz pinul 0 i 7 ca ieire

//aprind //atept //sting ledul 0 //aprind //atept //sting ledul 7

ledul 0 500ms ledul 7 500ms

O modalitate de a scrie codul mai elegant ar fi sa definim operaiile cu biii din PORTB i delay-ul cu cte un nume. Exemplu:
#include <avr/io.h> #include <util/delay.h> #define #define #define #define #define //header necesar pt a putea accesa pinii uC-ului //header necesar pentru delay

LED0_ON() PORTB|=(1<<PB0) LED0_OFF() PORTB&=~(1<<PB0) LED7_ON() PORTB|=(1<<PB7) LED7_OFF() PORTB&=~(1<<PB7) DELAY() _delay_ms(500)

void main() { DDRB|=(1<<DDB0)|(1<<DDB7); while(1)

//seteaz pinul 0 i 7 ca ieire

10

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


{LED0_ON(); DELAY(); LED0_OFF(); LED7_ON(); DELAY(); LED7_OFF(); } } //aprind ledul 0 //atept 500ms //sting ledul 0 //aprind ledul 7 //atept 500ms //sting ledul 7

Cele dou coduri sunt echivalente. Diferena este doar de estetic. Poi testa codul compilndu-l i apoi scriindu-l n uC.

Tema 1
1. Folosind circuitul construit, implementeaz un numarator binar pe 8 bii. 2. Folosind circuitul construit, implementeaz un program care s deplaseze un led aprins la stnga i la dreapta alternativ, lungimea deplasrii fiind de 7 bii. 3. Implementeaz un program care s deplaseze ledul stins la stnga i la dreapta alternativ, lungimea deplasarii fiind de 7 bii. 4. Combin programele create anterior (2 i 3) astfel nct pornind cu deplasarea ledului aprins, dup 3 deplasri complete se va trece la deplasarea ledului stins. Dup 3 astfel de deplasri programul trece din nou la deplasarea ledului aprins, ciclul repetndu-se la nesfarit. 5. Scrie un program care s conin cel puin 3 animaii diferite i care se vor schimba dupa un numr ales de cicluri. 6. Folosind 3 leduri consecutive pentru reprezentarea a 3 variabile binare a,b,c i unul pentru f, implementeaz funcia f abc a b c .

O variant de rezolvare a temei se gsete n folderul Tema 1.

11

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Partea 2 Push the button


n prima parte ai fcut cunotin cu microcontrollerele i ai nvat cum se folosete un port ca output. n cele ce urmeaz vei nva cum poi folosi butoane pentru a schimba funcionarea montajului.

De ce ai nevoie?
Pentru a putea folosi butoanele nti s achiziionezi (dac nu ai deja) i s adaugi la circuitul existent urmatoarele componente: 2 push butoane 2 rezistente de 5K6 2 condensatori 100nF Circuitul arat cum se vede mai jos. Este acelai circuit pe care l-ai folosit pn acum cu butoanele conectate la pinii PD2 i PD3.

12

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Cum folosesc butoanele n cod?


nainte de a te apuca de scris codul trebuie s tii c aproape fiecare pin, pe lng funcia sa principal de input / output mai are i alte funcii secundare notate n parantez n dreptul pinului din schem. Butoanele le-ai conectat pe pinii PD2 i PD3. n dreptul lor n schem ai s vezi scris INT0 respectiv INT1 care se refer la NTreruperi externe. Ce este o ntrerupere? O ntrerupere poate fi descris ca un eveniment care foreaz uC-ul s execute codul scris pentru acea ntrerupere n locul codului principal. La terminarea codului din ntrerupere se revine unde a rmas n codul principal. Pentru a nelege mai bine ce este o ntrerupere, cum se folosesc n general dar i cum vei folosi butoanele i recomand sa citeti din datasheet-ul uC-ului urmtoarele: Pag. 56 Alternate Port Functions Pag. 63 Alternate Functions of Port D Pag. 63-68 External Interrupts Pentru a te putea folosi efectiv de ntreruperi va trebui s incluzi n cod headerul avr/interrupt.h . ntreruperile sunt procesate de o funcie numit ISR (Interrupt Service Routine) ce primete ca parametru numele vectorului de ntrerupere (ex: ISR(INT0_vect)). Pentru butoane vei folosi ISR(INT0_vect) i ISR(INT1_vect). n interiorul fiecrei funcii vei scrie ce anume vrei s se ntmple cnd are loc ntreruperea respectiv. Butoanele au rezistene de pull-up (pe pinul respectiv al butonului ai 5V) care sunt conectate i la pinii uC-ului la un capat i mas n cealalt parte. Cnd apei unul din butoane, tensiunea pe pinul uC-ului va deveni 0V, deci ai o tranziie HIGH-LOW (falling edge). Att timp ct butonul este apsat ai LOW LEVEL. Cnd dai drumul butonului vei avea din nou 5V, deci o tranziie LOW-HIGH (rising edge). n funcie de cum ai configurat ntreruperea (vezi tabelul 31 i tabelul 32 de la pagina 66-67 a datasheetului) ea se va declana la unul din evenimentele descrise mai sus. n exemplele de mai jos ntreruperea va fi configurat s declaneze la falling edge. Pe lng configurarea corect a ntreruperilor, pentru ca acestea s declaneze trebuie activate global folosind funcia sei(). Pentru a dezactiva global ntreruperile se folosete funcia cli().

Exemple
1. Unul dintre butoane incrementeaz valoarea lui PORTB cu o unitate la fiecare apasare iar celalalt decrementeaz valoarea lui PORTB n acelai fel.
#include <avr/io.h> #include <avr/interrupt.h> ISR(INT0_vect) {PORTB++;} ISR(INT1_vect) {PORTB--;}

void main()

13

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


{DDRB=0xFF; //PortB ca iesire MCUCR|=(1<<ISC01)|(1<<ISC11); //declanseaza INT0 si INT1 pe tranzitie H-L GIMSK|=(1<<INT0)|(1<<INT1); //activeaza intreruperile pe INT0 si INT1 sei(); while(1); }

2. Butonul conectat la INT0 intrementeaz valoarea lui PORTB att timp ct e apsat iar cellalt mparte la doi valoarea la fiecare ridicare a butonului.
#include <avr/io.h> #include <avr/interrupt.h> ISR(INT0_vect) {PORTB++;} ISR(INT1_vect) {PORTB>>=1;}

void main() {DDRB=0xFF; MCUCR|=(1<<ISC10)|(1<<ISC11); GIMSK|=(1<<INT0)|(1<<INT1); sei(); while(1); }

//PortB ca iesire //declanseaza INT0 pe low level si INT1 tranzitie //L-H //activeaza intreruperile pe INT0 si INT1

pe

Tema 2 un exemplu de rezolvare se gsete n folderul Tema2


1. Folosind circuitul construit, implementeaz un numrtor binar pe 8 bii cu incrementare la apsarea unuia dintre butoane i decrementare pe celalalt buton astfel nct valoarea maxima s fie 255 chiar dac se mai apas butonul de incrementare dup ce s-a ajuns la aceast valoare. Analog pentru valoarea minim 0. 2. Modific codul problemei 5 de la Tema 1 n asa fel nct unul dintre butoane s schimbe viteza animaiei iar celalalt s schimbe animaia. 3. Scrie un program care la fiecare apsare a butonului notat n schem S1 s selecteze pe rnd unul din leduri. Apsarea butonului S2 schimb starea ledului selectat. 4. Scrie un program care s aprind ledul 0 apoi la fiecare apsare a butonului S1 va deplasa ledul / ledurile aprinse cu o pozitie spre dreapta. Butonul S2 va decrementa valoarea portului cu o unitate. INT0 va declana pe falling edge iar INT1 pe rising. 5. Scrie un program care sa implementeze un astabil, monostabil si bistabil folosind 2 leduri. Butonul S1 va selecta modul de functionare iar S2 va actiona ca trigger cnd este cazul.

14

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Partea 3 The clock is ticking


Dac pn acum ai fcut programe n care pentru a ntrzia execuia cu un anumit timp ai folosit o metod destul de ineficient (funcia _delay_ms()) pentru delay-uri mari, acum vei nva cum poi folosi timerele de care dispune uC-ul pentru a executa la intervale de timp regulate o anumit parte de cod, n acelai timp lsnd restul programului s funcioneze normal. Pentru a nelege cum funioneaz timerele i ce fac exemplele de mai jos, arunc o privire (atent) n datasheet la: Pag. 3 Overview (doar primul paragraf) Pag. 69 8-bit Timer/Counter0, Overview, Registers, Definitions Pag. 70 Timer/Counter Clock Sources, Operation Pag. 71 Timer/Counter Timig Diagrams Pag. 72-73 8-bit Timer/Counter Register Description Pag. 74 - Timer/Counter0 and Timer/Counter1 Prescalers, Internal Clock Source Deoarece, aa cum ai citit n datasheet, timerele funioneaz independent de restul programului, pentru a ti cnd timerul a ajuns la valoarea maxim, vei folosi o ntrerupere ntr-un mod asemntor cu cele pe care le-ai folosit pentru butoane. ntreruperea va fi ISR(TIMER0_OVF_vect) care va declana de fiecare dat cnd timerul ajunge la valoarea maxim. Acum probabil ai s te ntrebi la ce te ajut toate chestiile astea? Hai s lum un exemplu concret n care f uC - frecventa la care lucreaz uC-ul (n cazul de fa 1MHz), f T frecvena la care funcioneaz timerul. f uC 1000000Hz Alegem un prescaler de 1/1024 => f T f uC / 1024 976.56Hz tiind c timerul este pe 8 bii rezult c ISR(TIMER0_OVF_vect) va declana de 976/256=3.81 ori pe secund. Ce faci dac vrei ca o anumit parte de cod s se execute mai rar de 3.81 ori ntr-o secund? Rspunsul este destul de simplu: implementezi un timer software, care asemenea celui hardware va avea un prescaler stabilit de tine. Not: n cele ce urmeaz voi folosi notaii i expresii de genul declaneaz la 3.81Hz = declaneaz de 3.81 ori pe sec. n cazul de fa dac vrei sa obii execuia unui cod la aproximativ 1Hz poi face ca n exemplul de mai jos:
ISR(TIMER0_OVF_vect) {if(++t==3) {t=0; ... codul tau ... } } // declanseaza la 3.81Hz //la fiecare a treia ntrerupere se va executa codul //reseteaz timerul software //do the monkey business

Exemplul de cod de mai sus d o frecven de execuie a codului de aproximativ 1.27Hz. ATENIE! Frecvena de 1.27Hz obinut mai sus este frecvena la care se va intra n if, respectiv n branch. Frecvena de execuie a instruciunilor din branch este f uC 1000000Hz .

15

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Exemple
Acum c ai vzut cam cum st treaba cu calculele, hai s vedem i ceva exemple practice de cod. Exemplele ce urmeaz se bazeaz pe exemplele anterioare pentru a nelege mai bine cum se pot combina noiunile nvate pn acum. 1. Leduri clipitoare versiunea 2
#include <avr/io.h> #include <avr/interrupt.h>

ISR(TIMER0_OVF_vect) {static uint8_t t=0; if(++t==3) {t=0; if(PORTB) PORTB=0; else PORTB=0xFF; } } void main() {DDRB=0xFF; TIMSK|=(1<<TOIE0); TCCR0|=(1<<CS02)|(1<<CS00); sei(); while(1); } //Enable Timer0 overflow interrupt //Timer0 prescaler =f/1024

2. Moving LEDs - aplicaie folosete Timer0 pentru a obine delay-ul necesar aprinderii i stingerii ledurilor. INT0 i INT1 sunt folosite pentru detecia apsrii butoanelor care modific viteza i direcia de deplasare.
#include <avr/io.h> #include <avr/interrupt.h> uint8_t speed=1,t=0,led=0,i=0, dir=0; ISR(TIMER0_OVF_vect) {if(++t==speed) {t=0; if(dir) {if(!led) {if(i<=7) {i++; PORTB=(PORTB<<1)+1; } else {led=1; i=0;} }

16

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


else {if(i<=7) {i++; PORTB>>=1;} else {led=0; i=0;} } } else {if(!led) {if(i<=7) {i++; PORTB=(PORTB>>1)+0x80; } else {led=1; i=0;} } else {if(i<=7) {i++; PORTB<<=1;} else {led=0; i=0;} } } } } ISR(INT0_vect) {dir=!dir; PORTB=0; t=0; i=0; led=0; } ISR(INT1_vect) {if(++speed==4) speed=1; t=0; } void main() {DDRB=0xFF; MCUCR|=(1<<ISC01)|(1<<ISC11); GIMSK|=(1<<INT0)|(1<<INT1); TIMSK|=(1<<TOIE0); TCCR0|=(1<<CS02)|(1<<CS00); sei(); while(1); }

//trigger on falling edge //enable INT0 and INT1 trigger interrupt //Enable Timer0 overflow interrupt //Timer0 prescaler =f/1024

17

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Partea 4 Fade to black


n aceast parte ne vom ocupa de PWM Pulse Width Modulation. Spus mai pe romnete variezi timpul ct aplici 1 logic pe pinii care genereaz PWM. Astfel poti controla intensitatea luminii ledurilor instalate pe plac, viteza motoarelor de curent continuu, etc, sau poi ncerca s i creezi propria instalaie pentru bradul de Crciun.

Cum se folosete?
n datasheet este scris foarte detaliat (poate chiar prea detaliat) cum funcioneaz generatoarele de PWM i care sunt modurile de lucru. La baz totul este legat de timere (Timer1 i Timer2) care au i alte funcii pe lng cea de baz. Ca s nelegi o idee mai bine i recomand s arunci o privire n datasheet peste urmtoarele: Pag 59-60 Alternate Port Functions PortB: OC1A, OC1B,OC2 Pag 76-83 Timer1 Pag 85-88 Output Compare Units Pag 88 Modes of operation: Normal Mode, Fast PWM Mode Pag 97-103 Register Description (doar ce tine de PWM, fara Input Capture) Asemntor cu Timer1 se folosete i Timer2 cu cteva deosebiri: este pe 8 bii i are doar un singur generator de PWM. Pentru a-i fi mai uor s foloseti i Timer2 pentru PWM n exemplele ce urmeaz vei folosi Timer1 configurat n aa fel nct s fie compatibil cu Timer2. Ca i pn acum configurarea corect a hardware-ului este esenial n buna funcionare a montajului. Civa pai care trebuiesc urmai n folosirea PWM-ului ar fi: Setarea pinilor folosii pentru PWM ca output. Setarea modului de lucru al generatorului de PWM folosind tabelele din datasheet Iniializarea registrului OCR folosit cu o valoare dorit Activarea Timerului corespunztor generatorului de PWM care se dorete a fi folosit prin selectarea unei surse de ceas Aceti patru pai reprezint de fapt patru linii de cod care pot fi scrise oriunde n cod att timp ct se respect ordinea. De preferat este ca cele patru linii de cod sa fie scrise grupat pentru a evita problemele.

Exemple
1. n acest exemplu un singur generator de PWM va fi folosit doar pentru a demonstra implementarea n cod a celor patru pai descrii mai sus.
#include <avr/io.h> #include <util/delay.h> void main() {DDRB|=(1<<DDB1); //seteaza pinii de PWM ca output TCCR1A|=(1<<COM1A1)|(1<<WGM12)|(1<<WGM10);

18

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


// configureaza pwm: Fast PWM 8bit, Noninverting OCR1A=0; // initializeaza OCR1A cu 0 TCCR1B|=(1<<CS10); //seteaza sursa de ceas: clk/1 (no prescalling) while(1) //creeaza un effect de fade destul de nice {while(++OCR1A<255) _delay_ms(5); while(--OCR1A>0) _delay_ms(5); } }

2. Acest al doilea exemplu este puin mai complex folosind att Timer1 ct i Timer2 pentru a genera trei semnale PWM. n acest fel nlocuind cele 3 leduri de pe PCB conectate la generatoarele de PWM cu un singur led RGB s-ar putea obtine orice culoare existent. Scopul exemplului este ns altul: evidenierea modului de lucru asemanator al timerelor 1 i 2.
#include <avr/io.h> #include <util/delay.h> void main() { DDRB|=(1<<DDB1)|(1<<DDB2)|(1<<DDB3);//seteaza pinii de PWM ca output // configureaza Timer1: Fast PWM 8bit, Non-inverting TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM12)|(1<<WGM10); OCR1A=255; // initializeaza OCR1A cu 255,OCR1B cu 0 OCR1B=0; // configureaza Timer2: Fast PWM 8bit, Non-inverting TCCR2|=(1<<COM21)|(1<<WGM21)|(1<<WGM20); OCR2=0; // initializeaza OCR2 cu 0 //seteaza sursa de ceas Timer1: clk/1 (no prescalling) TCCR1B|=(1<<CS10); TCCR2|=(1<<CS20); //seteaza sursa de ceas Timer2: clk/1 (no prescalling) while(1) { while(--OCR1A>0) {OCR1B++; _delay_ms(5); } while(--OCR1B>0) {OCR2++; _delay_ms(5); } while(--OCR2>0) {OCR1A++; _delay_ms(5); } }}

19

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Partea 5 Convertorul Analogic Digital (ADC)

Pn acum am vzut cum se pot folosi diverse module ale uC-ului pentru a afia anumite valori sau evenimente pe cele 8 leduri. Dac n partea 2 (Push the button) am vzut cum putem detecta evenimente exterioare de scurt durat (apsarea unui buton) ce se prezint sub forma unor semnale digitale (1 butonul nu este apsat, 0 buton apsat), n aceast parte a tutorialului vom vedea cum putem citi semnale continue n timp (tensiunea pe o rezisten n acest caz). Pentru a putea realiza acest lucru trebuie modificat montajul realizat anterior prin conectarea lui AGND la GND, AVCC la VCC i AREF printr-un condensator la GND ca n schema prezentat mai jos.

20

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

Cum se folosete?
n datasheet funcionarea modulului de conversie analogic-digital este descris pe 13 pagini ns pentru a putea urma acest pas al tutorialului nu este necesar parcurgerea tuturor paginilor. Totui pentru o mai bun nelegerea felului cum merg lucrurile i recomand s citeti urmtoarele pagini: Pag. 196-198 Analog-to-Digital Converter - Features Pag. 198 Starting a Conversion, Prescaling and Conversion Timing Pag. 200 Changing Channel or Reference Selection Pag. 201 Voltage Reference Pag. 205-208 - ADC Conversion Result, ADC Multiplexer Selection, ADC Control and Status Register A, ADC Data Register

Acum voi explica pe rnd ce nseamn fiecare bloc despre care ai citit n paginile enumerate mai sus: Analog to Digital Converter (Convertor Analogic Numeric): acest dispozitiv are rolul de a converti valoarea unei tensiuni ntr-un numr. Modul n care se face acest lucru difer ntre tipurile de ADC. Pentru aceasta are nevoie de o tensiune de referin, fix, stabil. n funcie de tensiunea de referin i de rezoluia convertorului (numrul de bii pe care lucreaz), pentru aceeai valoare a tensiunii aplicate la intrare se pot obine rezultate diferite. Aa cum ai citit la pag. 205 ADC Conversion Result, rezultatul (numrul) se obine dup formula: n cazul n care se folosesc toi cei 10 bii ai convertorului. Prescaler (pag. 198 Prescalling and Conversion Timing) ca orice circuit digital, i ADC-ul are nevoie de un semnal de tact pentru a funciona. De frecvena acestui semnal depin timpul de conversie i rezoluia maxim. Pentru a folosi ADC-ul la rezoluia maxim, Atmel recomand frecvene ntre 50KHz i 200KHz. Timpul de conversie pentru prima conversie este de 25 de perioade de tact (clock cycles) iar pentru urmtoarele conversii este de 13 perioade. ADC Multiplexer (pag. 200 Changing Channel or Reference Selection): Este posibil ca unui singur convertor s i se atribuie mai multe c anale de intrare, ca i n cazul uC-ului ATMega8 care are un singur ADC cu 5 canale. Acestea se conecteaz la convertor cte unul la un moment dat prin intermediul unui multiplexor. Multiplexorul se comporta ca un comutator cu mai multe pozitii. Poziia este dat de biii MUX3:0 din registrul ADMUX. Astfel pentru canalul 0 (poziia 0) biii vor avea valorile 0000 (0 n zecimal) iar pentru canalul 5 (poziia 5) vor avea valorile 0101 (5 n zecimal). Pentru celelalte combinaii existente vezi Tabelul 75, pag. 206. ADC Voltage Reference (Tensiunea de referin) Aa cum am explicat mai sus, de tensiunea de referin depinde n mod direct rezultatul conversiei pentru aceeai tensiune aplicat la intrare. Convertorul existent n ATMega8 ofer posibilitatea de a alege ntre 3 referine: AREF

21

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR (tensiunea aplicat pe pinul AREF), AVCC (tensiunea de alimentare a convertorului, 5V, aplicat pe pinul AVCC) sau referina intern de 2.56V. Este recomandat ca tensiunea de referin s se aleag ct mai apropiat de valoarea maxim pe care o poate atinge semnalul de intrare ns sa nu fie mai mic.

Exemple
1. Acest exemplu demonstreaz cum se seteaz ADC-ul pentru a citi n mod continuu valoarea tensiunii aplicat pe canalul 0 cu afiare pe cele 8 leduri.
#include <avr/io.h> void adc_init(void); uint8_t adc_read(uint8_t channel); int main(void) { DDRB=0xFF; adc_init(); while(1) { PORTB = adc_read(0); } } void adc_init() { ADMUX|=(1<<REFS0) //Referinta AVCC, | (1<<ADLAR);//Deplaseaza rezultatul la stanga (cei mai semnificativi 8 biti in ADHC) ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) //Prescaler: F_CPU/128 | (1<<ADEN); //Activeaza ADCul } uint8_t adc_read(uint8_t channel) { ADMUX &= 0xE0; //Sterge vechiul canal ADMUX |= channel; //Seteaza noul canal ADCSRA|=(1<<ADSC); while(!(ADCSRA&(1<<ADIF))); return ADCH; } //Porneste conversia //Asteapta sfarsitul conversiei //Returneaza rezultatul (pe 8 biti)

//Portb devinde iesire //Initializeaza ADC //Bucla infinita //Transmite pe PortB valoarea citita pe canalul 0

22

S-ar putea să vă placă și