Sunteți pe pagina 1din 17

Aspecte practice privind utilizarea resurselor microcontrollerelor Atmel AVR

M.S. 2012
o mare parte din aceste materiale, inclusiv explicaii n cuvinte, se afl la: http://ham.elcom.pub.ro proiect 2 documentaie

Cel mai simplu circuit


VCC JF1 ISP 1 3 5 + 1 3 5 2 4 6 2 4 6 VCC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 U1 PB0(T0/XCK) PB1(T1) PB2(INT2/AIN0) PB3(OC0/AIN1) PB4(SS) PB5(MOSI) PB6(MISO) PB7(SCK) RESET Vcc GND XTAL2 XTAL1 PD0(RxD) PD1(TxD) PD2(INT0) PD3(INT1) PD4 (OC1B) PD5(OC1A) PD6(ICP1) (AD0)PA0 (AD1)PA1 (AD2)PA2 (AD3)PA3 (AD4)PA4 (AD5)PA5 (AD6)PA6 (AD7)PA7 AREF GND AVcc (TOSC2)PC7 (TOSC1)PC6 (TDI)PC5 (TDO)PC4 (TMS)PC3 (TCK)PC2 (SDA)PC1 (SCL)PC0 (OC2)PD7 R1 10K 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21

C1 2u2

VCC

VCC

RXD TXD

X1

R2 ATmega16-DIL40 330R C2 22pF C3 22pF SW1 1 2 VCC D2 LED C5 100n VCC C6 100n VCC + C4 10u

U3 D1 VINPUT 1N4001 1

LM7805 VOUT 3 VCC

C12 100n

GND

VIN

C13 100n

Ce face util: 1 pin de intrare (PD5), 1 pin de ieire (PD6)

Pini de I/O
Pini de intrare: Initializare cu DDRX.Y = 0 (Data Direction Register) Seteaz PORTX.Y = 1 pentru pull-up resistor intern implicit PORTX.Y = 0 (fr pull-ul resistor) Citete valoarea pinului X.Y folosind PINX.Y
Exemplu: If(PIND.5 == 0) LED = 1 // citete switch conectat la D.5

Pini de ieire: Iniializare cu DDRX.Y = 1 Scrie valoarea pinului folosind PORTX.Y


Exemplu: PORTD.6 = 1 // aprinde LED conectat la D.6

Not: se pot accesa toi cei 8 pini simultan


PORTC = 0b11101011 // scriere // citire

sau if(PINE == 0b10101011) {...}

Programarea uC
fiiere de intrare: *.c, *.h, etc fiier de ieire: *.hex (formatul s.n. Intel HEX dar nu este specific doar Intel) programarea clasic: uC scos din circuit i introdus ntr-un programator programarea in-system: uC rmne n circuit n timpul programrii; folosete conectorul dedicat ISP programarea folosind bootloader: soft scris prima dat n uC, care preia programul pe un port disponibil n sistem, nededicat (serial, USB, etc); bootloader-ul este un OS superminimal urmeaz 2 scheme de programatorare ISP bootloader: dup ce vedem portul serial

1. 2. 3.

Programator extern, serial


software: PonyProg

Programator serial simplificat


DB9 f emale 1 6 2 7 3 8 4 9 5 4K7 4K7 4K7 15K MISO SCK RESET Q1 NPN ISP 1 3 5 2 4 6

1 3 5

2 4 6

MOSI

DZ5V1

schema precedent, adaptat pentru plcua noastr (conector ISP 2x3, fr alimentare extern, cci plcua cu uC are deja alimentare) acelai pinout de conector ISP ca n schema cu uC

Programator extern, paralel

programatorul paralel e mai rapid dezavantaje:


portul paralel de la PC e mai fragil dect cel serial n lipsa sa, un convertor USB-paralel de obicei nu merge cu aceast schem

Programator paralel simplificat


CONNECTOR DB25 MALE 1 14 2 15 3 16 4 17 5 18 6 19 7 20 8 21 9 22 10 23 11 24 12 25 13

ISP 1 3 5 2 4 6

5 x 1K
SCK MOSI

1 3 5

2 4 6

RESET MISO

SHIELD

s-au eliminat componentele de protecie !

Comunicaia cu calculatorul
5V 10V

-10V

Procesor (TTL) MAX202

DB9 (RS232)

