Departament de Microelectrònica i Sistemes Electrònics
AVR i FONAMENTS DE COMPUTADORS
Enginyeria en Informàtica (ETSE)
exemples
A continuació es posen un conjunt d'exemples d'introducció a l'ensamblador i ús dels AVR
Tots estan fets sobre el microcontrolador ATmega8
Retards
A partir d'un primer exemple molt simple (introducció a l'ensamblador) es realitzen una sèrie de programes que porten a encendre un led pel PORTD.0 a una freqüència de 1Hz.
La primera rutina de retard
La rutina més simple de retard es fa construint un bucle, de la forma. Cal una variable inicialitzada a un valor i un bucle que decrementa la variable fins arribar a zero, moment en què se surt del bucle. El format és simple:ldi r16, 100
bucle: inc r16
brne bucleEl bucle s'executa mentre r16 no és igual a zero. Això vil dir que r16 anirà comptant fins que sigui superior a 2^8-1, moment en que sobresortirà del registre de 8 bits i s'igualarà a 0.
La duració del bucle es calcula en base al nombre d'instruccions que s'executen:
Instrucció #cicles/instr #cops TotalCàrrega inicial
Increment
salt
no saltldi
inc
brne
brne 1
1
2
1 1
156
155*2
1 1
156
310
1En total té una duració de 468 cicles de rellotge. Donat que el microcontrolador funciona a una freqüència de 1MHz, la duració del bucle és de 0.468mseg.
Amb un registre de 8 bits es pot comptar, com a màxim, fins a 256. Per tant, la durada màxima que es pot aconseguir amb un bucle (inicialitzant el registre a 0) és de 256*3=718cicles. Això vol dir que es necessita anidar dos bucles o emprar altres mitjans per a realitzar el retard d'1 segon.
Una rutina de retard de 3Hz
En un primer pas es vol aconseguir encendre i apagar un led a una freqüència de 3 Hz. Per fer-ho s'analitza la viabilitat d'aconseguir-ho mitjançant una rutina doblement anidada.
La rutina doblement anidada necessita de dues variables incrementals en la forma que mostra el següent codi:
ldi r17, n2
bucle2:ldi r16, n1
bucle1:inc r16
brne bucle1
inc r17
brne bucle2La duració del bucle intern, d'acord amb els càlculs realitzats en l'apartat anterior és de 3*n1 cicles. La duració del bucle goblal és, per tant,
Instrucció #cicles/instr #total ciclesCàrrega inicial de r17
Execució bucle intern
Increment r17
salt
no saltldi
bucle1
inc
brne
brne 1
3*(256-n1)
1
2
1 1
(256-n2)*3*(256-n1)
(256-n2)
2*(256-n2-1)
1...d'on el nombre total de cicles esdevé 3*(256-n2)*(256-n1+1).
Per a aconseguir una freqüència de sortida de 3Hz, s'ha de crear un retard d'1/6 de segon. Això és, 1/3/2 segons a 0 i 1/3/2 segons a 1.
Una possibilitat és fent n1=40 i n2=0. En total compta 3*256*(256-40+1) =166656 cicles.
Freq03h mostra el codi complert de l'exemple.
Led funcionant a 3Hz emprnat el doble registre X
Treballant amb els registres X, Y, o Z, que agrupen dos registres de 8 bits formant-ne un de 16 bits es pot optiimtzar una mica a rutina de retard. L'algorisme en aquest cas tindira el cos següent:
ldi xh, high (n)
ldi xl, low (n)
bucle:adiw x, 1
brne bucleEl bucle s'executa mentre X no sigui igual a zero. Això vil dir que X anirà incrementant fins que sigui superior a 2^16-1, moment en que sobresortirà del registre de 16 bits i s'igualarà a 0.
La duració del bucle és...
Instrucció #cicles/instr #cops TotalCàrrega inicial
Increment
salt
no saltldi
adiw
brne
brne 1
2
2
1 2
2^16-n
(2^16-n)-1
1 2
2*(2^16-n)
2*(2^16-n)-2
1...igual a 4*(2^16-n)+1.
Així, per aconseguir una freqüència d'1/3 calen dos retards (primer per tenir la sortida a 1 i després per la sortida a 0). Per tant, ciclesRetard=(1MHz/3)/2=166667cicles => n=23870
El programa Freq03hX mostra el codi complert.
Led funcionant a 1Hz amb comptador
Fins ara hem considerat rutines de retard que arribaven fins als 3Hz. Aquest és un límit que ve imposat per treballar amb dos registres de 8 bits o amb un registre de 16 bits. Superar aquest límit amb els mètodes vistos implica emprar un nou registre de 8 bits.
El comptador té uns avantatges clars quan es vol emprar com a generador de retards: facilita la feina de crear bucles de retard, gràcies als prescalers que porten incorporats un comptador de 16 bits pot realitzar un retard de fins a 2^16*1024 = 67 segons (amb un rellotge base d'1MHz) i, a més, el comptador pot implementar el retard mentre el programa principal es dedica a altres tasques.
Per a implementar un retard d'1 segon a partir d' un comptador, en un primer moment, es pot pensar en un mètode simple basat en interrupció per overflow. Es pot fer treballant amb el Timer1 de 16 bits i agafant un prescaler de 8. Per interrupció per overflow, només cal reinicialitzar el comptador a cada interrupció, moment que s'aprofita per canviar el valor de la sortida. El valor que cal carregar en la interrupció és 2^16-(1MHz/8prescaler/2nivells)=3036.
Tot i que el mètode és simple, encara surt complicat quan aprofitem els recursos que ens proporcionen els timers del microcontrolador.
Led funcionant a 1Hz amb comptador en mode CTC
Quan cal una freqüència de sortida precisa l'exemple mostra un petit retard que cal calcular de forma exacta. Aquest retard es produeix en el moment en què s'entra en overflow. Hi ha un escolament d'uns petits cicles de rellotge fins que es realitza la inicialització del comptador.
Treballant amb alguns dels modes avançats del comptador es pot aconseguir millorar la precisió. En aquest exemple es treballarà amb el mode Clear Timer on Compare i en Toggle Output in Compare (veure comptadors). El que es fa és simple: es carrega el valor al qual es vol commutar en un registre comparador. En arribar el registre comptador al valor del comparador automàticament es reinicia el comptador a 0, no escolant-se cap cicle addicional de rellotge. Al mateix temps, s'ha programat la sortida de forma que en cada comparació positiva commuti d'estat. L'exemple és tan simple que ni tan sols cal programar cap interrupció.
El resultat es pot veure en Freq1hCTC. S'ha treballat amb el timer1 de 16 bits i amb un prescaler de 8. Això ha donat un valor del comparador de 1MHz/8/2 = 62500. La sortida OC1A es té en el PORTB.1.
En Freq1hATmega128 es té el mateix programa per a funcionar amb el microcontrolador ATmega128 de la placa ET-AVR i amb el Timer1 de 16 bits. Donat que el rellotge funciona a 16MHz, en aquest cas s'ha treballat amb un prescaler de 256, fet que dóna un valor a carregar en el comparador de 16MHz/256/2 = 31250.
Control d'un motor pas a pas
Els motors pas a pas són motors que funcionen per fases i que proprocionen un control acurat de la posició a través de pasos (girs) d'angle constant del motor.
El funcionament és fàcil: cal controlar la fase que s'ha d'enviar al motor de forma que progressi de forma constant, sense fer salts.
L'exemple motor_pas_a_pas proporciona el codi que controla un motor de 4 fases A-noA-B-noB. A cada canvi de fase (veure figura 1, només es mostren A i B (nA i nB són els negats respectius)) el motor avança un pas en sentit de les agulles del rellotge o a la inversa, segons la fase que segueixi.
Figura 1. Fases en un motor pas a pas de 4 fils
El motor es manté fix a l'angle quan no hi ha avançament de fase.