You are on page 1of 15

Curso Bsico AVR AT90S1200 Escrito por Santiago Villafuerte Jueves, 19 de Marzo de 2009 20:24 Para comenzar a estudiar

este curso necesitas tener un conocimiento bsico de programacin a nivel ensamblador. Paso 1 Qu significa AVR? Pues segn ATMEL, slo es un nombre que se sacaron de la manga. Algunos dicen que significa Advanced Virtual RISC. Otros dicen que lleva las iniciales de los inventores de los AVR: Alf Egil Bogen and Vegard Wollan... AlfVegardRisk. Ya saben Reduced Instruction Set Computer es lo de RISC. Paso 2 Bajen el compilador de AVR, el AVR Studio. http://www.atmel.com/dyn/products/tools.asp?family_id=607 Si el link cambia slo busquen el AVR Studio ms reciente en la pgina de ATMEL. Paso 3 Para que sepan de que estamos hablando, bajen la hoja de caractersticas del AT90S1200. http://www.atmel.com/dyn/resources/paso 2 prod_documents/DOC0838.PDF Sera bueno que imprimieran las pginas del set de instrucciones, del espacio de I/O y del sumario de bits de registros. Paso 4 Bajen un generador de subrutinas de tiempo para AVR http://www.home.unix-ag.org/tjabo/avr/AVRdelayloop.html Por ahora slo dar una explicacin bsica del 1200. Comparar al ATMEL AT90S1200, que es un AVR muy popular y al MICROCHIP PIC16F84... se puede decir que son los ejemplos bsicos de comparacin. No. de instrucciones AVR: 89 PIC: 35 Registros AVR: 32 registros PIC: 68 RAM Velocidad AVR: 12MIPS (12MHz) PIC: 20MHz en donde c/inst. toma 4 ciclos de reloj en promedio

Memoria de programa AVR: 1kByte FLASH (512 lneas de programa, 16bits por inst.) PIC:1kx14 EEPROM AVR: 64B PIC: 64B Salidas AVR: 15 salidas PIC: 13 salidas TIMER AVR: 1 de 8bit (preescala desde CK hasta CK/1024) PIC: 1 de 8 bit (preescala desde 1:2 hasta 1:256) Comparador analgico (NO convertidor analgico) AVR: 1 PIC: NO Watchdog Ambos Oscilador interno Ambos, en el AVR slo habilitable con programacin paralela Niveles de pila (STACK) AVR: 3 PIC: 8 Interrupciones AVR: reset, int. externa, timer y por comparador analgico PIC: slo me acuerdo de que son 5 jeje Antes de empezar les explico algo bsico... en los AVR se tienen 3 registros para cada puerto de salida: DDRB - Sirve para decir que patitas son de entrada o salida, 0 es entrada, 1 es salida, es inverso a los pics PINB - Registro que sirve para entradas nadams PORTB - Registro que sirve de salidas nadams Es decir si leen, vyanse con PINB; si escriben vyanse a PORTB. Las terminales del AVR AT90S1200 son:

El PortB tiene 8 bits de datos, a diferencia del PORTD que tiene slo 7. El bit 7 del PORTD no sirve ; PORTD tambin consta de 3 registros: DDRD, PORTD y PIND. Programa de salidas en puerto B

Ahora el programa slo ser un ejemplo de cmo declarar salidas en puerto B, cada segundo se incrementa un conteo binario en portb. -----------------------------------------------------.include "1200def.inc" ;librera de definiciones de registros y dems cosas ser r16 ;SER pone a uno todos los bits del Registro 16 out ddrb,r16 ;saca R16 a DDRB, los 1 son salidas, los 0 son entradas ; que es contrario a los PIC, todo B es salida clr r16 ;pone a ceros todo r16 ciclo: inc r16 ; r16 ++ out portb,r16 ;pone r16 en portb, es decir en patitas del avr rcall retardo ;llama subrutina de 1 segundo rjmp ciclo ;salto incondicional a ciclo ; ============================= ; delay loop generator ; 4000000 cycles: es decir 1 segundo con xtal de 4MHz ; ----------------------------; delaying 3999996 cycles: retardo: ldi R17, $24 WGLOOP0: ldi R18, $BC WGLOOP1: ldi R19, $C4 WGLOOP2: dec R19 brne WGLOOP2 dec R18 brne WGLOOP1 dec R17 brne WGLOOP0 ; ----------------------------; delaying 3 cycles: ldi R17, $01 WGLOOP3: dec R17 brne WGLOOP3 ; ----------------------------; delaying 1 cycle: ret ; ============================= --------------------------------------------------------------------------------

