Sunteți pe pagina 1din 20

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?..................................................................................................10 Leduri clipitoare......................................................................................................................11 Tema 1........................................................................................................................................12 Partea 2 Push the button..............................................................................................................12 De ce ai nevoie?..........................................................................................................................13 Cum folosesc butoanele n cod?.................................................................................................13 Exemple......................................................................................................................................14 Partea 3 The clock is ticking........................................................................................................16 Exemple .....................................................................................................................................17 Partea 4 Fade to black..................................................................................................................19 Cum se folosete?.......................................................................................................................19 Exemple......................................................................................................................................19

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/)

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR 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!

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 5

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR 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 po i 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.

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.

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

n fereastra care i apare vei scrie codul.

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. 8

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR 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:

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> //header necesar pt a putea accesa pinii uC-ului

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

void main() { DDRB|=(1<<DDB0)|(1<<DDB7); PORTB|=(1<<PB0)|(1<<PB7); while(1); }

//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 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.

10

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR

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 ledul 0 //atept 500ms //sting ledul 0 //aprind ledul 7 //atept 500ms //sting ledul 7

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> //header necesar pt a putea accesa pinii uC-ului //header necesar pentru delay

#define LED0_ON() PORTB|=(1<<PB0) #define LED0_OFF() PORTB&=~(1<<PB0) #define LED7_ON() PORTB|=(1<<PB7) #define LED7_OFF() PORTB&=~(1<<PB7) #define DELAY() _delay_ms(500) void main() { DDRB|=(1<<DDB0)|(1<<DDB7); while(1) {LED0_ON(); //seteaz pinul 0 i 7 ca ieire //aprind ledul 0

11

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


DELAY(); LED0_OFF(); LED7_ON(); DELAY(); LED7_OFF(); } } //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 = ab c +a b +c .

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

Partea 2 Push the button

12

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR 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.

Cum folosesc butoanele n cod?

13

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR 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() {DDRB=0xFF;

//PortB ca iesire

14

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


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; //PortB ca iesire MCUCR|=(1<<ISC10)|(1<<ISC11); //declanseaza INT0 pe low level si INT1 pe tranzitie //L-H GIMSK|=(1<<INT0)|(1<<INT1); //activeaza intreruperile pe INT0 si INT1 sei(); while(1); }

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.

15

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 = 1000000 Hz

Alegem un prescaler de 1/1024 =>

f T = f uC / 1024 = 976 .56 Hz

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 = 1000000 Hz .

16

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. Ex1: 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

Ex2: 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; }

17

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


else {led=1; i=0;} } 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); //trigger on falling edge GIMSK|=(1<<INT0)|(1<<INT1); //enable INT0 and INT1 trigger interrupt TIMSK|=(1<<TOIE0); TCCR0|=(1<<CS02)|(1<<CS00); sei(); while(1); } //Enable Timer0 overflow interrupt //Timer0 prescaler =f/1024

18

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);

19

Tutorial Introducere n programarea i utilizarea microcontrollerelor Atmel AVR


// configureaza pwm: Fast PWM 8bit, Non-inverting // initializeaza OCR1A cu 0 //seteaza sursa de ceas: clk/1 (no prescalling) //creeaza un effect de fade destul de nice

OCR1A=0; TCCR1B|=(1<<CS10); while(1) {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 TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM12)|(1<<WGM10); // configureaza Timer1: Fast PWM 8bit, Non-inverting OCR1A=255; // initializeaza OCR1A cu 255,OCR1B cu 0 OCR1B=0; TCCR2|=(1<<COM21)|(1<<WGM21)|(1<<WGM20); // configureaza Timer2: Fast PWM 8bit, Non-inverting OCR2=0; // initializeaza OCR2 cu 0 TCCR1B|=(1<<CS10); //seteaza sursa de ceas Timer1: clk/1 (no prescalling) 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); } }}

20