;********************************************************************** ; MANEJO DE SERVOS - Programa Básico 2 - Manejo con interrupciones ; Por Eduardo J. Carletti, Robots Argentina, 2007 ;********************************************************************** list p=16F628A ; definir procesador #include ; definiciones de variables específicas del procesador ERRORLEVEL 1;-302 ; para evitar los mensajes de cambio de ; banco en el resultado del compilador __CONFIG _CP_OFF & _WDT_OFF & _LVP_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF ;***** DEFINICIÓN DEL NOMBRE DE ENTRADAS Y SALIDAS #define SERVO1 PORTA,0 ; puerto de salida de servo 1 #define PULSADOR1 PORTA,1 ; puerto de entrada de pulsador 1 #define PULSADOR2 PORTA,2 ; puerto de entrada de pulsador 2 #define PULSADOR3 PORTA,3 ; puerto de entrada de pulsador 3 ;***** VARIABLES CBLOCK 0x20 acum_A ; variable momentánea Posic ; posición servo fase ; fase de programa para interrupción Guardar_STATUS ; Guardar Status Guardar_W ; Guardar W ENDC ;*********************************************************************************** org 0x000 goto principal org 0x004 goto interrupcion ;*********************************************************************************** ; Principal ;*********************************************************************************** principal movlw b'00000111' ; deshabilita comparadores. Esto es movwf CMCON ; algo importante en el PIC 16F628A clrf PORTA ; inicia ports clrf PORTB ; inicia ports bsf STATUS,RP0 ; Apunta a banco 1 movlw b'00001110' ; PORTA movwf TRISA ; salidas menos 1, 2 y 3, entradas MOVLW b'00000000' ; PORTB movwf TRISB ; salidas movlw b'00000010' ; Configuración para TMR0 movwf OPTION_REG ; preescaler 2, 1:8 con CLK interno (que es ; de 1 MHz si el oscilador es de 4 MHz). ; El contador cuenta cada 8 useg bcf STATUS,RP0 ; Apunta a banco 0 clrf TMR0 ; inicia registro de timer en 0 movlw d'133' ; inicia valor de posición de servo (centro) movwf Posic clrf fase ; inicia para que comience con la fase 0 movlw b'10100000' ; Interrupciones habilitadas ; GIE (global), T0IE (timer 0) movwf INTCON ; Interrupción General, Interrupción Timer 0 ;*********************************************************************************** ; Lazo principal ;*********************************************************************************** lazo movf fase,f bz fase0 goto lazo ;*********************************************************************************** ; Rutina de apoyo ;*********************************************************************************** ; Fase 0: Los servos actúan con un pulso de control que va entre 0,5 ms y 2,5 ms. ; En el bloque que sigue se inicia en 1 el pulso de control y se espera un ; retardo fijo de aproximadamente 0,5 ms, que es el valor mínimo del pulso. ; Con este valor de longitud de pulso y una longitud cero en la parte variable, ; el servo está parado al máximo hacia la izquierda (sentido antihorario). fase0 bsf SERVO1 ; pone la señal de servo en 1 bcf INTCON,T0IF ; borra el flag de timer movlw d'192' ; (256-192 = 64) 64 * 8 us = 0,512 ms movwf TMR0 ; valor al registro de timer incf fase,f ; pasa a fase 1 goto lazo ;*********************************************************************************** ; Manejo interrupciones ;*********************************************************************************** interrupcion ; Salva todo bcf INTCON,T0IE ; deshabilita interrupción de timer movwf Guardar_W swapf STATUS, w movwf Guardar_STATUS ; distribuidor movf fase,w xorlw 0x01 ; ¿fase 1? bz fase1 ; sí movf fase,w xorlw 0x02 ; ¿fase 2? bz fase2 ; sí movf fase,w xorlw 0x03 ; ¿fase 3? bz fase3 ; sí goto salidaint ; ninguna de ellas, sale ; Fase 1: Aquí comienza el tiempo variable del pulso. Esto permite que ; el recorrido completo, de 180 grados (valores de pulso entre 0,5 ms ; y 2,5 ms), se divida en 256 segmentos (256 * 8 us = 2,048 ms). ; La parte variable del pulso de control varía entre 0 y 2 ms fase1 movf Posic,w ; 256-nn x 8 uS = 1 ms, 1,5 ms, 2,5 ms movwf TMR0 ; valor al registro de timer incf fase,f ; pasa a fase 2 goto salidaint ; Fase 2: Retardo de 20 ms, que es el tiempo estándar que debe separar los pulsos ; de control para los servos comunes de RC fase2 bcf SERVO1 ; pone la señal de servo en 0 bsf STATUS,RP0 ; Apunta a banco 1 movlw b'00000111' ; Configuración para TMR0 movwf OPTION_REG ; preescaler 7, 1:256 con CLK interno (que es ; de 1 MHz si el oscilador es de 4 MHz). ; El contador cuenta cada 256 useg bcf STATUS,RP0 ; Apunta a banco 0 movlw d'249' ; (256-249 = 7) 7 * 256 us = 17,92 ms + 2 ms pulso movwf TMR0 ; valor al registro de timer incf fase,f ; pasa a fase 3 goto salidaint ; Fase 3: Como en el bloque de la fase 2 cambió el prescaler del timer a 7, ahora ; debe reponerlo al valor de un conteo cada 8 useg, y volver al estado de fase = 0, ; con lo cual el ciclo se reinicia. También hemos insertado en esta fase, que se ; ejecuta cada 20 ms aproximadamente, la lectura de los pulsadores. fase3 bsf STATUS,RP0 ; Apunta a banco 1 movlw b'00000010' ; Configuración para TMR0 movwf OPTION_REG ; preescaler 2, 1:8 con CLK interno (que es ; de 1 MHz si el oscilador es de 4 MHz). ; El contador cuenta cada 8 useg bcf STATUS,RP0 ; Apunta a banco 0 clrf fase ; pasa a fase 0 pulsadores ; lee órdenes a través de pulsadores btfss PULSADOR1 goto iniciaPos ; servo en posición central btfss PULSADOR2 goto incPos ; incrementa Posic btfss PULSADOR3 goto decPos ; decrementa Posic goto salidaint ;*********************************************************************************** ; Rutinas de apoyo ;*********************************************************************************** iniciaPos movlw d'133' ; 256-133 = 123, 123 * 8 us = 984 us + 512 us movwf Posic ; posición central en esta disposición goto salidaint ; y sale decPos movf Posic,f ; se fija si Posic ya es cero bz sale1 ; si es cero no decrementa decf Posic,f ; si no es cero, decrementa sale1 goto salidaint ; y sale incPos movlw 0xFF ; se fija si Posic no es 0xFF xorwf Posic,w ; que es el valor máximo bz sale2 ; si es el valor máximo, no incrementa incf Posic,f ; si no es el valor máx, incrementa sale2 goto salidaint ; y sale ; Regresa todo salidaint bcf INTCON,T0IF ; borra el flag de timer swapf Guardar_STATUS, w movwf STATUS swapf Guardar_W, f swapf Guardar_W, w bsf INTCON,T0IE ; habilita interrupción de timer retfie ; retorna END