;------------------------------------------------------------- ;Definición de variables , llamada a libreria y configuración fusibles procesador. ;------------------------------------------------------------- List p=p12f675 ;procesador include "P12F675.INC" ;Definiciones de registros internos __config _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _BODEN_OFF & _CP_OFF & _CPD_OFF errorlevel -302 CONSTANT BASE=0x20 Numero equ BASE+0 ;Número aleatorio Cont_espera equ BASE+1 ;Contador de intervalos para temporización. Temporal equ BASE+2 ;Variable número temporal. Ck equ BASE+3 ;Contador de chequeos de pulsador. Pulsos equ BASE+4 ;Iteraciones para control de pulsador. RndL equ BASE+5 ;Byte bajo de número aleatorio. RndH equ BASE+6 ;Byte alto de número aleatorio. NumAnt equ BASE+7 ;Número visualizado anteriormente, para evitar 2 ;consecutivos iguales en ciclo dado wtmp equ BASE+8 ;registro temporal durpuls equ BASE+9 ;Almacenará la duración de la pulsación contador equ BASE+10 ;Contador bucle dado contpausa equ BASE+11 ;Contador creciente temporización. demo equ BASE+12 ;Estado normal =0 permisodemo equ BASE+13 ;Estado Inicial = 1 ;------------------------------------------------------------- org 0x00 ;Vector de Reset goto Inicio org 0x04 ;------------------------------------------------------------- rutinaint: banksel IOC ;Selecciona banco 1 bcf IOC,IOC5 ;DESHabilita interrupcion por cambio estado GPIO.5 banksel GPIO ;Selecciona banco 0 bcf INTCON,GPIE ;DESHabilita Interrupciones por cambio estado GPIO movf GPIO,W ;ver INTERRUPT-ON-CHANGE pag 23 en Datasheet bcf INTCON,GPIF ;Si no se lee GIO, GPIF no se borra. ; call demo1 retfie ;Vuelve al punto siguiente a Sleep, Activando GIE ;------------------------------------------------------------- ;INICIALIZACION Inicio: banksel GPIO ;Selecciona banco 0 clrf GPIO ;Borra Latch salida del puerto movlw 0x07 ;Selecciona GPIO <2:0> como - movwf CMCON ;Entradas/Salidas Digitales y no Comparador. movlw 0x01 ;Habilita Timer1 con oscilador interno - movwf T1CON ;y preescaler a 1:1 bcf INTCON,GIE ;Desactiva Interrupciones call Calibrado ;Coge valor de calibrado banksel OSCCAL ;Selecciona banco 1 movwf OSCCAL ;Configura valor de calibración CLRF ANSEL ;Digital I/O desabilita ADC movlw b'00101000' movwf TRISIO ;Configura GPIO<2:0>,<4> salidas, GPIO<5> entrada movlw b'00100000' movwf WPU ;Habilita pullups en entrada GPIO<5> movlw b'00000111' movwf OPTION_REG ;OPTION_REG<2:0>,Preescaler a 256 Timer 0 ;OPTION_REG<3>,Preescaler asignado a Timer0 ;OPTION_REG<4>,Flanco ascendente T0,NO USADO ;OPTION_REG<5>,T0 como temporizador OSC Interno ;OPTION_REG<6>,Int.por flanco de bajada GPIO<2>, ;NO USADO ;OPTION_REG<7>,GPIO pull-ups activados,confg.WPU banksel GPIO ;Selecciona banco 0 movlw d'8' ;Número de veces que se chequeará el pulsador por ;si fuese ruido. movwf Pulsos movlw 0x00 ;Inicializa número anterior por vez primera. movwf NumAnt movwf demo ;Inicializa demo =0 movlw 0x01 ;Inicializa permisodemo.=1 movwf permisodemo ;------------------------------------------------------------- ;Aquí hacemos que la primera vez que conectamos el PIC, o después de un RESET ;del mismo, pase a estado de bajo consumo (duerma) para ahorrar energía en el caso ;de que no pensemos utilizarlo inicialmente ;------------------------------------------------------------- goto nopulsaydormir ;------------------------------------------------------------- ;Esta rutina inicializa la variable durpuls al valor máximo d'40' ;para cuando funciona en modo demostración ;------------------------------------------------------------- maximo: movlw d'40' movwf durpuls ;Inicializa durpuls a 40. por estar activo demo goto rnd ;Continúa ciclo demo. ;------------------------------------------------------------- ;PULSADOR PULSADO ;------------------------------------------------------------- Inicio2: movfw demo ;Comprueba si demo está activa, si es así salta xorlw 0x01 ;la lectura de ciclos de pulsado btfsc STATUS,Z goto maximo ;Salta a durpuls valor máximo y a RND movlw d'0' ;si no es demo inicializa durpuls a valor mínimo movwf durpuls ;Inicializa durpuls a 0. incremento: movf Pulsos,W ;Iteraciones lectura pulsador movwf Ck ;Iteraciones contador subrutina call Pulsador ;salta a rutina comprobacion xorwf Pulsos,W ;Si es (N pulsos), es que se ha pulsado (pulsos) veces. btfss STATUS,Z ;Comprueba flag Z goto Bucle03 ;si es Z, es que se ha pulsado y no era ruido. incf durpuls ;Incrementa contador de ciclos lectura pulsador movf durpuls,w ;Coge valor máximo ciclo números xorlw d'40' ;Lo compara con d'40' btfss STATUS,Z goto bucle03 ;Si no ha llegado al máximo, va a rutina que ;comprueba pulsador libre. movf permisodemo,w ;Si SI ha llegado a valor máximo comprueba que es la xorlw d'01' ;primera vez que se pulsa. btfss STATUS,Z goto rnd ;salta a generador numeros y ciclo movlw d'01' ;Si es vez primera, asigna valor a demo. movwf demo goto rnd ;Como ha llegado al máximo valor d'40', pasa a calcular ;número aleatorio. ;------------------------------------------------------------- ;PULSADOR SOLTADO Bucle03: btfss GPIO,5 ;Activada entrada GPIO<5>?? Pulsador NO pulsado movf Pulsos,W ;Iteraciones lectura pulsador movwf Ck ;Iteraciones contador subrutina call Pulsador ;salta a rutina comprobacion iorlw .00 ;Si es 0, es que no se a pulsado nada btfss STATUS,Z ;Comprueba flag Z goto incremento ;Todavia NO movf durpuls,w iorlw d'0' btfsc STATUS,Z goto incremento clrf permisodemo ;Como no se ha pulsado hasta el valor máximo, ;anulamos posibilidad de demo ;------------------------------------------------------------- ;CAPTURA NUMERO ALEATORIO BASADO EN VALOR DE TIMER1 ;Como se ha soltado pulsador antes de llegar al máximo ;valor, pasa a calcular y visualizar números. rnd: incf durpuls movf TMR1L,W ;Ahora SI, Captura el valor de timer1 (Aleatorio?) andlw 0x0f ;Deja sólo los 4 bits menos signicativos movwf Temporal ;Almacena valor de 4 bits en temporal Call Divi ;Pasa a un valor de 1 a 6 desde Temporal movf Temporal,W ;Recupera temporal con valor de 1 a 6 movwf Numero ;Y almacenamos numero aleatorio final en "numero" movlw 0x00 movwf NumAnt ;Inicializa NumAnt (Numero anterior) para que durante ;ciclo dado no salgan dos números consecutivos iguales. ;------------------------------------------------------------- ;PAUSA PARA QUE DE TIEMPO A SOLTAR PULSADOR Y NO ANULE CICLO DADO ; movlw d'10' ;Equivale a 500 ms. ; movwf Cont_espera ;Variable de temporización ; call Espera_var ;Como variable es=1 temporiza 50msegs. ;------------------------------------------------------------- ;CICLO DADO movf durpuls,w ;Coge valor de veces leido el contador de pulsación movwf contador ;y lo almacena en contador de números a visualizar ciclo: movf contador,w ;pasa a W de nuevo el contador de números movwf wtmp ;lo almacena en variable para pausa desacelerada bcf status,c ;Borramos acarreo para que en la rotación siguiente ;entre un cero. rrf wtmp,f ;Dividimos variable wtmp entre 2 bcf status,c ;Borramos acarreo para que en la rotación siguiente ;entre un cero. rrf wtmp,f ;vtmp queda dividido por 4 ;Con esto si la pulsación fué máxima durpuls=40, habra ;resultado que wtmp vale d'10' movlw d'10' ;Cargamos valor máximo de pausa en W movwf contpausa ;lo pasamos a contpausa movf wtmp,w ;Pasamos el valor de durplus / 4 a contpausa (Max d'10') subwf contpausa,f ;Hacemos la resta para ver el valor de pausa mínima incf contpausa ;Lo incrementamos, por que si el pulsador fué llevado al ;valor límite (durpuls=40) resultará que wtmp será d'10' ;y al hacer la resta quedará contpausa=d'0'. Y como la ;rutina de temporización necesita un valor mínimo de d'1' llamaaleatorio: Call RANDOM ;Pone en rndl y rndh un aleatorio de 16 bits. Call SubDiv ;Convierte aleatorio en número aleatorio de 1 a 6 ;depositándolo en temporal. movf temporal,w xorwf NumAnt,w ;Compruba si aleatorio actual es igual al anterior btfsc Status,z ;Si es diferente, continúa ciclo. goto llamaaleatorio ;Si es igual, solicita uno de nuevo. movf Temporal,W ;Número a visualizar movwf NumAnt ;Salva número para comprobar que no se repita en proximo ciclo. call Tabla ;Conversion a código dado movwf GPIO ;Visualiza sobre los 7 LEDS del dado movf contpausa,W movwf Cont_espera ;Variable de temporización call Espera_var2 ;Como variable es=1 temporiza 50msegs. decfsz contador,F ;Siguiente número goto ciclo ;Como es cero,Repite nuevo dado a 6 ;------------------------------------------------------------- salida: movf Numero,W ;Recoge número aleatorio call Tabla ;Conversion a código dado movwf GPIO ;Visualiza aleatorio sobre los 7 LEDS del dado ; movlw d'200' ;Temporiza 10 segs ; movlw d'60' ;Temporiza 3 segs movlw d'100' ;Temporiza 5 segs movwf Cont_espera ;Inicializa variable de temporización a d'240' call Espera_var ;Temporiza la visualizacion 50ms*240 = 12 segs ;o menos si se ha pulsado. clrf GPIO ;Apaga los leds ;------------------------------------------------------------------------ ;Comprobamos que no se ha pulsado nada antes de dormir. nopulsaydormir: movf Pulsos,W ;Iteraciones lectura pulsador movwf Ck ;Iteraciones contador subrutina call Pulsador ;salta a rutina comprobacion iorlw .00 ;Si es 0, es que no se a pulsado nada btfss STATUS,Z ;Comprueba flag Z goto Inicio2 ;si no es Z, es que se ha pulsado o era ruido y ;va a Inicio2. Si no se pulsó, va a estado de ;suspension y bajo consumo standby. movf demo,W xorlw d'01' btfsc STATUS,Z goto Inicio2 ;------------------------------------------------------------------------ ;A DORMIR dormir: ; call demo1 ;Hace efecto de luces banksel IOC ;Selecciona banco 1 bsf IOC,IOC5 ;Habilita interrupcion por cambio estado GPIO.5 banksel GPIO ;Selecciona banco 0 bsf INTCON,GPIE ;Habilita Interrupciones por cambio estado GPIO bsf INTCON,GIE ;Habilita Interrupciones Globales sleep ; movlw d'40' ;Temporiza 1 segs ; movwf Cont_espera ;Inicializa variable de temporización a d'40' ; call Espera_var2 ;Temporiza la visualizacion 25ms*40 = 1 segs ;o menos si se ha pulsado.5 ; call demo1 ;Hace efecto de luces nop btfsc STATUS,NOT_TO ;Chequea si se ha despertado por desbordamiento WDT goto Inicio2 ;Reinicia el bucle principal, ya se se habrá despertado ;por interrupcion por cambio estado GPIO5 clrwdt ;Como se ha despertado por WDT, lo borra goto dormir ;Se duerme de nuevo ;------------------------------------------------------------------------ Tabla: addwf PCL,F ;Desplazamiento sobre la tabla nop ;Esto es por que pcl ya apunta a la dirección siguiente. retlw b'00000001' ;Número 1 retlw b'00000010' ;Número 2 retlw b'00000011' ;Número 3 retlw b'00000110' ;Número 4 retlw b'00000111' ;Número 5 retlw b'00010110' ;Número 6 ;------------------------------------------------------------------------ ;Esta rutina temporiza 1 milisegundo Espera_1ms: bcf INTCON,T0IF ;Desconecta el flag de rebosamiento movlw 0xfc ;Complemento A1 del D04 (1024us=1ms) movwf TMR0 ;Carga el Timer0 Espera_1ms_1: clrwdt ;Refresca el WatchDog btfss INTCON,T0IF ;Rebasamiento timer0?? goto Espera_1ms_1;todavía NO, sigo esperando return ;------------------------------------------------------------------------ ;Esta rutina temporiza 50 milisegundos por las veces indicadas en Cont_espera como variable entrada Espera_var: bcf INTCON,T0IF ;Desconecta el flag de rebosamiento movlw 0x3c ;Complemento A1 del D195 (49920us=50ms) movwf TMR0 ;Carga el Timer0 Intervalo: btfss GPIO,5 ;Activada entrada GPIO<5>??? Pulsador NO pulsado return ;Si ha sido pulsada vuelve a bucle principal. goto nosale ;Si no, continúa temporizando nosale: clrwdt ;Refresca el WatchDog btfss INTCON,T0IF ;Rebasamiento timer0?? goto Intervalo ;todavía NO, sigo esperando decfsz Cont_espera,F ;Decrementa el contador de intervalos goto Espera_var ;Repite el intervalo de 50ms return ;------------------------------------------------------------------------ ;Esta rutina temporiza 30 milisegundos por las veces indicadas en Cont_espera como variable entrada Espera_var2: bcf INTCON,T0IF ;Desconecta el flag de rebosamiento ; movlw 0x9d ;Complemento A1 del d'98' (25088us=25ms) movlw 0x89 ;Complemento A1 del d'118' (30208us=30ms) movwf TMR0 ;Carga el Timer0 Intervalo2: clrwdt ;Refresca el WatchDog btfss INTCON,T0IF ;Rebasamiento timer0?? goto Intervalo2 ;todavía NO, sigo esperando decfsz Cont_espera,F ;Decrementa el contador de intervalos goto Espera_var2 ;Repite el intervalo de 30ms return ;------------------------------------------------------------------------ Pulsador: movf Ck,W ;Copia iteraciones en W BuclePulsador: movwf wtmp ;Salva W en Wtmp por que será modificado ;en espera_1ms. call Espera_1ms movf wtmp,w btfsc GPIO,5 ;Comprueba si se ha pulsado (Pullup) decf Ck,W ;Si no se ha pulsado, iteraciones en W=W-1 decfsz Ck,F ;Decrementa iteraciones y comprueba si hemos terminado goto BuclePulsador ;Como no hemos terminado, repetimos lectura. return ;Devolvemos W, si el pulsado es OK, W=iteraciones ;------------------------------------------------------------------------ ;Esta rutina crea un aleatorio de 16 bits en RndH y RndL RANDOM: MOVF RndH, W ;Comprueba que RndH y RndL, IORWF RndL, W ;no sean 0 BTFSC STATUS, Z COMF RndL, F ;Si es cero, hace RndL = 0xff BTFSS RndH, 6 ; Comprueba bit RndH.6, si es 1 invierte bit RndH.7 MOVLW 00H BTFSC RndH, 6 MOVLW 80H XORWF RndH, F BTFSS RndH, 4 ; Comprueba bit RndH.4, si es 1 invierte bit RndH.7 MOVLW 00H BTFSC RndH, 4 MOVLW 80H XORWF RndH, F BTFSS RndL, 3 ; Comprueba bit RndL.3, si es 1 invierte bit RndH.7 MOVLW 00H BTFSC RndL, 3 MOVLW 80H XORWF RndH, F RLF RndH, W ; Rota RndH en W para obtener acarreo RLF RndL, F ; Desplaza RndL a la izquierda RLF RndH, F ; Desplaza RndH a la iaquierda RETURN ;------------------------------------------------------------- ;REDUCCION NUMERO ALEATORIO A UNO ENTRE 1 Y 6 SubDiv: movf RndL,W ;Captura el valor de RndH Aleatorio andlw 0x0f ;Deja sólo los 4 bits menos signicativos movwf Temporal ;Copia numero de 1 a 15 en Temporal Divi: movlw d'6' subwf Temporal,W ;Resta 6 al numero aleatorio movwf Temporal ;Lo guarda sublw d'5' btfss STATUS,C ;Mira si es menor de 5 goto Divi ;No, sigue restando incf Temporal,F ;El numero queda entre 1 y 6 Return ;------------------------------------------------------------- ;Rutina que hace vaivén de los leds para Comprobar funcionamiento de rutina ;de control de interrupción o que un sleep está funcionando. ;------------------------------------------------------------- demo1: movlw d'10' ;10 veces movwf wtmp b1demo1: movlw 0x03 call minidemo1 movlw 0x11 call minidemo1 movlw 0x05 call minidemo1 movlw 0x11 call minidemo1 decfsz wtmp,f goto b1demo1 clrf GPIO return minidemo1: movwf gpio movlw d'2' movwf Cont_espera ;Inicializa variable de temporización a d'4' call Espera_var2 ;Temporiza la visualizacion 50ms*4 = 200ms return ;------------------------------------------------------------- ;Rutina que coge el valor de calibrado del fabricante devolviendolo en W. ;------------------------------------------------------------- org 0x3ff Calibrado: retlw 0x44 ;------------------------------------------------------------- ;------------------------------------------------------------- end ;Fin de código fuente