;********************************************************************** ; ; NOM: Mpap_F84.asm ; Date: 21/08/2001 modifié le 22 ; Version: V1.2 ; Circuit: Carte Moteur pas à pas gérée par PIC 16F84 ; Auteur: ACQUIER Bernard ; ;********************************************************************** ; * ; Fichier requis: P16F84.inc * ; * ;********************************************************************** ; Notes: ; La carte Moteur pas à pas géré par PIC 16F84, reçoit des ordres ; grâce à la liaison RS485. Cette carte doit piloter 2 moteurs ; pas à pas unipolaire. ; U(p), D(own): Qui fera tourner un moteur dans un sens ou dans l'autre. ; R(ight), L(eft): idem mais pour l'autre moteur. ; S(top): pour arréter les deux à la fois, mais laisser les moteurs alimentées. ; H(alt): pour arréter les deux à la fois, mais ne plus alimenter les moteurs. ; E(xterne) pour activer le relais. ; e(xterne) aussi, mais pour désactiver le relais. ; La vitesse est constante et elle est réglée par le PIC (pas d'IRQ TIMER). ; La carte ne répond pas, elle exécute, c'est tout! ; ; L'indicateur MODE permet de signaler ce que fait le PIC ; MODE_RXD indique qu'il reçoit un code sur la RS485 ; MODE_M1 indique si le moteur M1 tourne ou non. port RA0--RA3 ; MODE_M2 indique si le moteur M2 tourne ou non. port RB4--RB7 ; MODE_UD indique le sens du moteur M1 Up ou Down. ; MODE_RL indique le sens du moteur M2 Right ou Left. ; ; Les pas sont en RAM et indique les phases des sorties RA0--RA3 et RB4--RB7. ; PAS0($99), PAS1($33), PAS2($66), PAS3($CC), même valeur 4bits MSB = 4bits LSB ; pour chaque moteur. en fait PAS0 = PAS+0, PAS1 = PAS+1,.....PAS3 = PAS+3 ; ; Il faut aussi 2 compteurs cmptM1 et cmptM2 indiquant sur quel PAS il se trouve ; de PAS0 à PAS3, donc ils comptent de 0 à 3. ; et si cmptM1(2) = 4 alors = 0. ; et si cmptM1(2) = $FF alors = 3, pour un sens inverse. ; ;********************************************************************** LIST p=16F84 ; Définition de processeur #include ; Définitions des constantes __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC ; '__CONFIG' précise les paramètres encodés dans le processeur au moment de ; la programmation du processeur. Les définitions sont dans le fichier include. ; Voici les valeurs et leurs définitions : ; _CP_ON Code protection ON : impossible de relire ; _CP_OFF Code protection OFF ; _PWRTE_ON Timer reset sur power on en service ; _PWRTE_OFF Timer reset hors-service ; _WDT_ON Watch-dog en service ; _WDT_OFF Watch-dog hors service ; _LP_OSC Oscillateur quartz basse vitesse ; _XT_OSC Oscillateur quartz moyenne vitesse ; _HS_OSC Oscillateur quartz grande vitesse ; _RC_OSC Oscillateur à réseau RC ;********************************************************************* ; ASSIGNATIONS * ;********************************************************************* OPTIONVAL EQU b'00000111' ; Valeur registre option ; Résistance pull-up ON ; Interrupt flanc descendant RB0 ; Préscaler timer à 256 (exemple) INTERMASK EQU b'10010000' ; Masque d'interruption ; Interruptions sur RB0 (exemple) et GIE C_PORTA EQU b'00010000' ; A0 à A3 en sorties, RA4 enentrée (Config PORTA) C_PORTB EQU b'00000001' ; B0 en entrée, B2 à B7 en sorties (Config PORTB) PAS0 EQU 0x99 ; Config sorties pour actionner chaque phase moteur PAS1 EQU 0x33 PAS2 EQU 0x66 PAS3 EQU 0xCC ;********************************************************************* ; DEFINE * ;********************************************************************* ; #DEFINE Relais PORTB,3 ; Relais de sortie 1 #DEFINE MODE_RXD MODE,0 ; Nous sommes en réception d'un caractère ; sur RS485 #DEFINE MODE_M1 MODE,1 ; indique si le moteur M1 tourne ou non. #DEFINE MODE_M2 MODE,2 ; indique si le moteur M2 tourne ou non. ; #DEFINE MODE_UD MODE,3 ; indique le sens du moteur M1 Up ou Down. #DEFINE MODE_RL MODE,4 ; indique le sens du moteur M1 Right ou Left. ; #DEFINE RELAIS PORTB,3 ; indique le port qui (des)active le relais ;********************************************************************* ; MACRO * ;********************************************************************* BANK0 macro bcf STATUS , RP0 ; passer banque0 endm BANK1 macro bsf STATUS , RP0 ; passer banque1 endm ; ; #Include ; Macro Lecture / Ecriture EEPROM ; et eventuellement ses paramètres ; à mettre pdt sa programmation ;********************************************************************* ; DECLARATIONS DE VARIABLES * ;********************************************************************* ;exemples ;--------- CBLOCK 0x00C ; début de la zone variables w_temp :1 ; Sauvegarde du registre W status_temp : 1 ; Sauvegarde du registre STATUS MODE :1 ; permet de savoir le mode de travail PAS :4 ; allocation des PAS cmptM1 :1 ; compteur simple pour moteur M1 cmptM2 :1 ; compteur simple pour moteur M2 TEMP :1 ; TEMPoraire ENDC ; Fin de la zone ;********************************************************************** ; DEMARRAGE SUR RESET * ;********************************************************************** org 0x000 ; Adresse de départ après reset goto init ; Adresse 0: initialiser ;********************************************************************** ; ROUTINE INTERRUPTION * ;********************************************************************** ;sauvegarder registres ;--------------------- org 0x004 ; adresse d'interruption movwf w_temp ; sauver registre W swapf STATUS,w ; swap status avec résultat dans w movwf status_temp ; sauver status swappé ; intsw1 btfsc INTCON,INTE ; tester si interrupt RB0 autorisée btfss INTCON,INTF ; oui, tester si interrupt RB0 en cours goto restoreg ; non sauter au test suivant call intrb0 ; oui, traiter interrupt RB0 bcf INTCON,INTF ; effacer flag interupt RB0 restoreg; swapf status_temp,w ; swap ancien status, résultat dans w movwf STATUS ; restaurer status swapf w_temp,f ; Inversion L et H de l'ancien W ; sans modifier Z swapf w_temp,w ; Réinversion de L et H dans W ; W restauré sans modifier status retfie ; return from interrupt ;********************************************************************** ; INTERRUPTION RB0/INT * ;********************************************************************** intrb0 bsf MODE_RXD ; Flanc descendant sur RB0 call RECEPT ; Reception octets (dans l'IRQ) return ; fin d'interruption RB0/INT ; peut être remplacé par ; retlw pour retour code d'erreur ;********************************************************************* ; INITIALISATIONS * ;********************************************************************* init BANK0 CLRF INTCON ; aucune interruptions autorisées clrf PORTA ; Sorties portA à 0 clrf PORTB ; sorties portB à 0 BANK1 ; passer banque1 movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option MOVLW C_PORTA ; E / S PORTA MOVWF TRISA ; MOVLW C_PORTB ; E / S PORTB MOVWF TRISB ; ; Effacer RAM ; ------------ movlw 0x0c ; initialisation pointeur movwf FSR ; pointeur d'adressage indirect init1 clrf INDF ; effacer ram incf FSR,f ; pointer sur suivant btfss FSR,6 ; tester si fin zone atteinte (>=40) goto init1 ; non, boucler btfss FSR,4 ; tester si fin zone atteinte (>=50) goto init1 ; non, boucler ;Initialiser les PAS ;------------------- BANK0 ; passer banque0 movlw PAS0 movwf PAS movlw PAS1 movwf PAS+1 movlw PAS2 movwf PAS+2 movlw PAS3 movwf PAS+3 ; movlw INTERMASK ; masque interruption movwf INTCON ; charger interrupt control ;********************************************************************* ; PROGRAMME PRINCIPAL * ;********************************************************************* start btfsc MODE_RXD ; a t'on reçu un caractère? call DECOD ; Oui et on va le traiter. btfsc MODE_M1 ; doit-on faire tourner le moteur M1 call ROTM1 ; oui btfsc MODE_M2 ; doit-on faire tourner le moteur M2 call ROTM2 ; oui call TEMPO ; entre chaque phase Moteur... ; cela évite une IRQ Timer goto start ; et l'on boucle. ; ; DECOD bcf MODE_RXD ;comme on le traite, on l'efface. decodU movlw A'U' ; caractère ASCII 'U'? comme Up XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decodD ; comme Down bsf MODE_M1 ; le moteur M1 est actif bcf MODE_UD ; Up=0 et Down=1 RETURN decodD movlw A'D' ; caractère ASCII 'D'? comme Down XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decodR ; comme Right bsf MODE_M1 ; le moteur M1 est actif bsf MODE_UD ; Up=0 et Down=1 RETURN decodR movlw A'R' ; caractère ASCII 'R'? comme Right XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decodL ; comme Left bsf MODE_M2 ; le moteur M2 est actif bcf MODE_RL ; Right=0 et Left=1 RETURN decodL movlw A'L' ; caractère ASCII 'L'? comme Left XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decodS ; comme Stop bsf MODE_M2 ; le moteur M2 est actif bsf MODE_RL ; Right=0 et Left=1 RETURN decodS movlw A'S' ; caractère ASCII 'S'? comme Stop XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decodH ; comme Halt bcf MODE_M1 ; le moteur M1 est inactif bcf MODE_M2 ; le moteur M2 est inactif RETURN decodH movlw A'H' ; caractère ASCII 'H'? comme Halt XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decodE ; comme E(xterne) bcf MODE_M1 ; le moteur M1 est inactif bcf MODE_M2 ; le moteur M2 est inactif clrf PORTA ; Moteur éteint movf PORTB,w ; lecture du port andlw 0x0F ; pour ne pas influencer RB0 à RB3 movwf PORTB ; et l'on envoie le tout sans avoir modifié RB0 à RB3. RETURN decodE movlw A'E' ; caractère ASCII 'E'? comme Externe XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité goto decode ; comme e(xterne) mais désactive le relais bsf RELAIS ; le relais est activé RETURN decode movlw A'e' ; caractère ASCII 'e'? comme externe aussi XORWF XmtReg,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité RETURN ; Caractère non traité, donc on ignore!!!! bcf RELAIS ; le relais est desactivé RETURN ; ; ROTM1 movlw PAS ; on prend l'adresse dans w addwf cmptM1,w ; de toute façon, on commence à 0 ; le traitement d'incrémentation se fera après. movwf FSR ; pointeur d'adressage indirect movf INDF,w ; on lit la valeur à envoyer sur le port andlw 0x0F ; RA4 est une entrée, donc no problem! movwf PORTA ; et l'on envoie... ; On incrémente ou décrémente le compteur cmptM1 btfsc MODE_UD ; Up ou Down? goto ROTDown ROTUp incf cmptM1,f movlw 0x04 ; à 4? XORWF cmptM1,W ; On compare au registre de sauvegarde caractère BTFSC STATUS,Z ; Si Z=1, égalité clrf cmptM1 ; on repart à 0 RETURN ; on termine là si Up ROTDown decf cmptM1,f movlw 0xFF ; à ff? ---> 0 - 1 = ff XORWF cmptM1,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité RETURN movlw 0x03 ; on va en bout de liste movwf cmptM1 RETURN ROTM2 movlw PAS ; on prend l'adresse dans w addwf cmptM2,w ; de toute façon, on commence à 0 ; le traitement d'incrémentation se fera après. movwf FSR ; pointeur d'adressage indirect movf INDF,w ; on lit la valeur à envoyer sur le port andlw 0xF0 ; le lsb ne compte pas car sur RB4 à RB7 movwf TEMP ; en Temporaire movf PORTB,w ; lecture du port andlw 0x0F ; pour ne pas influencer RB0 à RB3 iorwf TEMP,w ; un OU tout simple movwf PORTB ; et l'on envoie le tout sans avoir modifié RB0 à RB3. ; On incrémente ou décrémente le compteur cmptM1 btfsc MODE_RL ; Right ou Left ? goto ROTLeft ROTRight incf cmptM2,f movlw 0x04 ; à 4? XORWF cmptM2,W ; On compare au registre de sauvegarde caractère BTFSC STATUS,Z ; Si Z=1, égalité clrf cmptM2 ; on repart à 0 RETURN ; on termine là si Up ROTLeft decf cmptM2,f movlw 0xFF ; à ff? ---> 0 - 1 = ff XORWF cmptM2,W ; On compare au registre de sauvegarde caractère BTFSS STATUS,Z ; Si Z=1, égalité RETURN movlw 0x03 ; on va en bout de liste movwf cmptM2 RETURN TEMPO ; de 2ms movlw 0xFF ; le maximum movwf TEMP ; autant qu'il serve loop nop nop nop nop nop nop decfsz TEMP,f ; 9µs*256 = 2.304ms goto loop RETURN #Include END ; directive fin de programme