uC conine deja un port serial (TTL) compatibil cu PC-ul trebuie doar un translator de nivele electrice (TTL RS232) utilitate:
debugging pe robotul real: printf() n programul uC nu scrie pe ecran, ci pe portul serial; se pot scrie valorile citite de la senzori (pentru calibrare), se pot trimite de la PC parametri modificai, comenzi, etc, n timp real bootloader, pentru a nu mai folosi programator !

Comunicaia cu calculatorul
5V 10V -10V

Procesor (TTL) MAX202

DB9 (RS232)

Structura unui caracter: 1 start bit 8 data bits (8D) 1 stop bit Comparai cele 2 forme de und: TTL, RS232 (cea mai natural este TTL) Cei 10 bii pe f.u. TTL: START, 8D, STOP = 0101010101 NOT: LSB transmis primul (MSB lng stop bit) deci numrul pe 8 bii se citete de la dreapta: 01010101

Translatorul de nivele seriale

OBS: MAX232: 4 x 1F; MAX202: 4 x 100nF TxD, RxD snt aceiai ca pe schema cu procesorul

Programarea cu bootloader pe portul serial


Prima dat tot trebuie scris bootloader-ul folosind un programator extern Vi-l pot scrie eu; disponibil pentru AT Mega 8,16,32,128 cu cuar de 7.37MHz (toate uC) i 8 i 13.5MHz (doar AT Mega16) avantaj:
nu mai necesit programator extern !

dezavantaje:
personalizat pentru un anumit tip de procesor i cuar necesit port serial

ntreruperi
ntreruperi externe: se activeaz la
recepionarea unui front/nivel pe anumii pini recepia unui caracter pe serial, etc

ntreruperi interne:
eveniment dat de un timer intern (ajunge la o anumit valoare, etc) finalul unei conversii A/D, etc

Vezi datasheet pentru lista ntreruperilor fiecrui procesor n soft, o ntrerupere e deservit (engl. serviced) de o funcie C numit ISR (ISR= Interrupt Service Routine) Vezi programul de test: ntreruperea pentru Timer 1 face s clipeasc LED-ul de la PORTD.6 cu perioada de 1 sec.

Timere
Timer 0,1,2 Alte uP au alt numr de timere 8 bii sau 16 bii sursa: clock intern, clock intern cu prescaler, clock extern (timer 2), pin special de intrare... prescalerul permite reducerea fCLOCK frecvene mai mici perioade mai mari

multe moduri de lucru, trebuie citit datasheet-ul Folosite pentru generarea sau msurarea unor intervale de timp Obs: pt generare, se poate folosi i funcia delay_ms(valoare) dar ine procesorul blocat (nu lucreaz pe intreruperi)

Aplicaie 1: generarea unui eveniment periodic

modul CTC (Clear Timer on Compare Match)


perioade de timp T1 dup fiecare T1 are loc o ntrerupere (timer1 interrupt) codul scris de user n rutina ntreruperii va fi executat periodic, cu perioada T1

exemplu: timer 1 (16bii)


timerul este incrementat de la 0 folosind ceasul selectat valoarea curent este n TCNT1 (Timer Count) cnd TCNT1 = OCRA1 (Output Compare Register), se genereaz o ntrerupere i se reseteaz timerul, dup care incrementarea continu de la 0 alegnd OCRA1 i frecvena clock-ului se poate genera orice perioad

Calcul detaliat

Intervalul T1 = N subintervale dt
N = OCR1A dt = ceasul sistemului, eventual divizat printr-un prescaler (divizor de vitez mare, avnd cteva valori fixe) dac dorim T1 mare, tb. N mare i dt mare
N mare: registru de 16b, nu 8b dt mare: prescaler ct mai mare verif. care timer e pe 16b

exemplu: dorim ntrerupere de timer la 1s folosind Timer 1


Folosim modul CTC n registrele urmtoare setm biii pentru mod, valoarea prescalerului, ntreruperi Cum se calculeaz valoarea unui registru de control ? Foaia de catalog e sfnt ! toate tabelele provin de acolo. RTFM ! (Read The Fine Manual) Apoi ncrcm val. calculate n TCCR1A, TCCR1B, OCR1

Registre Timer/Counter 1

Timer/Counter 1

