; "Compteur 4 digits" ; (C) Fabrice Sincère, 12/2010 ; IUT Nancy-Brabois ; version 1.0.7 ; microcontrôleur PIC 16F84A ; développé avec Microchip MPLAB IDE List p=16F84A ; processeur utilisé #include __config _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC ;bits de configuration : ;code protect OFF ;watchdog timer OFF ;power up timer ON ;oscillateur HS (quartz 20 MHz) ;xxxxxx ; macro ;xxxxxx bank1 macro ; passage en banque 1 bsf STATUS,RP0 endm bank0 macro ; passage en banque 0 bcf STATUS,RP0 endm ;xxxxxxxxxxxxxxxxxxxxxxxxx ; déclaration de variables ;xxxxxxxxxxxxxxxxxxxxxxxxx CBLOCK H'00C' ; début de la zone des registres d'usage général du 16F84A digit : 1 ; variable qui indique n° de l'afficheur actif (1 à 4) STATUS_TEMP : 1 ; sauvegarde du registre STATUS (routine d'interruption) W_TEMP : 1 ; sauvegarde du registre W (routine d'interruption) afficheur_4 : 1 ; contient le chiffre des unités à afficher (codage BCD) afficheur_3 : 1 ; contient le chiffre des dizaines à afficher (codage BCD) afficheur_2 : 1 ; contient le chiffre des centaines à afficher (codage BCD) afficheur_1 : 1 ; contient le chiffre des milliers à afficher (codage BCD) afficheur : 1 ; contient le chiffre actif à afficher (codage BCD) compt_BPplus : 1 ; variable de la temporisation anti-rebonds du BP "PLUS" compt_BPmoins : 1 ; variable de la temporisation anti-rebonds du BP "MOINS" flag_BPmoins :1 ; drapeau mis à 1 lors d'un front montant sur le BP "MOINS" ; (on utilise le bit 0) flag_tempoBPmoins : 1 ; drapeau mis à 1 lors du debut de la temporisation ; anti-rebonds du BP "MOINS" (on utilise le bit 0) BPmoins_bak ; niveau antérieur sur le BP "MOINS" (on utilise le bit 0) ENDC ;xxxxxxxxxxxxxxxxxxxx ; démarrage sur reset ;xxxxxxxxxxxxxxxxxxxx org H'0000' goto initialisation ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine d'interruption ; 2 source d'interruption ; - RB0/INT sur front montant ; - TMR0 en mode timer ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx org H'0004' ; vecteur d'interruption movwf W_TEMP swapf STATUS,W movwf STATUS_TEMP ; sauvegarde du registre W puis du registre STATUS btfss INTCON,INTE goto suite0 ; on vérifie que l'interruption RB0/INT est autorisée ; (car cette interruption est désactivée pendant la temporisation ; de l'anti-rebonds) btfsc INTCON,INTF goto inter1 ; si oui : on teste le drapeau de l'interruption RB0/INT suite0 btfsc INTCON,T0IF goto inter2 ; on teste s'il s'agit bien d'une interruption TMR0 goto restauration ; (par précaution) ; xxxxxxxxxxxxxxxxxxxxxxxxxxxx ; gestion interruption RB0/INT ; xxxxxxxxxxxxxxxxxxxxxxxxxxxx inter1 ; Antirebonds ; L'interruption RB0/INT est désactivée pendant 60*3,3 ms # 200 ms movlw D'60' movwf compt_BPplus call conversion_plus bcf INTCON,INTE ; on désactive l'interruption RB0/INT bcf INTCON,INTF ; on efface le drapeau RB0/INT goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; gestion de l'interruption TMR0 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx inter2 ; Cette interruption a lieu toutes les : ; 0,2 µs*256*64 (prescaler) = 3,3 ms call tempo_BPplus ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Rafraîchissement de l'affichage ; Les 4 afficheurs sont multiplixés ; On active les afficheurs les uns après les autres (un toutes les 4 ms) decf digit, f ; on change d'afficheur 4->3->2->1->4-> etc btfss STATUS, Z goto suite movlw D'4' movwf digit suite ; on alimente l'afficheur correspondant movlw D'1' subwf digit, W btfss STATUS, Z goto digit2 ; (digit) différent de 1 movlw B'00011100' movwf PORTA ; RA1=0 : afficheur1 alimenté movf afficheur_1, W movwf afficheur ; on charge (afficheur_1) dans (afficheur) goto fin digit2 movlw D'2' subwf digit, W btfss STATUS, Z goto digit3 ; (digit) différent de 2 movlw B'00011010' movwf PORTA ; RA2=0 : afficheur2 alimenté movf afficheur_2, W movwf afficheur ; on charge (afficheur_2) dans (afficheur) goto fin digit3 movlw D'3' subwf digit, W btfss STATUS, Z goto digit4 ; (digit) différent de 3 movlw B'00010110' movwf PORTA ; RA3=0 : afficheur3 alimenté movf afficheur_3, W movwf afficheur ; on charge (afficheur_3) dans (afficheur) goto fin digit4 movlw D'4' subwf digit, W btfss STATUS, Z goto fin ; (digit) différent de 4 movlw B'00001110' movwf PORTA ; RA4=0 : afficheur4 alimenté movf afficheur_4, W movwf afficheur ; on charge (afficheur_4) dans (afficheur) goto fin fin call conversion7 ; test du bouton poussoir "MOINS" call moins bcf INTCON,T0IF ; on efface le drapeau T0IF goto restauration restauration swapf STATUS_TEMP,W ; restauration des registres STATUS puis W movwf STATUS swapf W_TEMP,f swapf W_TEMP,W retfie ; retour d'interruption ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine "tempo_BPplus" ; temporisation anti-rebonds 200 ms (bouton poussoir "PLUS") tempo_BPplus btfsc INTCON,INTE return ; INTE = 1 decf compt_BPplus,f ; INTE = 0 btfss STATUS, Z return ; compt_BPplus < > 0 ; compt_BPplus = 0 : fin de la temporisation bsf INTCON,INTE ; on réautorise l'interruption RB0/INT bcf INTCON,INTF ; on efface le drapeau RB0/INT return ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine de gestion de l'interrupteur "MOINS" ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; quand on appuie sur ce bouton (sur front montant), on décrémente le compteur. ; la durée de la temporisation pour l'anti-rebonds est 60*3,3 ms # 200 ms moins ; test front montant btfss PORTB,1 goto suit2 ; BP "MOINS" au niveau bas btfsc BPmoins_bak,0 ; BP "MOINS" au niveau haut goto suit2 ; BP "MOINS" au niveau haut (3,3 ms avant) bsf flag_BPmoins,0 ; drapeau mis à 1 suit2 bcf BPmoins_bak,0 btfsc PORTB,1 bsf BPmoins_bak,0 ; mémorisation du niveau du BP "MOINS" ; test du drapeau de début de tempo btfss flag_tempoBPmoins,0 goto suit3 ; drapeau tempo à 1 decf compt_BPmoins,f btfsc STATUS,Z ; on teste si (compt_BPmoins) est nul goto suit4 return ; (compt_BPmoins) est non nul suit4 ; (compt_BPmoins) est nul ; fin de temporisation bcf flag_tempoBPmoins,0 ; drapeau remis à 0 bcf flag_BPmoins,0 ; drapeau remis à 0 return suit3 ; drapeau tempo à 0 ; test du drapeau front montant btfss flag_BPmoins,0 return ; drapeau front montant à 0 ; drapeau front montant à 1 ; début temporisation bsf flag_tempoBPmoins,0 ; drapeau mis à 1 movlw D'60' movwf compt_BPmoins call conversion_moins ; mise à jour affichage return ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine "conversion_plus" ; Incrémentation du compteur (codage BCD) ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx conversion_plus incf afficheur_4,f ; on teste si (afficheur_4)=D'10' movlw D'10' subwf afficheur_4,W btfss STATUS,Z return ; (afficheur_4) différent (inférieur à) de D'10' ; (afficheur_4) égal à D'10' clrf afficheur_4 incf afficheur_3,f ; on teste si (afficheur_3)=D'10' movlw D'10' subwf afficheur_3,W btfss STATUS,Z return ; (afficheur_3) différent de D'10' ; (afficheur_3) égal à D'10' clrf afficheur_3 incf afficheur_2,f ; on teste si (afficheur_2)=D'10' movlw D'10' subwf afficheur_2,W btfss STATUS,Z return ; (afficheur_2) différent de D'10' ; (afficheur_2) égal à D'10' clrf afficheur_2 incf afficheur_1,f ; on teste si (afficheur_1)=D'10' movlw D'10' subwf afficheur_1,W btfss STATUS,Z return ; (afficheur_1) différent de D'10' clrf afficheur_1 return ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine "conversion_moins" ; décrémentation du compteur (codage BCD) ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx conversion_moins decf afficheur_4,f ; on teste si (afficheur_4)=D'255' movlw D'255' subwf afficheur_4,W btfss STATUS,Z return ; (afficheur_4) différent de D'255' ; (afficheur_4) égal à D'255' movlw D'9' movwf afficheur_4 decf afficheur_3,f ; on teste si (afficheur_3)=D'255' movlw D'255' subwf afficheur_3,W btfss STATUS,Z return ; (afficheur_3) différent de D'255' ; (afficheur_3) égal à D'255' movlw D'9' movwf afficheur_3 decf afficheur_2,f ; on teste si (afficheur_2)=D'255' movlw D'255' subwf afficheur_2,W btfss STATUS,Z return ; (afficheur_2) différent de D'255' ; (afficheur_2) égal à D'10' movlw D'9' movwf afficheur_2 decf afficheur_1,f ; on teste si (afficheur_1)=D'255' movlw D'255' subwf afficheur_1,W btfss STATUS,Z return ; (afficheur_1) différent de D'255' movlw D'9' movwf afficheur_1 return ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine de conversion BCD -> 7 segments ; et commande de l'afficheur actif ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx conversion7 movlw D'0' subwf afficheur, W btfss STATUS, Z goto valeur1 ; (afficheur) différent de 0 movlw B'00000000' movwf PORTB bsf PORTA,0 ; on affiche 0 return valeur1 movlw D'1' subwf afficheur, W btfss STATUS, Z goto valeur2 ; (afficheur) différent de 1 movlw B'11100100' movwf PORTB bsf PORTA,0 ; on affiche 1 return valeur2 movlw D'2' subwf afficheur, W btfss STATUS, Z goto valeur3 ; (afficheur) différent de 2 movlw B'10010000' movwf PORTB bcf PORTA,0 ; on affiche 2 return valeur3 movlw D'3' subwf afficheur, W btfss STATUS, Z goto valeur4 ; (afficheur) différent de 3 movlw B'11000000' movwf PORTB bcf PORTA,0 ; on affiche 3 return valeur4 movlw D'4' subwf afficheur, W btfss STATUS, Z goto valeur5 ; (afficheur) différent de 4 movlw B'01100100' movwf PORTB bcf PORTA,0 ; on affiche 4 return valeur5 movlw D'5' subwf afficheur, W btfss STATUS, Z goto valeur6 ; (afficheur) différent de 5 movlw B'01001000' movwf PORTB bcf PORTA,0 ; on affiche 5 return valeur6 movlw D'6' subwf afficheur, W btfss STATUS, Z goto valeur7 ; (afficheur) différent de 6 movlw B'00001100' movwf PORTB bcf PORTA,0 ; on affiche 6 return valeur7 movlw D'7' subwf afficheur, W btfss STATUS, Z goto valeur8 ; (afficheur) différent de 7 movlw B'11100000' movwf PORTB bsf PORTA,0 ; on affiche 7 return valeur8 movlw D'8' subwf afficheur, W btfss STATUS, Z goto valeur9 ; (afficheur) différent de 8 movlw B'00000000' movwf PORTB bcf PORTA,0 ; on affiche 8 return valeur9 movlw D'9' subwf afficheur, W btfss STATUS, Z return ; (par précaution) movlw B'01100000' movwf PORTB bcf PORTA,0 ; on affiche 9 return ;xxxxxxxxxxxxxxx ; initialisation ;xxxxxxxxxxxxxxx initialisation bank0 clrf PORTA ; mise à 0 des sorties du port A clrf PORTB ; mise à 0 des sorties du port B bank1 movlw B'01000101' movwf OPTION_REG ; bit 7 (/RBPU) = 0 : activation des résistances de pull-up du port B ; bit 6 (INTEDG)= 1 : interruption RB0/INT sur front montant ; bit 5 (T0CS) = 0 : Timer0 Clock Source Select = CLKOUT ; bit 3 (PSA) = 0 : Prescaler attribué au module TMR0 ; bit 2 (PS2)= 1 ; bit 1 (PS1) = 0 ; bit 0 (PS0) = 1 : Facteur de division du prescaler = 1:64 ; bit 4 : ici, option non utilisée (= 0, par exemple) movlw B'00000000' movwf TRISA ; bit 0 du port A (RA0) = 0 : configuration en sortie (segment G) ; bit 1 du port A (RA1) = 0 : configuration en sortie (afficheur 1 : chiffre des milliers) ; bit 2 du port A (RA2) = 0 : configuration en sortie (afficheur 2 : chiffre des centaines) ; bit 3 du port A (RA3) = 0 : configuration en sortie (afficheur 3 : chiffre des dizaines) ; bit 4 du port A (RA4) = 0 : configuration en sortie (afficheur 4 : chiffre des unités) movlw B'00000011' movwf TRISB ; bit 0 du port B (RB0) = 1 : configuration en entrée (bouton poussoir PLUS) ; bit 1 du port B (RB1) = 1 : configuration en entrée (bouton poussoir MOINS) ; bit 2 du port B (RB2) = 0 : configuration en sortie (segment A) ; bit 3 du port B (RB3) = 0 : configuration en sortie (segment B) ; bit 4 du port B (RB4) = 0 : configuration en sortie (segment C) ; bit 5 du port B (RB5) = 0 : configuration en sortie (segment D) ; bit 6 du port B (RB6) = 0 : configuration en sortie (segment E) ; bit 7 du port B (RB7) = 0 : configuration en sortie (segment F) ; affichage possible de 0000 à 9999 bank0 movlw B'10110000' movwf INTCON ; bit 7 (GIE) = 1 : autorisation globale des interruptions ; bit 5 (T0IE) = 1 : autorisation de l'interruption TMR0 ; bit 4 (INTE) = 1 : autorisation de l'interruption RB0/INT (bouton poussoir PLUS) ; bit 2 (T0IF)= 0 : on efface le drapeau de l'interruption TMR0 ; bit 1 (INTF)= 0 : on efface le drapeau de l'interruption RB0/INT ; les autres bits sont inutilisés (valeur par défaut = 0) clrf PORTA ; sorties du port A au niveau bas ; les afficheurs sont donc éteints clrf TMR0 ; mise à zero du timer0 clrf afficheur_1 clrf afficheur_2 clrf afficheur_3 clrf afficheur_4 clrf afficheur movlw D'4' movwf digit movlw D'60' movwf compt_BPplus movwf compt_BPmoins clrf flag_BPmoins clrf flag_tempoBPmoins bsf BPmoins_bak,0 goto debut_programme ;xxxxxxxxxxxxxxxxxxxxx ; programme principal ;xxxxxxxxxxxxxxxxxxxxx debut_programme ; on attend le débordement de TMR0 (H'FF' -> H'00') ; ou un front montant sur l'entrée RB0/INT, ; ce qui génére une interruption goto debut_programme END