Programa de control de una LCD 16x2 Ahora les dejo un programa ms avanzado, en el que se hace uso de una LCD 16x2 y en ella se muestra un conteo de 0 a 9 usando el AVR. Antes de seguir les hago una recomendacin, siempre trabajen registros desde el nmero 16 hasta el 31, ya que estos pueden ser trabajados con direccionamiento inmediato. Luego les dir que onda con los otros del 0 al 15. En el programa se ven instrucciones nuevas: LDI R16,$38 Esta instruccin carga de modo inmediato el valor hexa 38 en el registro 16. Si quisieran cargar el dato decimal 10, slo pongan: LDI R16,10 MOV R16,R20 Aqu el valor del R20 pasa al R16. CPI R20,$3a Hace una comparacin inmediata mediante una resta: R20 - 3A. Esto levanta banderas en el registro STATUS. BRNE loop Branch if Not Equal. Brinca si no es igual, es decir, si Z=0; en ese caso se va a loop. CBI PORTD,0 Clear Bit, pone a cero un bit de algn registro de entrada/salida. En este caso pone a cero el bit cero. Es importante que CBI y SBI slo se usen en registros de entrada/salida que estn en el rango de 00 a 1F, ya que en los dems no funcionan. Para modificar el contenido de los dems, sera conveniente usar un LDI a algn registro y luego un OUT hacia el registro e/s. Bueno, pues les dejo el cdigo: -------------------------------------------------------;MigSantiago ;Contador de 0-9 en LCD de 16x2 ;RB0-RB7 son DB0-DB7 ;RD0 es RS ;RD1 es E ;R20 conteo ASCII ;R17,18,19 Subrutinas tiempo .org 0000 .include "1200def.inc"

;Establece E/S SER R16 OUT DDRB,R16 ;portb salida OUT DDRD,R16 ;portd salida RCALL unseg ;espera inicio de LCD 1seg ;Configura LCD LDI R16,$38 RCALL instru ;8-bit,2 lneas, 5x7 LDI R16,$0e RCALL instru ;D=1,C=1,B=0 LDI R16,$06 RCALL instru ;incremento, no desplaza texto LDI R16,$01 RCALL instru ;limpia LCD ;Escritura de 0-9 cero: LDI R20,$30 ;cero en ASCII loop: MOV R16,R20 ;prepara conteo ASCII a mandar RCALL dato ;manda ASCII a LCD RCALL unseg ;espera 1 seg LDI R16,$80 ;va a home RCALL instru INC R20 CPI R20,$3a ;si es 3a se va a cero BRNE loop RJMP cero ;Subrutina: instruccin a LCD instru: CBI PORTD,0 ;RS=0 RJMP envio ;Subrutina: dato a LCD dato: SBI PORTD,0 ;RS=1 RJMP envio ;Subrutina: enva dato o inst a LCD envio: SBI PORTD,1 ;E=1 OUT PORTB,R16 ;Saca R16 por B RCALL dosms ;espera 2ms escritura CBI PORTD,1 ;E=0 RCALL dosms ;espera proceso RET ;Subrutina de 2ms ; 8000 cycles: ; ----------------------------; delaying 7998 cycles: dosms: ldi R17, $1f

WGLOOP0: ldi R18, $55 WGLOOP1: dec R18 brne WGLOOP1 dec R17 brne WGLOOP0 ; ----------------------------; delaying 2 cycles: nop ret ; ============================= ;Subrutina de 1seg ; 4000000 cycles: ; ----------------------------; delaying 3999996 cycles: unseg: ldi R17, $24 WGLOOP3: ldi R18, $BC WGLOOP4: ldi R19, $C4 WGLOOP5: dec R19 brne WGLOOP5 dec R18 brne WGLOOP4 dec R17 brne WGLOOP3 ; ----------------------------; delaying 3 cycles: ldi R17, $01 WGLOOP6: dec R17 brne WGLOOP6 ; ----------------------------; delaying 1 cycle: ret ; ============================= --------------------------------------------------------