Exemplu de calcul: dorim 1 s = frecven mic fcuar =13.5MHzdivizare cu 13,500,000 > 65536 (16 bii) nu se poate trebuie prescaler prescaler max (CS12:CS10 = 101): 1024; 13.5MHz / 1024 = 13.184KHz avem 13184Hz, dorim 1Hz: mai divizm cu 13184 = 3380h OCR1AH = 33h, OCR1AL = 80h mai rmne s setm divizorul i modul de lucru; am ales CTC din tabelul anterior i acesta: TCCR1A = 0 i TCCR1B= 00001101 = 0Dh

Good News !
Toate calculele pot fi fcute de catre CodeWizard culorile corespund calculelor precedente tot e necesar s citii datasheet-ul pt. explicarea modurilor, a divizorilor etc
Compare A match OCR1A dac era B OCR1B

Aplicaie 2: Modul PWM al timerelor

modul PWM: util pentru varierea vitezei unui motor, etc TPWM fix, factorul de umplere variabil prin varierea T (T1,T2) 1 = T1/TPWM mic vitez mic 2 = T2/TPWM mare vitez mare La nceputul unei perioade TPWM, pinul OC0 setat pe 1 TCNT0 incrementat automat pn atinge maximul (255 pt 8bii) n momentul TCNT0= OCR0 pinul OC0 devine 0 pt restul perioadei TPWM deci, pe pinul OC0 avem semnalul PWM din figur Pt fiecare timer (0,1,2...) avem un pin OC (Output compare) corespunztor

10

Calcul frecven PWM timer0


La PWM frecvena constant, factorul de umplere variabil Etape:
programm la nceput frecvena constant fPWM =1/TPWM n timpul funcionrii variem fact. de umplere dup dorin varierea variem T1/T2 precedent variem OCR0

Exemplu: alegem frecvena pentru fcuar = 13.5MHz factori de divizare:


presupunem prescaler de 1024 umplerea registrului de timer de 8 bii: 256 obinem fPWM = 13500000/1024/256 = 51 Hz OBS: 51Hz poate fi acceptabil la becuri/motoare, dar n cazul LED-urilor aceasta frecven este vizibil ca un uor flicker

alegem un prescaler mai mic: 256, implicit fPWM va fi mai mare fPWM = 13500000/256/256 = 205 Hz deci folosim prescaler de 256 CS02:00 = 100

Timer/Counter 0 Control Register

programm Timer0 n modul PWM alegem un prescaler de 256: CS02:CS00 = 100

11

Timer/Counter 0 Control Register

tabelul COM 01:00 valabil pentru modul Fast PWM alegem WGM 01:00 = 11, COM 01:00 = 10 CS 02:00 = 100 n total: TCCR0 = 01101100 = 6Ch

Good news !

n modul PWM nu ne trebuie ntrerupere de timer; resetarea timerului duce la trecerea n 1 (hardware) a pinului OC0, iar atingerea valorii OCR0 duce la trecerea n 0 a pinului, nu avem nimic de fcut ntr-o rutin de ntrerupere

CodeWizard din nou !

12

Programul n modul PWM


// intializam timerul 0 in modul PWM // Clock source: System Clock/256, Clock value: 13500000/256=52734 Hz, Mode: Fast PWM top=FFh, OC0: Non-Inverted PWM TCCR0=0x6C; // valoarea din calculul precedent TCNT0=0x00; OCR0=0x00; // programul variaz intensitatea luminoas a unui LED conectat la pinul OC0 n 4 pai // intensitatea se schimb la cte o secund, schimbnd OCR0 void main (void) { while(TRUE) { OCR0 = 0; delay_ms(1000); // stins OCR0 = 4; delay_ms(1000); // slab OCR0 = 16; delay_ms(1000); // mediu OCR0 = 253; delay_ms(1000); // tare } }

PWM
Avantaj PWM hardware (folosind modul PWM al timerelor): dup iniializare, tot ce tb s fac programul e s scrimbe OCR n orice moment i se schimb automat factorul de umplere pe pinul OC corespunztor Dezavantaje:
uC nu are dect puine timere dac avem 3 timere: 3 canale PWM posibile, fiecare cu un pin OC corespunztor; dac dorim s controlm de ex. 10 motoare/becuri, nu putem un timer PWM nu mai poate fi folosit la altceva (poate avem neoie de multe temporizri n aplicaie)

13

