Pour mon projet avec l'AD9850 j'ai besoin de gérer un encodeur, plutôt que de chercher sur le net j'ai ré-inventé la roue, c'est plus amusant.
J'ai utilisé un encodeur très bas de gamme chinois mais çà doit convenir à n'importe quel autre type d'encodeur pour peu que le chronogramme soit identique. En examinant le résultat à l'analyseur logique j'ai été surpris de la bonne qualité des signaux, aucun rebond et pas obligé d'inclure des tempos pour les masquer. J'avais pourtant déjà été bien embêté auparavant avec ce type de composant.
Principe:
Pour comprendre le fonctionnement il suffit de faire le chronogramme de l'encodeur, de l'observer et d'en tirer une table de vérité. Il faut auparavant sauvegarder l'état antérieur des pins pour les comparer ensuite avec le nouvel état.
On s'aperçoit que si on tourne en sens anti-horaire la pin A vaut toujours B_old, et à l'inverse si on tourne en sens horaire la pin A est toujours différente de B_old.
Si on n'a pas touché l'encodeur rien ne change, A=A_old et B=B_old.
A partir de là on a tout ce qu'il faut pour pondre un algorithme:
Et en tirer un code ASM.
La première partie concerne juste l'initialisation du PIC:
Code : Tout sélectionner
;************************************************************************************************
; F6FCO - Init PIC 18F4525 ;
; ;
;********************************************************************************************** ;
Errorlevel-302
list p=18f4525
#include <p18f4525.inc>
CONFIG OSC = INTIO67 ; Oscillateur interne 8MHz
CONFIG IESO = OFF ; Délai au démarrage (ON/OFF)
CONFIG BOREN = OFF ; Reset si chute de tension (ON/OFF)
CONFIG BORV = 0 ; Tension de reset en 1/10ème Volts
CONFIG WDT = OFF ; Mise hors service du watchdog (ON/OFF)
CONFIG PBADEN = OFF ; PORTB<4:0> les broches sont configurées comme E/S numériques lors de la réinitialisation
CONFIG LPT1OSC = OFF ; Timer1 configuré pour un fonctionnement plus puissant
CONFIG MCLRE = ON ; Mclr configuré comme entrée
CONFIG STVREN = ON ; Reset sur débordement de pile (ON/OFF)
CONFIG LVP = OFF ; Programmation basse tension autorisée (ON/OFF)
CONFIG XINST = OFF ; L'extension du jeu d'instructions et le mode d'adressage indexé sont désactivés(mode hérité)
CONFIG DEBUG = OFF ; Debugger hors service
CONFIG CP0 = OFF ; Code protection sur block 0 (ON/OFF)
CONFIG CP1 = OFF ; Code protection sur block 1 (ON/OFF)
CONFIG CP2 = OFF ; Code protection sur block 2 (ON/OFF)
CONFIG CPB = OFF ; Code protection sur bootblock (ON/OFF)
CONFIG CPD = OFF ; Code protection sur eeprom (ON/OFF)
CONFIG WRT0 = OFF ; Protection écriture block 0 (ON/OFF)
CONFIG WRT1 = OFF ; Protection écriture block 1 (ON/OFF)
CONFIG WRT2 = OFF ; Protection écriture block 2 (ON/OFF)
CONFIG WRTB = OFF ; Protection écriture bootblock (ON/OFF)
CONFIG WRTC = OFF ; Protection écriture configurations (ON/OFF)
CONFIG WRTD = OFF ; Protection écriture zone eeprom (ON/OFF)
CONFIG EBTR0 = OFF ; Protection lecture de table block 0 (ON/OFF)
CONFIG EBTR1 = OFF ; Protection lecture de table block 1 (ON/OFF)
CONFIG EBTR2 = OFF ; Protection lecture de table block 2 (ON/OFF)
CONFIG EBTRB = OFF ; Protection lecture de table bobtfsssssssssssssssotblock (ON/OFF)
; ------------------------------------ #define
;#define EncA PORTD,0
; ------------------------------------
CBLOCK H'0'
EncA_old :1 ; état de la pin A de l'encodeur au tour d'avant
EncB_old :1 ; état de la pin B de l'encodeur au tour d'avant
Sens :1 ; sens de rotation de l'encodeur
Valeur :1
ENDC
ORG H'0'
; ------------------------------------
init
movlw B'01110011'
movwf OSCCON
movlw b'00000000'
movwf TRISC
movwf TRISB
movlw b'00000011' ; les 2 pins de l'encodeur en entrée, ici sur le PORTD
movwf TRISD
La routine de gestion de l'encodeur proprement dite, elle se suffit à elle-même. Ca aurait pu être optimisé au niveau des tests mais pour qu'elle soit portable des 16F aux 18F je n'ai pas utilisé celles spécifiques aux 18F. Il faut déclarer les variables EncA_old, EncB_old et Sens, toutes sur 1 octet. Il suffit ensuite de l'invoquer. L'encodeur est ici câblé sur PORTD,0 et PORTD,1, si on veut changer il ne faut pas oublier de modifier la routine au niveau des comparaisons ANDLW et la valeur du décalage RRNCF.
Code : Tout sélectionner
;------------------------------------------------------------------------------
;
; Gestion encodeur rotatif - F6FCO -
; Octobre 2021
;
; pin A de l'encodeur sur PORTD,0 configurée en input
; pin B de l'encodeur sur PORTD,1 configurée en input
;
; Déclarer les variables:
; EncA_old :1 ; état de la pin A de l'encodeur au tour d'avant
; EncB_old :1 ; état de la pin B de l'encodeur au tour d'avant
; Sens :1 ; sens de rotation de l'encodeur
;-------------------------------------------------------------------------------
Gestion_encodeur
movf PORTD,w
andlw b'00000001'
subwf EncA_old,w
btfsc STATUS,Z
goto enc1
enc3 movf PORTD,w ; est-ce que A=B_old ?
andlw b'00000010'
rrncf WREG,w
subwf EncA_old,w
btfsc STATUS,Z
goto enc4
movlw 1
movwf Sens ; Sens=1 horaire
enc5 movf PORTD,w
andlw b'00000001'
movwf EncA_old
movf PORTD,w
andlw b'00000010'
movwf EncB_old
return
enc1 movf PORTD,W
andlw b'00000010'
subwf EncB_old,w
btfss STATUS,Z
goto enc3
enc2 movlw 2
movwf Sens ; sens=2 encodeur figé
return
enc4 clrf Sens ; Sens=0 anti-horaire
goto enc5
La partie main qui sera variable selon le programme de chacun, ici je me suis contenté pour l'exemple d'incrémenter ou décrementer la variable "Valeur".
Code : Tout sélectionner
#include <encodeur init.asm>
; -----------------------------------
;initialisations variables encodeur
movlw 2
movwf Sens
movf PORTD,w
andlw b'00000001'
movwf EncA_old
movf PORTD,w
andlw b'00000010'
movwf EncB_old
movlw d'127'
movwf Valeur
main
call Gestion_encodeur
movf Sens,w
sublw 2 ; test si Sens=2 inerte
btfsc STATUS,Z
goto fin
movf Sens,w
sublw 1 ; test si Sens =1 horaire
btfsc STATUS,Z
bra horaire
goto AntiHoraire ; sinon antihoraire
horaire decf Valeur
goto fin
AntiHoraire
incf Valeur
fin goto main
; ----------------------------------------
#include <encodeur routines.asm>
end

je n'avais pas vu, sory