Programa para uso de teclado de matriz de 4x4 Ahora les va un programa que lee la presin de una tecla en un teclado 4x4. Les pongo un poco de teora respecto al teclado y cmo est conectado. Una buena manera de ahorrar lneas de entrada al micro es, en lugar de dedicar una lnea exclusiva por cada tecla utilizada, emplear un teclado matricial. El teclado matricial se caracteriza por estar cada una de las teclas conectada a dos lneas (una columna y una fila)

que la identifican. De este modo el nmero de teclas que pueden conectarse es el producto de filas por el de columnas.

La tcnica de programacin requiere tanto de entradas como de salidas. Las filas estn conectadas a las patillas de salida y las columnas a las de entrada. Se comienza el testeo colocando a 0 la primera fila, y a 1 las restantes. Si la tecla pulsada estuviese en la columna 0, sta colocara en su lnea un 0 lgico. Bastar con hacer un muestreo de las columnas, buscando el 0, para saber la tecla exacta que fue pulsada en la matriz. Si no es pulsada ninguna tecla en una fila, las entradas se encuentran en estado flotante, razn por la que son necesarias las resistencias de polarizacin internas, que mantienen las entradas a nivel alto. En nuestro caso, yo conect las resistencias a tierra. Por lo tanto, lo que se busca es un UNO en las lneas de entrada. Las instrucciones nuevas que este programa tiene son: sbic pinb,5 Brinca la siguiente instruccin si el bit 5 del puerto B est en CERO. SI fuera sbis, brinca la sig. inst. si el bit 5 del port b est en UNO. Es importante decirles que los AVR at90s1200 tienen slo 3 saltos a subrutina. Este programa que escrib no tiene ni un slo salto a subrutina, as que si lo van a implementar en otro programa en dnde hagan uso de un teclado pues slo llamaran a la lectura del teclado y gastaran un nivel de pila. El programa es: --------------------;programa teclado 4x4 rapid switch ;pb0, pb1, pb2, pb3 Salidas matriz ;pb4, pb5, pb6, pb7 Entradas matriz ;pd0, pd1, pd2, pd3 Salidas LEDS ;pd4 salida estado tecla presionada (E) ; pb4 pb5 ; | | | | ;pb0 -> 0 ;pb1 -> 4 ;pb2 -> 8 pb6 pb7 1 2 3 5 6 7 9 a b

;pb3 -> c d e f .include "1200def.inc" SER OUT LDI OUT R16 ;FF DDRD,R16 ;PtoD Salida R16,$0F ;00001111 DDRB,R16 ;PtoB 4sal 4ent

clr r16 out PORTD,r16 ;borra PtoD OUT PORTB,r16 ;borra PtoB inicio: clr r16 clr r17 ;Registro mandado a ptoD clr r18 ;registro del contador de barrido clr r19 ;indicador de lnea actual de barrido linea1: ldi r16,$01 out portb,r16 ;rb0=1 lnea 1 activa rjmp barrido ;va a checar presin de tecla linea2: inc r19 inc r18 ;en subrutina barrido, la primer lnea ;no hace incremento, por eso se ;incrementa aqu ldi r16,$02 out portb,r16 ;rb1=1 lnea 2 activa rjmp barrido linea3: inc r19 ;incrementa indicador de lnea inc r18 ldi r16,$04 out portb,r16 ;rb2=1 lnea 3 activa rjmp barrido linea4: inc r19 ;incrementa indicador de lnea inc r18 ldi r16,$08 out portb,r16 ;rb3=1 lnea 4 activa rjmp barrido nopresion: clr r16 ;pon E y LEDS a cero out portd,r16 ;no hubo presin rjmp inicio barrido: sbic pinb,4 ;si rb4=0 no hay presin rjmp presion inc r18 ;siguiente tecla sbic pinb,5

rjmp presion inc r18 ;siguiente tecla sbic pinb,6 rjmp presion inc r18 ;siguiente tecla sbic pinb,7 rjmp presion rjmp quelinea ;no hubo presin en X lnea presion: mov r17,r18 ;r17=r18 out portd,r17 ;saca tecla y E por portd sbi portd,4 ;pd4=1 es decir E=1 rjmp inicio ;que ya no haga barrido quelinea: cpi r19,$00 ;determina en que lnea de barrido va breq linea2 ;va a lnea 2 cpi r19,$01 breq linea3 cpi r19,$02 breq linea4 cpi r19,$03 breq nopresion ;se va a limpiar ptod -----------------------------

