Título: Dudas para crear temporizador en ensamblador
Publicado por: Fox_Neo en 20 Marzo 2013, 10:15 am
Hola quiero crear un temporizador con el PIC P16F886, de 0,5 segundos de pulso osea con una frecuencia de 1Hzy no se como programarlo , tengo la idea pero no se plasmarlo en emsalblador. Os explico: Voy a usar el oscilador interno del PICde 4MHz lo que es lo mismo con un periodo de 0,25us si una instruccion tarda 4 ciclos de reloj, cada instrucción tarda en ejegutarse 1us. Tengo que conseguir que oscile a 0,5s--> 500.000us para ello quiero poner el TMR0 inicialmente a 250 y el preescale a 8 con lo que el TMR0 se desborda cada 2000us (250*8=2000). Si con un contador cuento 250 vecesda 0,5 s (2000us*250=500.000us=0.5s). Lo que no se hacer o que no entiendo como se le da la orden de que empie a contar otra cosa que no entiendo es que al ir comparando el valor del contador cuenta como un tiempo de instrucción por tanto ya se retrasaria, no se tengo un cacao muy grande, se que tengo cuando se supere el desbordamiento del TMR0 cada 2000us tengo que poner el bit TI0IF del registro INTCON mediante programa a 0.
Aqui os dejo un diagrama de como creo que funciona: (http://s2.subirimagenes.com/otros/previo/thump_8365894untitledu.jpg) Gracias
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Meta en 20 Marzo 2013, 14:35 pm
Hola:
Si le interesa usar retardos, aquí hay información.
http://electronica-pic.blogspot.com.es/2012/02/retardos-para-pic12f-16f-y-18f.html
Saludo.
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Fox_Neo en 20 Marzo 2013, 23:30 pm
Gracias Meta por la ayuda, umm lo único que he sabido hacer es configurar los puertos:
;***** CONFIGURACIÓN ****************************************************** List p=16F886 ;Tipo de procesador include "P16F886.INC" ;Definiciones de registros internos ;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados ;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades __config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF ;Palabra 1 de configuración __config _CONFIG2, _WRT_OFF&_BOR40V ; _MCLRE_ON: Reset externo ACTIVADO. ; _CP_OFF: Protección del código DESACTIVADO. ; _WDT_OFF: Watchdog DESACTIVADO. ; _IntRC_OSC: Oscilador interno de 4MHz. ;***** DEFINICIÓN DE VARIABLES ; Definimos las posiciones de memoria de los datos CONTADOR equ 0x10 ;************************************************************************** ; Inicialización del programa: ; Origen Org 0x00 goto Inicio ;Vector de reset org 0x05 ; Configuración de los puertos como entradas y salidas Inicio clrf PORTB ; Borrado de los biestables de salida bsf STATUS,RP0 ; Selecciona banco 3 (RP0=RP1=’1’) bsf STATUS,RP1 clrf ANSEL ; El puerto A de tipo digital clrf ANSELH ; El puerto B de tipo digital bcf STATUS,RP1 ; Selecciona banco 1 (RP1=’0’ RP0=’1’) clrf TRISB ; RB7:RB0 se configuran como salidas movlw b'00111111' movwf TRISA ; RA5:RA0 se configuran como entrada movlw b'00000110' ;movemos el valor de la opción del preescale al registro W movwf OPTION_REG ;pasamos el valor de w al registro bcf STATUS,RP0 ; Se vuelve al banco 0 movlw b'00000111' ;movemos el valor de la opción del preescale al registro W movwf INTCON ;
ya más no se estoy bastante perdido :S Gracias[/size]
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Meta en 21 Marzo 2013, 01:33 am
Hola: Aquí encontré un ejemplo sencillo. ;El Timer 0 TMR0. ; ;Se trata de comprobar el funcionamiento básico del Timer 0. Cuando se detecta un flanco ;decendente en RA0 (conectada con un pulsador), se activa la salida RB0 durante un tiempo ;y luego se desconecta. El TMR0 realiza una temporización de 50mS que se repite tantas veces ;como se indique en la variable "Temp". Así pues la temporización total será de 50mS*Temp. ; ;Suponiendo una frecuencia de trabajo de 4MHz, 4Tosc=1uS. Trabajando con un prescaler de 256, ;al TMR0 hay que cargarlo con 195 para temporizar 50mS (Temporización=1uS*195*256) List p=16F886 ;Tipo de procesador include "P16F886.INC" ;Definiciones de registros internos ;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados ;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades __config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF&_BOR_OFF ;Palabra 1 de configuración __config _CONFIG2, _WRT_OFF&_BOR40V ;Palabra 2 de configuración Valor equ .20 ;Constante para temporizar 1 seg (50mS*20) Temp equ 0x020 ;Variable para la temporización org 0x00 ;Vector de RESET goto Inicio org 0x05 ;********************************************************************************************* ;Delay: El Timer 0 realiza un retardo de 50mS que se repite tantas veces como se indica en la ;constante valor Delay movlw Valor movwf Temp ;Nº de veces a temporizar 50 mS Delay_1 movlw ~.195 movwf TMR0 ;Inicia el Timer 0 con 195 (195*256=49.9mS) bcf INTCON,T0IF ;Repone flag del TMR0 Delay_2 btfss INTCON,T0IF ;Fin de los 50mS ?? goto Delay_2 ;No, el TMR0 no ha terminado decfsz Temp,F ;Decrementa el contador. Fin de temporización ?? goto Delay_1 ;No, el TMR0 temporiza otros 50 mS return ;Si, final de la temporización ;Programa principal Inicio clrf PORTB ;Borra los latch de salida bsf STATUS,RP0 bsf STATUS,RP1 ;Selecciona banco 3 clrf ANSEL ;Puerta A digital clrf ANSELH ;Puerta B digital bcf STATUS,RP1 ;Selecciona banco 1 movlw b'11111110' movwf TRISB ;RB0 se configura como salida movlw b'00111111' movwf TRISA ;RA5:RA0 se configuran como entrada movlw b'00000111' movwf OPTION_REG ;TMR0 con reloj interno y preescaler de 256 bcf STATUS,RP0 ;Selecciona banco 0 ;Este es el cuerpo principal del programa. Espera a que en RA0 se detecte un flanco descendente Loop btfsc PORTA,0 ;RA0=0 ?? goto Loop ;No, esperar bsf PORTB,0 ;Si activar RB0 call Delay ;Temporizar bcf PORTB,0 ;Desactivar RB0 goto Loop ;Repetir el proceso end
Otro más por aquí. ;La interrupción del TMR0. ; ;Se trata de comprobar la interrupción provocada por el TMR0. El programa ;lee el estado de los interruptores conectados a RA0 y RA1 para reflejarlo en ;los leds conectados a RB0 y RB1 respectivamente. Al mismo tiempo el TMR0 ;genera una interrupción cada 0.01 seg. (10 mS) que se repetirá 50 veces con objeto ;de hacer intermitencia de 500 mS sobre el led conectado a RB3. List p=16F886 ;Tipo de procesador include "P16F886.INC" ;Definiciones de registros internos ;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados ;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades __config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF&_BOR_OFF ;Palabra 1 de configuración __config _CONFIG2, _WRT_OFF&_BOR40V ;Palabra 2 de configuración Contador equ 0x020 ;Variable para la temporización org 0x00 ;Vector de RESET goto Inicio org 0x04 ;Vector de interrupción goto Interrupcion org 0x05 Interrupcion bcf INTCON,T0IF ;Repone flag del TMR0 decfsz Contador,F ;Decrementa el contador. Ha habido 50 interrupciones ?? goto Seguir ;No, no han pasado los 500 mS Con_si_0 movlw .50 movwf Contador ;Repone el contador nuevamente para contar 50 interrupciones movlw b'00001000' xorwf PORTB,F ;RB3 cambia de estado Seguir movlw ~.39 movwf TMR0 ;Repone el TMR0 con 39 retfie ;Retorno de interrupción Inicio clrf PORTB ;Borra los latch de salida bsf STATUS,RP0 bsf STATUS,RP1 ;Selecciona banco 3 clrf ANSEL ;Puerta A digital clrf ANSELH ;Puerta B digital bcf STATUS,RP1 ;Selecciona banco 1 clrf TRISB ;RB7:RB0 se configuran como salida movlw b'00111111' movwf TRISA ;RA5:RA0 se configuran como entrada movlw b'00000111' movwf OPTION_REG ;Preescaler de 256 para el TMR0 bcf STATUS,RP0 ;Selecciona banco 0 ;El TMR0 se carga con 39. Con un preescaler de 256 y a una frecuencia de 4MHz se obtiene una interrupción ;cada 10mS. Se habilita la interrupción del TMR0. movlw ~.39 movwf TMR0 ;Carga el TMR0 con 39 movlw .50 movwf Contador ;Nº de veces a repetir la interrupción movlw b'10100000' movwf INTCON ;Activa la interrupción del TMR0 ;Este es el cuerpo principal del programa. Consiste en leer constantemente el estado de RA0 y RA1 para visualizar ;sobre RB0 y RB1 sin que cambie el estado actual de RB7 Loop btfsc PORTA,0 ;Testea el estado de RA0 goto RA0_ES_1 bcf PORTB,0 ;Desactiva RB0 goto TEST_RB1 RA0_ES_1 bsf PORTB,0 ;Activa RB0 TEST_RB1 btfsc PORTA,1 ;Testea el estado de RA1 goto RA1_ES_1 bcf PORTB,1 ;Desactiva RB1 goto Loop RA1_ES_1 bsf PORTB,1 ;Activa RB1 goto Loop end ;Fin del programa fuente
Saludo.
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Fox_Neo en 21 Marzo 2013, 16:41 pm
Muchas garcias Meta por la ayuda creo que estoy avanzando hasta ahora llevo lo siguiente, me falta poner que cuando el contador de usuario llegue a 0 se active la salida:
;************************************************************************** ;***** CONFIGURACIÓN ****************************************************** List p=16F886 ;Tipo de procesador include "P16F886.INC" ;Definiciones de registros internos ;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados ;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades __config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF ;Palabra 1 de configuración __config _CONFIG2, _WRT_OFF&_BOR40V ; _MCLRE_ON: Reset externo ACTIVADO. ; _CP_OFF: Protección del código DESACTIVADO. ; _WDT_OFF: Watchdog DESACTIVADO. ; _IntRC_OSC: Oscilador interno de 4MHz. ;***** DEFINICIÓN DE VARIABLES ; Definimos las posiciones de memoria de los datos CONTADOR equ 0x20 ;************************************************************************** ; Inicialización del programa: ; Origen Org 0x00 goto Inicio ;Vector de reset org 0x05 ; Configuración de los puertos como entradas y salidas Inicio clrf PORTB ; Borrado de los biestables de salida bsf STATUS,RP0 ; Selecciona banco 3 (RP0=RP1=’1’) bsf STATUS,RP1 clrf ANSEL ; El puerto A de tipo digital clrf ANSELH ; El puerto B de tipo digital bcf STATUS,RP1 ; Selecciona banco 1 (RP1=’0’ RP0=’1’) clrf TRISB ; RB7:RB0 se configuran como salidas movlw b'00111111' movwf TRISA ; RA5:RA0 se configuran como entrada movlw b'00000010' ;movemos el valor de la opción del preescale al registro W EN ESTE CASO A 8 movwf OPTION_REG ;pasamos el valor de w al registro bcf STATUS,RP0 ; Se vuelve al banco 0 movlw b'00000111' ;movemos el valor de la opción del preescale al registro W movwf INTCON ; Fin de la inicialización del programa. empezar MOVLW .250 ;INICIALIZAR CONTADOR MOVWF CONTADOR esperar BTFSS PORTA,0 ;comprobamos si en interuptor esta en ON GOTO esperar MOVLW d'5' ;INICIALIZAR TMR0 A 5 PARA QUE CUENTE HASTA 250 YA QUE DESBORDA A 256 para simular x ejemplo poner 252 MOVWF TMR0 ;CARGA EL VALOR DE 5 EN TMR0 CLRF INTCON ;POR SI MIENTRAS SE ESPERABA A QUE SE ACTIVARA EL INTERRUPTOR SE HA DESBORDADO esperardes BTFSS INTCON,T0IF ;VERIFICAMOS CUANDO LLEGA A 256 MEDIANTE EL BIT 2 DEL REGISTRO INTCON GOTO esperardes ;SI NO ES UNO HAY QUE ESPERAR CLRF INTCON ;SE HA ALCANZADO DESBORDAMIENTO HAN PASADO 2000us SE BORRA EL DESBORDAMIENTO DECFSZ CONTADOR,1 ;COMPROBAR QUE EL CONTADOR HA LLEGADO A 0 CUANDO OCURRE SALTA UNA INSTRUCCION GOTO esperar GOTO empezar ;EL CONTADOR ESTA A 0 , YA HAN PASADO 0,5 SEGUNDOS end
¿Como lo veis de momento? :) Gracias por la ayuda.[/size]
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Fox_Neo en 22 Marzo 2013, 01:50 am
Bueno por fin lo he conseguido me ha costado lo suyo pero lo he conseguido ;D aqui esta:;***** CONFIGURACIÓN ****************************************************** List p=16F886 ;Tipo de procesador include "P16F886.INC" ;Definiciones de registros internos ;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados ;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades __config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF ;Palabra 1 de configuración __config _CONFIG2, _WRT_OFF&_BOR40V ; _MCLRE_ON: Reset externo ACTIVADO. ; _CP_OFF: Protección del código DESACTIVADO. ; _WDT_OFF: Watchdog DESACTIVADO. ; _IntRC_OSC: Oscilador interno de 4MHz. ;***** DEFINICIÓN DE VARIABLES ; Definimos las posiciones de memoria de los datos CONTADOR equ 0x20 AUX equ 0x21 ;************************************************************************** ; Inicialización del programa: ; Origen Org 0x00 goto Inicio ;Vector de reset org 0x05 ; Configuración de los puertos como entradas y salidas Inicio clrf PORTB ; Borrado de los biestables de salida bsf STATUS,RP0 ; Selecciona banco 3 (RP0=RP1=’1’) bsf STATUS,RP1 clrf ANSEL ; El puerto A de tipo digital clrf ANSELH ; El puerto B de tipo digital bcf STATUS,RP1 ; Selecciona banco 1 (RP1=’0’ RP0=’1’) clrf TRISB ; RB7:RB0 se configuran como salidas movlw b'00111111' movwf TRISA ; RA5:RA0 se configuran como entrada movlw b'00000010' ;movemos el valor de la opción del preescale al registro W EN ESTE CASO A 8 movwf OPTION_REG ;pasamos el valor de w al registro bcf STATUS,RP0 ; Se vuelve al banco 0 movlw b'00000111' ;movemos el valor de la opción del preescale al registro W movwf INTCON ; Fin de la inicialización del programa. ;______________________________ACTIVACIÓN INICIAL DE LA SALIDA_________________________________________________________ ESPERAR BTFSS PORTA,0 ;PRIMERA VEZ QUE SE VA A VER SI ESTA ACTIVADO EL INTERUPTOR GOTO ESPERAR MOVLW b'0000001' ;SE ACTIVA LA SALIDALA PRIMERA VEZ QUE SE PONE EL INTERRUPTOR MOVWF PORTB MOVLW 0X01 ;INICIALIZO EL REGISTRO AUX PARA INDICAR QUE SE HA ACTIVADO EL INTERRUPTOR MOVWF AUX ;__________________________________________________________________________________________________________ empezar MOVLW .2 ;INICIALIZAR CONTADOR A 250 PARA SIMULAR PONER EL CONTADOR A 2 MOVWF CONTADOR esperar2 CALL COMP_ENTRADA ;COMPRUEBA EL ESTADO DE LA ENTRADA BTFSS AUX,0 ;SI EL RESULTADO DE LA LLAMADA HA DADO 0 NO SE SALTA UNA INSTRUCCIÓN POR TANTO TIENE QUE REINICIARSE EL PROGRAMA GOTO ESPERAR MOVLW d'252' ;INICIALIZAR TMR0 A 5 PARA QUE CUENTE HASTA 250 YA QUE DESBORDA A 256 para simular x ejemplo poner 252 MOVWF TMR0 ;CARGA EL VALOR DE 5 EN TMR0 CLRF INTCON ;POR SI MIENTRAS SE ESPERABA A QUE SE ACTIVARA EL INTERRUPTOR SE HA DESBORDADO esperardes BTFSS INTCON,T0IF ;VERIFICAMOS CUANDO LLEGA A 256 MEDIANTE EL BIT 2 DEL REGISTRO INTCON CUANDO LLEGA SE DESBORADA DANDO UN 1 GOTO esperardes ;SI NO ES 1 HAY QUE ESPERAR CLRF INTCON ;SE HA ALCANZADO DESBORDAMIENTO HAN PASADO 2000us SE BORRA EL DESBORDAMIENTO DECFSZ CONTADOR,1 ;COMPROBAR QUE EL CONTADOR HA LLEGADO A 0 CUANDO OCURRE SALTA UNA INSTRUCCION GOTO esperar2 GOTO activarsal ;EL CONTADOR ESTA A 0 , YA HAN PASADO 0,5 SEGUNDOS activarsal MOVLW b'0000001' XORWF PORTB,F ;INVIERTE EL VALOR DE LA SALIDA GOTO empezar ;_______________________SUBRUTINAS________________________________________________ COMP_ENTRADA NOP esperar3 BTFSS PORTA,0 GOTO SALIDA0 RETURN SALIDA0 CLRF PORTB CLRF AUX ;AL APAGAR EL INTERUPTOR EN MITAD DEL PROCESO ENTRA AQUI Y SEÑALO CON UN 0 QUE SE HA APAGADO EN INTERRUPTOR ES COMO EN C PONER EL RESULTADO DE UNA FUNCIÓN GOTO esperar3 end
Gracias por la ayuda, si veis algo que se puede mejorar o reducir el programa me gustaría saberlo o si veis algún fallo. Salu2
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Meta en 23 Marzo 2013, 03:44 am
Hola:
Puedes comprobarlo con un simulador de PIC como el Proteus 7.10.
Saludo.
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Firos en 26 Marzo 2013, 21:32 pm
Si ya has conseguido que funcione ahora podrías perfeccionarlo. Cuando comprobamos si un interruptor está a "1" o a "0" hay que eliminar rebotes. Es decir, cualquier modo de contacto piezoeléctrico al hacer que conecten sus dos "bornes" hay ahí un "ruido" que en ocasiones puede ser que realmente el interruptor no esté a "1" o que en cuanto le des el contador automáticamente se detenga (en caso de que cuando detecte cero se pare). Por esto mismo te recomiendo que hagas una cosa. Hazte una subrutina de retardos, como la que tienes de 0,5 segundos en este mismo hilo pero con muchas otras de 20 milisegundos, 50 milisegundos, 100 milisegundos, etc, etc. Para hacer la comprobación de un pulsador es tan fácil como poner: bucle btfss PORTA,1 ; Comprueba pulsador conectado en RA1. goto bucle
call R20MS ; Haz una subrutina y solo tendras que poner esto en el código, sin tener que escribirla tu cada dos por tres.
btfss PORTA,1; Comprueba de nuevo, eliminando los rebotes goto bucle
TU CODIGO -> Y aqui sigues con tu codigo.
En breves te pongo otro enlace con un ejemplo de una subrutina
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Fox_Neo en 29 Marzo 2013, 00:20 am
Gracias Firos por responder siempre me gustan tus respuestas y aprendo bastante. A ver si lo he entendido, te refieres que se compruebe el estado de la entrada cada cierto tiempo ¿no?
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Firos en 29 Marzo 2013, 12:21 pm
Gracias Firos por responder siempre me gustan tus respuestas y aprendo bastante. A ver si lo he entendido, te refieres que se compruebe el estado de la entrada cada cierto tiempo ¿no?
No... Mira esta imagen: (http://hyperphysics.phy-astr.gsu.edu/hbasees/electronic/ietron/debounce.gif) Bien, en la parte de arriba, vemos una señal que va desde 0 a 5 V pero... al ser un interruptor mecánico, el contacto que hacen los dos bornes metálicos para dejar pasar la corriente no es perfecto y rebota un poco, dando ese efecto que aparece en la parte de arriba a la izquierda de la imagen, una señal que hace "ziczac". Esos rebotes no los percibimos porque transcurren en microsegundos. El problema es que los microprocesadores trabajan mucho más rápido. Por ejemplo, un microprocesador trabajando a 4Mhz realiza una instrucción en cada microsegundo. Eso que ves a la derecha es una forma de eliminar esos rebotes sin usar ningun programa, haciéndolo mediante Hardware pero eso no nos interesa aquí (aunque no está mal saberlo). Como ves, la señal de la derecha va desde "0" lógico a "1" lógico sin ningún problema. Ahora bien, ¿como eliminamos esto mediante un programa? Con el código que te he puesto. Tendríamos que comprobarlo un par de veces en un tiempo mínimo, mayor que el de los rebotes y menor de el que una persona pudiera cerrar y abrir el interruptor. Por esto mismo puedes hacer un retardo de 20 milisegundos (20000 microsegundos) para que no tenga interferencias e implementarlo en el código. Lo que se suele hacer cuando programamos para simplificar el código son "subrutinas" o "funciones" que son partes de código que se repiten y que con ponerlas una vez en una parte de el código y llamarlas desde donde las queremos ejecutar nos basta. Por ejemplo: Si el PIC lo tenemos trabajando a 4Mhz con lo que tenemos 1 instrucción por segundo, podemos usar un par de contadores para tal efecto (sin usar los TIMERS para no mantenerlos ocupados y poder usarlos para hacer retardos de otro tipo como PWM, capturas de señal, retardos de tiempo para encender y apagar LEDS, etc, etc). Imagina que tenemos 2 contadores. Con uno, podemos contar hasta 256, ¿verdad? Y como tenemos trabajando el microprocesador a 4Mhz sabemos que cada vez que ejecutemos una instrucción para incrementarlo (como INCF) tardaremos 1uS (microsegundo).
¿Y si usamos otro contador? Podríamos contar 256 veces el otro contador. Por lo tanto: 256 * 256 = 65536
Podríamos contar trabajando a 4Mhz con dos contadores hasta 65536 uS (65536 milisegundos). Pues bien, ahora solo nos hace falta despejar la formula.
XXX * 200 = 20000 <- Pongo 200 por poner algo, también podríamos ponerle 256 y solo tendríamos que borrar el contador con "CLRF" para que empiece a contar.
20000 / 200 = 100 <- Pues ya sabemos lo que tenemos que cargar en cada contador.
Esto es una manera rápida y cutre de hacerlo. Lo que tendríamos que hacer es un diagrama de flujo (un esquema) con los pasos que hacemos en el contador y sumarle los pasos que tarda en cada acción en cada bucle porque con estos cálculos que te he puesto para que lo entendamos todos en realidad va a tardar bastante mas de 20000 uS (aunque no lo percibirá el ojo humano y podríamos despreciarlo si la finalidad es únicamente comprobar el interruptor).Esta es la que uso yo, que tiene un desfase de 1uS (que 1/20000 es un fallo mínimo): ;******************************************************************** ; "R20MS" ;tsubrutina R20MS = (4.RET1.RET2 + 4.RET2 + 1) micseg. ;Rutina de temporización 20 milisegundos. ;********************************************************************
R20MS movlw .25 ;Carga RET2. movwf RET2 ; "
R20MS1: movlw .199 ;Carga RET1. movwf RET1 ; "
R20MS2: clrwdt ;Inicializa WDT. decfsz RET1,F ;Decrementa RET1 hasta cero. goto R20MS2 ;Si RET1 no es cero repite decremento. decfsz RET2,F ;Si RET1=0 decrementa RET2. goto R20MS1 ;Si RET2 no es 0 repite el bucle. return
Y la tengo metida dentro de un fichero al que llamo "retardos.inc". Los contadores están en las posiciones altas 0x63, por ahí, para que si programo no me equivoque y ponga otro registro en el mismo sitio. Luego, en el programa principal, en la parte de abajo ponemos: include "retardos.inc"
end
Y con eso nos incluirá al compilar el programa la subrutina en nuestro programa. Ahora, desde cualquier otra parte de el programa podemos llamarla con: Con lo que si miras el programa del POST anterior lo podrás ver mejor: Si ya has conseguido que funcione ahora podrías perfeccionarlo. Cuando comprobamos si un interruptor está a "1" o a "0" hay que eliminar rebotes. Es decir, cualquier modo de contacto piezoeléctrico al hacer que conecten sus dos "bornes" hay ahí un "ruido" que en ocasiones puede ser que realmente el interruptor no esté a "1" o que en cuanto le des el contador automáticamente se detenga (en caso de que cuando detecte cero se pare). Por esto mismo te recomiendo que hagas una cosa. Hazte una subrutina de retardos, como la que tienes de 0,5 segundos en este mismo hilo pero con muchas otras de 20 milisegundos, 50 milisegundos, 100 milisegundos, etc, etc. Para hacer la comprobación de un pulsador es tan fácil como poner: bucle btfss PORTA,1 ; Comprueba pulsador conectado en RA1. goto bucle
call R20MS ; Haz una subrutina y solo tendras que poner esto en el código, sin tener que escribirla tu cada dos por tres.
btfss PORTA,1; Comprueba de nuevo, eliminando los rebotes goto bucle
TU CODIGO -> Y aqui sigues con tu codigo.
En breves te pongo otro enlace con un ejemplo de una subrutina Espero que haya quedado claro :) Un saludo.
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Firos en 30 Marzo 2013, 18:35 pm
Estaba revisando el hilo un poco... y se me ha ocurrido otra cosa. Veo que en tu código para cambiar de bancos tocas los registros RP0 y RP1. Lo que voy a proponerte ahora es otra cosa para que no tengas que estar escribiendo eso también. Imagínate que cada vez que quieras cambiar de banco no tuvieras que pensar... mmm en cual había que poner un "1" en RP0 o en RP1?... Pues bien. Puedes hacer lo siguiente: Banco0 macro bcf STATUS,RP0 bcf STATUS,RP1 endm
Banco1 macro bsf STATUS,RP0 bcf STATUS,RP1 endm
Banco2 macro bcf STATUS,RP0 bsf STATUS,RP1 endm
Banco3 macro bsf STATUS,RP0 bsf STATUS,RP1 endm
padigital macro ;Para el correcto funcionamiento de esta macro es movlw 06 ;necesario que antes se esté posicionado en el banco 1. movwf ADCON1 endm Con esto, estas creando unas macros y te servirán para no tener que escribir tanto en el código cada vez que quieras cambiar de banco. Será menos tedioso programar en ASM. Estas macros lo que hacen es sustituir en el código donde pongas "Banco0" por lo que pone ahí. No es como una subrutina o función a la cual llamas y realizas un salto de PC para ejecutarla. Con esto directamente le mandas a el compilador que sustituya "Banco 0" por "bcf STATUS,RP0 / bcf STATUS,RP1". Esto puedes guardarlo en la misma carpeta donde vayas a compilar tu programa y llámalo "macros.inc" por ejemplo. Luego, para incluirlo en tu programa, en vez de ponerlo abajo, ponlo arriba, encima de la declaración de variables, debajo de la configuración del PIC. list p=16f876, f=INHX8M, r=hex include "p16f876.inc" include "macros.inc" CONDIR equ 20 CONCAR equ 21 org 0
Pruébalo. Espero que te sirva. Un saludo.
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Fox_Neo en 1 Abril 2013, 22:55 pm
Gracias Firos como siempre me gusta mucho tus respuestas, despúes de las vacaciones me lo miraré con más detenimiento. Si veo que no entiendo algo ya lo diré ;D Salu2
Título: Re: Dudas para crear temporizador en ensamblador
Publicado por: Meta en 20 Abril 2013, 00:00 am
Cuando comprobamos si un interruptor está a "1" o a "0" hay que eliminar rebotes.
Ejemplo de antirebores de un pulsador. Este antirebores es por software y funciona de maravilla, es para ahorrar más electrónica. ; Cada vez que presiona el pulsador conectado a la línea RA4 conmutará el estado de ; un LED conectado a la línea RB1. ; ; ZONA DE DATOS ********************************************************************** LIST P=16F84A INCLUDE <P16F84A.INC> __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC CBLOCK 0x0C ENDC #DEFINE Pulsador PORTA,4 ; Pulsador conectado a RA4. #DEFINE LED PORTB,1 ; Línea donde se conecta el diodo LED. ; ZONA DE CÓDIGOS ******************************************************************** ORG 0 ; El programa comienza en la dirección 0. Inicio bsf STATUS,RP0 ; Acceso al Banco 1. bsf Pulsador ; La línea RA4 se configura como entrada. bcf LED ; Se configura como salida. bcf STATUS,RP0 ; Acceso al Banco 0. bcf LED ; En principio diodo LED apagado. Principal btfsc Pulsador ; ¿Pulsador presionado?, ¿(Pulsador)=0? goto Fin ; No. Vuelve a leerlo. call Retardo_20ms ; Espera que se estabilicen los niveles de tensión. btfsc Pulsador ; Comprueba si es un rebote. goto Fin ; Era un rebote y sale fuera. btfsc LED ; Testea el último estado del LED. goto EstabaEncendido EstabaApagado bsf LED ; Estaba apagado y lo enciende. goto EsperaDejePulsar EstabaEncendido bcf LED ; Estaba encendido y lo apaga. EsperaDejePulsar btfss Pulsador ; ¿Dejó de pulsar?. ¿(Pulsador)=1? goto EsperaDejePulsar ; No. Espera que deje de pulsar. Fin goto Principal INCLUDE <RETARDOS.INC> END
Saludo.
|