PWM
Soluie: PWM software Folosim un timer n modul CTC pt controlul tuturor celor 10 (sau oricte) motoare, conectate la 10 pini de uz general Setm perioada timerului la o valoare mic (ex: 1ms) n rutina ISR a timerului:
folosim un contor i pt a obine TPWM=ct; ex: i=50 TPWM=50ms; incrementm i; cnd i=50 facem i=0 pt a obine perioada de repetiie=ct controlm ci pini externi (de uz general) dorim; cnd i=0 i setm pe toi pe 1 stabilim cte praguri de comparaie i1,i2,... dorim; cnd i=i1 trecem pinul 1 pe 0, cnd i=i2 trecem pinul 2 pe 0, etc

i1,i2,... vor fi variabile globale; cnd programul principal le schimb, automat se vor vedea i n rutina ISR

Senzori
Senzori cu ieire digital (TTL)
stri: LO i HI se citesc pe un pin de intrare (PINX.y, nu PORTX.y) variant: asigur doar starea LO, starea HI fiind implicit i dat de o rezisten de pull-up; exemplu: tast/microswitch conectat la mas (vezi primul circuit) pull-up intern: se activeaz cu PORTX.y=1 cnd direcia e de intrare (DDRX.y=0) pot fi i senzori analogici (de lumin, cmp magnetic etc) la care se detecteaz trecerea peste o valoare de prag

Senzori cu ieire analogic


se folosete convertorul A/D intern maxim 8 canale = 8 senzori

14

Exemplu: senzor de lumin

AO = 1/2 LM358 (-Vcc = 0V, +Vcc = +5V) Fotodioda e polarizat invers, pentru sensibilitate maxim ! R1 = zeci.. sute K (exemplu: semireglabil de 1M )

Convertorul Analog-Numeric (ADC)

Specificaii ! kSPS = kilo Samples per Second Tip de conversie: aproximaii succesive (AS); mai multe detalii vezi cursul de IEM :-) Registre de control: ADMUX, ADCSRA

15

ADC

REFS: referina poate fi AVCC, AREF extern sau 2.56V (referin intern precis) nu am inclus modurile difereniale; ADLAR = AD Left Adjust Result :
dac snt suficieni 8 bii, se folosete ADLAR=1 i se citete doar ADCH (coninnd cei mai semnificativi 8bii) dac se doresc 10b ADLAR=0, se citesc ADCH, ADCL atenie la execuia prii analogice dac vrei s v bazai pe 10b !

ADC
ADEN = ADC Enable ADSC = ADC Start Conversion; se pune pe 1 pentru a porni o conversie n modul Single Conversion; este 1 atta timp ct conversia e n lucru, devine 0 cnd rezultatul e gata; n modul Free Running se pune pe 1 la nceput ADATE = ADC Auto Trigger Enable; se fol. n conjuncie cu registrul SFIOR ADIF = ADC Interrupt Flag; devine 1 cnd o conversie e gata i se lucreaz pe ntreruperi; este automat trecut n 0 cnd se execut ntreruperea ADC ADIE = ADC Interrupt Enable; n plus, trebuie setat bitul I n SREG ADPS 2:0 = cu ct se divizeaz XTAL pentru a obine ceasul ADC

16

Exemplu de folosire a ADC n modul Sgl. conv.


void init_adc(void) { // ADCSRA initialization; in order from MSB: // 10 = enable ADC, do not start a conversion yet // 0 = disable free-running mode // 10 = clear ADIF interrupt flag, disable ints // 101 = ADC clock =XTAL/32 ADCSRA=0b10010101; #define ADMUX_NOCHANNEL 0b00100000 // ADMUX initialization // 00 = VREF=AREF // 1 = ADLAR=1 (left adjust, use only 8 bits) // the rest: channel selection ADMUX=ADMUX_NOCHANNEL; } // channel can be 0 to 7; float read_voltage(byte channel) { channel &= 0b00000111; ADMUX = ADMUX_NOCHANNEL | channel; ADCSRA |= 0b01000000; while (ADCSRA & 0b01000000); ADCSRA |= 0b00010000; return (float)(ADCH) * 0.215; }

// external AREF, ADLAR=1

// 8 channels are possible= max value 111 // select channel 0 to 7 (000 to 111) // start conversion by setting bit ADSC=1 // wait for result; while working, ADSC is 1 // clear ADIF flag // calibrate to whatever values are in the schematic

17

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