Al final lo que hace el programa es determinar si se presion una tecla. Si se presion, enciende la salida E (pd4) y saca la tecla por pd0, pd1, pd2, pd3. Si se presionara el CERO slo encendera E y pd0, pd1, pd2, pd3 estaran apagadas. Si se presionara la tecla F encendera E y todas las dems: 1111 = 15 = F. Declaracin de variables No uso la declaracin de variables para los registros del AVR, pero les explico unas directivas para usarlas: Si quieres definir pines: .equ RxD =0; En este caso el pin 0 se llama RxD .equ TxD =1; En este caso el pin 1 se llama TxD Si quieres renombrar registros: .def contbit =R16 def temporal =R17 Y se usan normalmente: cbi PORTD,TxD; el pin 1 se pone a cero ldi contbit,$aa; Carga el R16 con AA Programa con interrupcin externa Ahora entremos con las interrupciones. Les presento un programa que hice muy bsico sobre la interrupcin externa. La aplicacin que le di fue generar un nmero aleatorio (random) para obtener la lectura de un dado, es decir, un nmero que fuera 1, 2, 3, 4, 5 6 al momento en que uno aprieta un botn. Hay registros que habilitan las interrupciones: GIMSK - Tiene el bit INT0, el cul al estar en 0 deshabilita la interrupcin externa. Si est en 1 pues la habilita. MCUCR - Slo interesan los bits ISC00 y ISC01. Sirve para decir que flanco es el que dispara la int. ext. Los otros pnganlos a cero.

ISC01 ISC00 0 0 LOW 0 0 1 reservado 1 0 flanco derecho 1 1 flanco izquierdo STATUS - La bandera I habilita el llamado a interrupcin en general. La instruccin SEI habilita el bit I de status.

Ahora les pongo una imagen de cmo conectar los 7 leds en un arreglo que simule los puntos de un dado real:

Los AVR tienen un vector de interrupcin nico para cada interrupcin: 0x00 RESET 0x01 Interrupcin externa (GIMSK) 0x02 TIMER, OVF0 (TIMSK) 0x03 ANA_COMP Para cada interrupcin el contador de programa va a caer en un vector en especfico. El avr va a estar incrementando R17 hasta que llegue la presin del botn, sale del loop infinito y adecua el estado de R17 para convertirlo a una salida de 1 a 6 en el dado. Para regresar de una interrupcin hay que usar RETI para que regrese al programa normal y rehabilite I en status. ;dado electrnico hecho con interrupcin externa ; B0 B1 B2 B3 B4 B5 B6 B7 ; 1 2 3 4 5 6 7 NC ; ;MigSantiago ; _______ ; 1|O 4 O|5 ; 2|O O O|6 ; 3|O O |7 ; ------;PD2 Push Button a tierra con r pull-up .include "1200def.inc" rjmp inicio rjmp int_ext nop nop inicio: ser r16 out ddrb,r16 ;ptob salida out gimsk,r16 ;habilita int. externa ldi r16,$03 out mcucr,r16 ;flanco izquierdo activa interrupcin sei ;activa interrupciones random: inc r17 ;inc. random r17

rjmp random int_ext: rcall rebote ;espera rebote de push button andi r17,$07 ;filtra 5 primeros bits a cero cpi r17,$00 ;si hubo cero saca 1 breq sacauno cpi r17,$01 ;si hubo 1 saca 1 breq sacauno cpi r17,$02 ;si hubo 2 saca 2 breq sacados cpi r17,$03 breq sacatres cpi r17,$04 breq sacacuatro cpi r17,$05 breq sacacinco cpi r17,$06 breq sacaseis cpi r17,$07 ;si hubo 7 saca seis breq sacaseis sacauno: ldi r16,$08 ;prende 4 sacadado: out portb,r16 reti sacados: ldi r16,$41 ;prende 1 y 7 rjmp sacadado sacatres: ldi r16,$49 ;prende 1, 4 y 7 rjmp sacadado sacacuatro: ldi r16,$55 ;prende 1,3,5,7 rjmp sacadado sacacinco: ldi r16,$5d ;prende 1,3,4,5,7 rjmp sacadado sacaseis: ldi r16,$77 ;prende 1,2,3,5,6,7 rjmp sacadado ; delay loop generator ; 800000 cycles: ; ----------------------------; delaying 799995 cycles: rebote: ldi R20, $5F WGLOOP0: ldi R18, $17 WGLOOP1: ldi R19, $79 WGLOOP2: dec R19 brne WGLOOP2 dec R18 brne WGLOOP1

