Programa Proton IDE de un PIC Encoder con un 16F876A, 16 bits de resolución, por Interrupción, bis.
Segunda Versión:
Segunda Versión:
Device=16F876A
REMINDERS = FALSE
Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE
ALL_DIGITAL = TRUE
On_INTERRUPT GoTo Interrupcion
Symbol INTE = INTCON.4 ' RB0 Habilitar interrupción externa.
Symbol INTF = INTCON.1 ' RB0 Flag de interrupción externa.
Symbol GIE = INTCON.7 ' Global Interrupt Enable.
Symbol INTEDG = OPTION_REG.6 ' Flag = 0 Flanco bajada. Flag = 1 Flanco subida.
GIE = 1 ' Activar interrupciones generales.
INTE = 1 ' Activar la interrupción externa RB0/INT.
INTEDG = 1 ' Activar la interrupción por flanco de subida.
TRISA = %100011
TRISB = %11111111
TRISC = %11111111
PORTA.2 = 0 ' Motor parado.
PORTA.3 = 0
PORTA.4 = 0 ' Apaga el LED.
Dim P As DWord ' Declaramos el valor de P como DWord (32 bits), es la posición.
Dim X As DWord ' Declaramos el valor de X como DWord (32 bits), es el contador de pulsos.
Dim Q As DWord ' Q nos servirá para saber que ha llegado a la posición y no hay nueva posición.
Dim Aux As Byte ' Se almacenará el valor anterior de RA0 y RA1, hasta la siguiente comparación.
Dim Enc As Byte ' Se almacenará el valor actual de RA0 y RA1, hasta la siguiente comparación.
Dim Temp As Byte ' Contador para temporización.
Dim Flag As Bit ' Bandera que avisa de nueva posición.
Q=0 ' Ponemos todas las variables a cero.
P=0
X=0
Aux=0
Enc=0
Temp=0
Flag=0
Bucle: ' Bucle infinito.
PORTA.4 = Flag ' Enciende/apaga el LED si motor está en marcha o parado.
If Flag=1 Then
Q=P ' Igualamos para detectar cambios después.
P.BYTE0 = PORTB ' Carga el byte bajo de los 16 bits.
P.BYTE1 = PORTC ' Carga el byte alto de los 16 bits.
P.0 = PORTA.0 ' RA0 y RA1 pasan a ocupar los bits P0 y P1,
P.1 = PORTA.1 ' sobre-escribiéndolos.
If P<>Q Then Flag=0 ' Detectar nueva entrada de datos.
EndIf
If X = P Then
PORTA.2 = 0 ' Motor Parado.
PORTA.3 = 0
Flag=1
GoTo Bucle
EndIf
If Temp>8 Then Temp=0 ' PWM.
Inc Temp
If Flag=1 And Temp>3 Then
PORTA.2 = 0 ' Motor parado (PWM).
PORTA.3 = 0
GoTo Bucle
Else
If X > 70000 Then ' Si x<0, Motor hacia delante.
PORTA.2 = 1
PORTA.3 = 0
GoTo Bucle
EndIf
If X > P Then ' Si x>p, motor hacia atrás.
PORTA.2 = 0
PORTA.3 = 1
GoTo Bucle
EndIf
If X < P Then ' Si x<p, motor hacia delante.
PORTA.2 = 1
PORTA.3 = 0
GoTo Bucle
EndIf
EndIf
GoTo Bucle
End
Interrupcion: '-------- Decodificador de Encoder --------------
Context SAVE ' Salva en contexto de los registros antes de operar con la interrupción.
If PORTB.0 = 1 Then ' Si RB0 se ha puesto a 1 (flanco de subida),
INTEDG = 0 ' entonces activar la siguiente interrupción por flanco de bajada.
If PORTB.1 = 1 Then ' Si RB1 está a 1
Inc X ' entonces incrementar el contador X.
EndIf
Else ' Si RB0 se ha puesto a 0 (flanco de bajada),
INTEDG = 1 ' entonces activar la siguiente interrupción por flanco de subida.
If PORTB.1 = 1 Then ' Si RB1 está 1
Dec X ' entonces decrementar el contador X.
EndIf
EndIf
INTF = 0 ' Borra el "flag" de la interrupción RB0/INT
' para poder permitir la siguiente interrupción.
Context Restore ' Restablece el contexto de los registros tal como estaban antes de la
' interrupción.