Story Transcript
Tema 5. Temporizadores e interrupciones 5.1. Temporizadores A y B. Modos de funcionamiento. El módulo temporizador (timer) es imprescindible en cualquier sistema microcontrolador. Se utiliza siempre que se quiera controlar a la variable tiempo. En el M16C/62A se disponen de 11 temporizadores de 16-bits cada uno, etiquetados como temporizadores A (5 de ellos) y temporizadores B (6). Todos los temporizadores trabajan de forma independiente. Los temporizadores A tienen 4 modos de funcionamiento: 1. Modo temporizador, en el que se realiza la cuenta desde una fuente interna, el reloj. 2. Modo contador de eventos, en el que se realiza la cuenta o bien desde una fuente externa o por desbordamiento de otro temporizador. 3. Modo un-disparo (one-shot), en el que la cuenta se para al llegar a cero. 4. Modo modulador de la anchura de pulso (Pulse Width Modulation. PWM), en el que la anchura de pulso puede ser modificada. El modo de funcionamiento del temporizador se fija en el registro de modo de funcionamiento TAiMR (con i=0...4), definido en la dirección del área SFR (Special Function Registers) (figura 5.1). 7 TAiMR
(Dirección: 0396H … 039AH)
TCK1 TCK0
MR3
MR2
MR1
0
MR0 TMOD1 TMOD0
Después de un reset, se inicializa con 00H. Se tiene permiso de lectura y escritura.
TMOD1, 0: Bits de selección del modo de funcionamiento. El modo temporizador se selecciona con 00, contador de eventos con 01, un disparo con 10 y PWM con 11.
MR3, 2, 1, 0: La función varía según el modo de funcionamiento. Para el modo temporizador: MR0 selecciona la polaridad del pulso de salida. Cuando MR0 es 0, cada vez que se desborde el temporizador se invierte la polaridad de la salida TAiOUT. MR2, 1 fijan el comienzo y la parada de la cuenta: cuando es 11, el comienzo y la parada de la cuenta se hace cuando TAiIN esté en alto “HIGH”, para 10 en bajo “LOW”, y para 0X no se activa. MR3 siempre debe ser cero.
TCK1, 0:
Por ejemplo:
Bits de selección de la fuente interna de cuenta, el reloj. La función varía según el modo de funcionamiento. Para el modo temporizador: 00: Cuenta con el reloj f1 (16 MHz para M16C/62A y 10 Mhz para M16C/60) 01: Divisor por 8, f8 10: Divisor por 32, f32 11: Divisor por 32 usando el sub-reloj, fc32.
mov.b #80H, TA0MR
; fija el modo temporizador de TA0 con reloj de f32
Figura 5.1. TAiMR: Registro de modo de funcionamiento de los temporizadores tipo A.
El valor inicial de la cuenta se fija en el registro TAi de 16 bits, que en el caso del temporizador A0, ocupa la dirección del área SFR: 0386H. Por ejemplo: mov.w #1000, TA0 ;inicializa el valor de cuenta del temporizador A0
El disparo del temporizador se lleva a cabo poniendo a uno el bit correspondiente a cada temporizador del registro de comienzo de cuenta, TABSR (figura 5.2). 7 TABSR
TB2S
0
(Dirección: 0380H)
TB1S
TB0S TA4S
TA3S TA2S
TA1S
TA0S
Después de un reset, se inicializa con 00H. Se tiene permiso de lectura y escritura.
TBiS y TAiS: Bit individuales para comenzar la cuenta de cada temporizador. Notad que para el MSA0600 y puesto que sólo hay 8 temporizadores sólo se necesita este registro, para el M16C/62PU se necesitan dos registros para los 11 temporizadores. con 0 se para la cuenta y con 1 se comienza la cuenta. Por ejemplo: bset TA0S
; comienza la cuenta
Ver registros ONSF y UDF
Figura 5.2. TABSR: Registro de comienzo de cuenta de los temporizadores A y B.
La comprobación de que la cuenta del temporizador (fijada en TAi) ha terminado (ha llegado a 0000H), se lleva a cabo en el registro de control de interrupción TAiIC, que se encarga de realizar una interrupción hardware. El usuario debe testar el bit de este registro correspondiente al temporizador utilizado. Por ejemplo: btstc 3, TA0IC ; comprueba la interrupción hardware de fin de cuenta del temporizador A0.
DISEÑO BASADO EN MICROCONTROLADORES. Curso 2004-2005 TEMA 5. TEMPORIZADORES E INTERRUPCIONES. (6 horas) PRÁCTICA 2. Control del parpadeo de un diodo y conexión de un altavoz para oír diversos tonos. Tiempo estimado: 2 horas teoría + 4 horas prácticas. Fecha de realización: 4, 5 y 6 de abril. Entrega de prácticas: 12 de abril.
Objetivos: - Trabajar con los puertos E/S y el temporizador A0 (TA0, TA0MR, TA0S y TA0IC). - Controlar las interrupciones del temporizador y conocer las limitaciones del miniemulador.
Enunciado:
PARTE 1: Parpadeo de un diodo LED Coloca en la regleta el diodo y una resistencia:
+ ÁNODO
CÁTODO
+ 1.- Realiza un programa para hacer parpadear el diodo a intervalos de 1 segundo. Con la ayuda del osciloscopio determina su frecuencia de encendido/apagado y compárala con la que debes obtener del programa. 2.- Modifica el programa para que el tiempo en on del diodo sea de 2 segundos y en off de 3 segundos, y que se repita 10 veces. Es posible o te lo impide el sistema de desarrollo. ; Enciende/Apaga el diodo cada segundo ;----- definición de símbolos MSA600 ---------------------------------------; VramTOP .equ 000400h ; inicio de la RAM interna VramEND .equ 002BFFh ; final de la RAM interna VIstack .equ 002C00h ; Direccion de la cima de la pila stack pointer VprogTOP .equ 018000h ; inicio del area de programa Vintbase .equ 01FD00h ; inicio tabla de interrupciones variable Vvector .equ 01FFDCh ; inicio tabla de interrupciones fija SB_base .equ 000380h ; Base del direccionamiento SB relativo ;
;----- sección de datos en RAM interna (no usada) ----------------------; .section memory,data .org VramTOP ; ;----- sección de codigo ----------------------.section prog,code .org VprogTOP ; .sb SB_base ; Establece SB_base para direccionamiento relativo ; .sbsym data ; Establece data para que su dirección efectiva ; se calcule con direccionamiento SB relativo ; ;----- inicialización de registros y limpieza de la RAM--------------------------------------------; reset: ldc #VIstack,ISP ; inicializa registro Interrupt Stack Pointer ldc #SB_base,SB ; inicializa registro SB ldintb #Vintbase ; establece la base de la tabla de interrupciones ; mov.w #0,R0 mov.w #(VramEND+1-VramTOP)/2,R3 mov.w #VramTOP,A1 sstr.w ; ;----- inicialización de temporizador y puertos ---------------------------------------------; bset PD8_0 ; P8_0 salida (Está asociado al diodo rojo del MSA0600) ; mov.b #80h,TA0MR ; TA0 en modo timer con f32 mov.w #625,TA0 ; 625 periodos de 3200ns= 2 ms. (el reloj es de 10MHz) bset TA0S ; arranca el contadort ; ;----- programa principal --------------------------------------------; main: mov.w #0,r0 ; r0 cuenta de periodos de 2 ms. retraso: btstc 3,TA0IC ; Interrupción del TA0 (2msec)? jnc retraso add.w #1,r0 ; r0 = r0+1 cmp.w #500,r0 ; r0=500? jnz retraso bnot P8_0 ; cambia la polaridad del diodo jmp main ; ;----- interrupción de reset --------------------------------------------; .section int_reset,romdata .org Vvector+(8*4) .lword reset ; ;----- program end ---------------------------------------------; .end ;
PARTE 2: Música. Conecta el altavoz en la extensión del P8_0 y comprueba si suena/no_suena cada segundo. Tened en cuenta que la frecuencia de resonancia es de 600 Hz, y el margen efectivo de frecuencias de 450 Hz a 8 KHz. 3.- Realiza un programa en el que se alternen cada 3 segundos el encendido del diodo y el sonido de un tono. Puedes elegir el puerto que quiera, pero cuidado con las limitaciones de los puertos de E/S. Descríbelas. 4.- Como ampliación de la práctica, te propongo que elabores códigos de programa para sintetizar fragmentos de tu canción preferida. Este fragmento lo realizaron alumnos de
años anteriores. Consulta, compara y analiza (documenta los códigos) el fichero musica.a30 disponible en la Web de la asignatura. ;**************************************************************** ;* Código de Mitsubishi ;* Canción: "Para Elisa" de Beethoven ;* Antonio Blanco Oliva ;* Jacob Mariscal Fernández ;* Karim Rahimpur ;**************************************************************** ; ;----- Incluye archivo sfr.inc -------------------------------------; .list off .include sfr.inc ; o bien sfr62a.inc(compatible 100%) .list on ; ;----- Definici¢n de Simbolos MSA600---------------------------------------; VramTOP .equ 000400h VramEND .equ 002BFFh VIstack .equ 002C00h VprogTOP .equ 018000h Vintbase .equ 01FD00h Vvector .equ 01FFDCh SB_base .equ 000380h ; ;----- Secciones datos/programa ----------------------------------; .section memory,data .org VramTOP ; num: .blkw 2 ; .org 700h data: .blkw 500 ; .section prog,code .org VprogTOP .sb SB_base .sbsym num ; ; ;----- limpieza de la RAM --------------------------------------------; reset: ldc #VIstack,ISP ldc #SB_base,SB ldintb #Vintbase ; mov.w #0,R0 mov.w #(VramEND+1-VramTOP)/2,R3 mov.w #VramTOP,A1 sstr.w ; ;----- inicializa puertos 6 y 7 de salida y 8 y 9 de entrada (no son usadas); mov.w #0FFFFh,PD6 mov.w #0FFEFh,P6 mov.w #0,PD8 ; mov.b #80h,TA0MR ; mov.w #0AAAAh,TA0 ; cuenta a 43690 (0.14 seg.) mov.b #7,TA0IC mov.b #04h,TA4MR ; timer A4 con f1 y salida por pin TA4OUT (P8_0) mov.w #0,TA4 ; Nota inicial: Silencio mov.b #11h,TABSR ; Arranca los timers A0 y A4 ; fset I ; Activa las interrupciones de los temporizadores ; ;----- main program --------------------------------------------; main: jsr data_set ; Realiza la copia a RAM de la canción ?: jmp ?; Bucle infinito ;
; ;----- music data set (descifra el código y coméntalo) -------------------; data_set: mov.w #0,r0 mov.w #0,r3 mov.w #0,a1 lde.w music1_count,r2 mov.w r2,num shl.w #1,num loop: mov.w a1,a0 lde.w music1_data[a0],r1 movhl r1h,r0l jsr ram_store movll r1h,r0l jsr ram_store movhl r1l,r0l jsr ram_store movll r1l,r0l jsr ram_store add.w #2,a1 sbjnz.w #1,r2,loop rts ; ram_store: push.w a1 mov.b r0l,a0 shl.w #1,a0 lde.w sound_data[a0],a1 mov.w r3,a0 shl.w #1,a0 mov.w a1,data[a0] add.w #1,r3 pop.w a1 rts ; ;----- manejador de la rutina de interrupción -----------------; sound: push.w a0 mov.w num+2,a0 mov.w data[a0],TA4 add.w #2,num+2 cmp.w num,num+2 jne ?+ mov.w #0,num+2 ?: pop.w a0 reit ; ;----- Datos de la música ------------------------------------; music1_count: .word 170 music1_data: .word 04343h,04832h,07709h,0B788h,00BD8h .word 0220Bh,04343h,04832h,07709h,0B788h .word 00B28h,07708h,02344h,04D54h,0333Ch .word 04322h,02B32h,08800h,0BB44h,00044h .word 01103h,04343h,04832h,07709h,0B788h .word 00BD8h,0220Bh,04343h,04832h,07709h .word 0B788h,00B28h,07777h,00000h,00000h ; ;----- Tabla con los periodos de oscilación de cada nota -----------------------; sound_data: .word 00000h,04F34h,04AA9h,04280h ; --,Si (nota B4, 493,2Hz),Do,Re .word 03B41h,037EEh,031D3h,02C63h ; Mi,Fa,So,La (440Hz) .word 029FEh,02554h,02140h,01DA0h ; Si,Do,Re,Mi .word 01BF7h,018E9h,01631h,013CDh ; Fa,So,La,Si ; ;----- vector table (21 entradas necesarias)-----------------------------; .section uniter,romdata .org Vintbase+(4*21) .lword sound
; .section .org .lword
inter,romdata Vvector+(8*4) reset
; ;----- program end --------------------------------------------; .end ;
Notas de aclaración: -
-
-
La canción se almacena en memoria RAM interna, y es una tabla con los valores de cuenta que hay que suministrar al temporizador para cada una de las notas de la canción. Cada nota de la canción se especifica con un nibble, por lo que se dispone de 16 notas distintas (ver tabla sound_data). Por ejemplo, la nota Si de la cuarta octava debe tener una frecuencia de 493,2 Hz aproximadamente. Para conseguirlo, se calcula su periodo como 1/493,2 Hz=0,002027575 seg = 2027575 ns. Puesto que la señal de reloj es de 10 MHz, 100 ns. de periodo, se establece la cuenta en 20276, es decir 4F34h. Esto se repite para todas las demás notas. El tempo de la canción se gobierna por el temporizador TA0, con señal de reloj f32 (3200 ns.). Como la cuenta que realiza es 0AAAAh (43690), da una duración de 3200ns * 43690 = 0,14 seg., aproximadamente. Sería posible tocar notas más largas tocando varias notas cortas seguidas, pero sólo como múltiplos de 0,14 seg. Cuando pasan 0,14 seg. el TA0 provoca una interrupción y se cambia el periodo de oscilación del otro temporizador (TA4) para que toque la nota. Después se entra en bucle y se repite la melodía indefinidamente. Cada nota tiene 4 bits y la canción está almacenada a 2 notas por byte. La traducción de la canción se realiza leyendo palabras de 16 bits, por lo que hay un número de notas múltiplo de 4, incluyendo los silencios.