dec R20 brne WGLOOP0 ; ----------------------------; delaying 3 cycles: ldi R20, $01 WGLOOP3: dec R20 brne WGLOOP3 ; ----------------------------; delaying 2 cycles: ret ; ============================= Es importante que acomoden bien los LEDs para que le encuentren forma a las salidas del dado. Programa con interrupcin por timer cada segundo Bueno, ya que estn medio familiarizados con las interrupciones les dejo un programa que genera una salida binaria cada segundo usando interrupciones: -------------------------------------------------------------------------------;Programa que incrementa conteo binario ;en PtoB cada segundo usando interrupcin ;por timer ;CK/64 tiempo mnimo=16us ;4ms/16us=250 conteos ;256-250=6 -> TCNT0 ;4ms x 250conteos= 1s .include "1200def.inc" rjmp main nop rjmp timer main: clr r17 ;pone a cero salida a ptoB clr r25 ;pone a cero contador 4ms ser r16 out ddrb,r16 ;ptoB de salida out timsk,r16 ;habilita int. por timer ldi r16,6 out tcnt0,r16 ;manda el 6 a timer sei ;habilita I en SREG ldi r16,$03 out tccr0,r16 ;011 en escala: CK/64 ciclo: nop ;pasa el tiempo rjmp ciclo

timer: inc r25 ;inc. conteo de 4ms cpi r25,$fa ;250d = fah breq increm ;se va a inc. ptoB pon_conteo: ldi r16,$06 out tcnt0,r16 ;comienza tiempo 4ms otra vez reti ;regresa de interrupcin ;habilitando I en SREG increm: inc r17 ;inc conteo en ptoB out portb,r17 ;saca conteo clr r25 ;borra conteo de 4ms rjmp pon_conteo --------------------------------------------------------------------------------

Les explico los registros del TIMER: TIMSK - Habilita la interrupcin por sobreflujo del contador TCNT0 TIFR - Es la bandera que dice si hubo sobreflujo del TCNT0 TCCR0 - Aqu uno da las escalas de divisin de TCNT0 TCNT0 - Aqu se lleva la cuenta En TCCR0 Se tiene CS02, CS01 y CS00 los cuales indican la escala y el funcionamiento del Timer, los datos que llevan son CS02, CS01 y CS00 respectivamente: *Cristal de 4MHz 000 - stop, no cuenta 001 - CK, la escala es igual al cristal que uno le ponga (0.25us por conteo y 4MHz) 010 - CK/8 (2us) 011 - CK/64 (16us) 100 - CK/256 (64us) 101 - CK/1024 (256us) 110 - Flanco derecho en patita T0 PD4 111 - Flanco izquierdo en T0 R25 va a contar 250 veces el desbordamiento del timer. El timer se va a desbordar cada 4ms ya que se us CK/64. R16 lleva un 6 para que el conteo se haga 250 veces. 16us x 250 (r16) = 4ms 4ms x 250 (r25) = 1000ms

Trabajando los registros 16 a 31 Antes de explicarte, por favor baja este archivo de Atmel: http://www.atmel.com/dyn/resources/prod_documents/DOC0856.PDF

Este archivo trae las explicaciones de cada cdigo de operacin de la familia de 8bit de AVRs. Trae instrucciones que los AT90S1200 no incluyen, pero a esas no les hagas caso, slo estudia las que trabaja el 1200. Ya que tengas el archivo checa la pgina 16 por ejemplo. Ah viene explicada bien la instruccin ADC (Suma con acarreo) por ejemplo. Abajo dice que los registros que maneja esta instruccin son 0 < d < 31, 0 < r < 31 (menor o igual) Ahora checa la pgina 20. Ah se explica la operacin ANDI (AND inmediata). Los registros que ella trabaja son 16 < d < 31, 0 < K < 255 (K es el nmero a poner en la AND) Porqu? No te puedo dar una respuesta exacta, pero tiene que ver con el modo de direccionamiento del AVR. Cada instruccin tiene lmites de trabajo con los registros, siempre hay que checarlas. Te recomiendo que leas las instrucciones en las que ests interesado.

Eso es todo por mi parte. Este es un curso muy breve que se basa en conocimientos que el lector ya tenga sobre lenguaje ensamblador. Si buscas un programador para este AVR te recomiendo entres a http://www.atmel.com y hagas una bsqueda. Ah encontrars programadores muy sencillos y el software para trabajarlos.

You might also like