; "Cardio-fréquencemètre" ; (C) Fabrice Sincère, février 2007 ; IUT Nancy-Brabois ; version 1.02 ; microcontrôleur PIC 16F628A ; développé avec Microchip MPLAB IDE List p=16F628A ; processeur utilisé #include __config _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF & _DATA_CP_OFF & _BOREN_OFF & _MCLRE_ON ;bits de configuration : ;code protect OFF ;watchdog timer OFF ;power up timer ON ;oscillateur HS (quartz à grande fréquence) ;low voltage program OFF ;data EE read protect OFF ;brown out detect OFF ;master clear enable ON ;xxxxxx ; macro ;xxxxxx bank1 macro ; passage en banque 1 bsf STATUS,RP0 bcf STATUS,RP1 endm bank0 macro ; passage en banque 0 bcf STATUS,RP0 bcf STATUS,RP1 endm ;xxxxxxxxxxxxxxxxxxxxxxxxx ; déclaration de variables ;xxxxxxxxxxxxxxxxxxxxxxxxx CBLOCK H'020' ; début de la zone des registres d'usage général du 16F628A compteur : 1 ; variable de la boucle de temporisation STATUS_TEMP : 1 ; sauvegarde du registre STATUS (routine d'interruption) W_TEMP : 1 ; sauvegarde du registre W (routine d'interruption) afficheur_1 : 1 ; variable de l'afficheur des unités afficheur_10 : 1 ; variable de l'afficheur des dizaines afficheur_100 : 1 ; variable de l'afficheur des centaines buzzer : 1 ; le bit 0 de (buzzer) est utilisé comme drapeau ENDC ;xxxxxxxxxxxxxxxxxxxx ; démarrage sur reset ;xxxxxxxxxxxxxxxxxxxx org H'0000' goto initialisation ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine d'interruption ; 2 sources d'interruptions ; - timer0 (en mode timer) (interruption prioritaire) ; - RB0/INT sur front montant ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx org H'0004' ; vecteur d'interruption movwf W_TEMP swapf STATUS,W movwf STATUS_TEMP ; sauvegarde du registre W puis du registre STATUS btfsc INTCON,T0IF goto inter2 ; on teste s'il s'agit d'une interruption TMR0 btfsc INTCON,INTF goto inter1 ; on teste s'il s'agit d'une interruption RB0/INT goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxx ; gestion interruption RB0/INT ; xxxxxxxxxxxxxxxxxxxxxxxxxxxx inter1 ; on incrémente l'affichage 4 fois de façon à passer de 15 s à 1 min. call conversion call conversion call conversion call conversion bcf INTCON,INTF ; on efface le flag 'RB0/INT External Interrupt' bsf buzzer,0 ; drapeau mis à 1 (autorisation de l'activation du buzzer) goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxx ; gestion interruption timer0 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxx inter2 ; Cette interruption intervient toutes les : ; 256*256(prescaler)*1 µs (quartz 4 MHz) = 65,536 ms ; Le but est de créer une temporisation de 15 secondes (1/4 de minute): ; 229*65,536 ms = 15,0077 secondes incf compteur,f ; on incrémente (compteur) ; on teste si (compteur)=D '229' movlw D'229' subwf compteur,W btfss STATUS,Z goto fin_inter2 ; (compteur) différent de D '229' ; (compteur) égal à D '229' ; mise à jour des afficheurs (rafraîchissement toutes les 15 secondes, ; la valeur affichée est le pouls moyen des 15 dernières secondes) bcf PORTA,0 ; sortie RA0 au niveau bas bcf PORTA,1 ; sortie RA1 au niveau bas bcf PORTA,2 ; sortie RA2 au niveau bas clrf PORTB ; sorties du port B au niveau bas btfsc afficheur_1 , 0 ; on teste le bit 0 de (afficheur_1) bsf PORTB, 1 ; si bit=1 alors RB1 = 1 btfsc afficheur_1 , 1 ; on teste le bit 1 de (afficheur_1) bsf PORTB, 2 ; si bit=1 alors RB2 = 1 btfsc afficheur_1 , 2 ; on teste le bit 2 de (afficheur_1) bsf PORTB, 3 ; si bit=1 alors RB3 = 1 btfsc afficheur_1 , 3 ; on teste le bit 3 de (afficheur_1) bsf PORTB, 4 ; si bit=1 alors RB4 = 1 btfsc afficheur_10 , 0 ; on teste le bit 0 de (afficheur_10) bsf PORTB, 5 ; si bit=1 alors RB5 = 1 btfsc afficheur_10 , 1 ; on teste le bit 1 de (afficheur_10) bsf PORTB, 6 ; si bit=1 alors RB6 = 1 btfsc afficheur_10 , 2 ; on teste le bit 2 de (afficheur_10) bsf PORTB, 7 ; si bit=1 alors RB7 = 1 btfsc afficheur_10 , 3 ; on teste le bit 3 de (afficheur_10) bsf PORTA, 0 ; si bit=1 alors RA0 = 1 btfsc afficheur_100 , 0 ; on teste le bit 0 de (afficheur_100) bsf PORTA, 1 ; si bit=1 alors RA1 = 1 btfsc afficheur_100 , 1 ; on teste le bit 1 de (afficheur_100) bsf PORTA, 2 ; si bit=1 alors RA2 = 1 clrf afficheur_1 clrf afficheur_10 clrf afficheur_100 clrf compteur fin_inter2 bcf PORTA, 3 ; RA3 = 0 (buzzer inactif) btfss buzzer,0 ; on teste le drapeau goto suite ; si drapeau = 0 bsf PORTA, 3 ; si drapeau = 1 alors RA3 = 1 (buzzer actif pendant 65,536 ms) bcf buzzer,0 ; on efface le drapeau suite bcf INTCON,T0IF ; on efface le flag 'TMR0 Overflow Interrupt' 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 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine de conversion binaire -> BCD ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx conversion incf afficheur_1,f ; on teste si (afficheur_1)=B'00001010' movlw B'00001010' subwf afficheur_1,W btfss STATUS,Z return ; (afficheur_1) différent de B'00001010' ; (afficheur_1) égal à B'00001010' clrf afficheur_1 incf afficheur_10,f ; on teste si (afficheur_10)=B'00001010' movlw B'00001010' subwf afficheur_10,W btfss STATUS,Z return ; (afficheur_10) différent de B'00001010' ; (afficheur_10) égal à B'00001010' clrf afficheur_10 incf afficheur_100,f return ;xxxxxxxxxxxxxxx ; initialisation ;xxxxxxxxxxxxxxx initialisation bank0 clrf PORTA ; mise à 0 des sorties du port A clrf PORTB ; mise à 0 des sorties du port B movlw B'00000111' movwf CMCON ; inactivation des comparateurs analogiques bank1 movlw B'11000111' movwf OPTION_REG ; bit 7 (/RBPU) = 1 : désactivation des résistances de pull-up du port B ; bit 6 (INTEDG)= 1 : Interrupt on rising edge of RB0/INT pin ; bit 5 (T0CS) = 0 : Timer0 Clock Source Select = CLKOUT ; bit 3 (PSA) = 0 : Prescaler attribué au Timer0 ; bit 2 (PS2)= 1 ; bit 1 (PS1) = 1 ; bit 0 (PS0) = 1 : Facteur de division du prescaler = 1:256 ; bit 4 : ici, option non utilisée (= 0, par exemple) movlw B'00010000' movwf TRISA ; bit 0 du port A (RA0) = 0 : configuration en sortie ; (vers entrée D du 74LS47 - afficheur 7 segments des dizaines) ; bit 1 du port A (RA1) = 0 : configuration en sortie ; (vers entrée A du 74LS47 - afficheur 7 segments des centaines) ; bit 2 du port A (RA2) = 0 : configuration en sortie ; (vers entrée B du 74LS47 - afficheur 7 segments des centaines) ; bit 3 du port A (RA3) = 0 : configuration en sortie ; (commande du buzzer) ; bit 4 du port A (RA4) = 1 : non utilisés ; (configuration en entrée, par exemple) movlw B'00000001' movwf TRISB ; bit 0 du port B (RB0) = 1 : configuration en entrée ; bit 1 du port B (RB1) = 0 : configuration en sortie ; (vers entrée A du 74LS47 - afficheur 7 segments des unités) ; bit 2 du port B (RB2) = 0 : configuration en sortie ; (vers entrée B du 74LS47 - afficheur 7 segments des unités) ; bit 3 du port B (RB3) = 0 : configuration en sortie ; (vers entrée C du 74LS47 - afficheur 7 segments des unités) ; bit 4 du port B (RB4) = 0 : configuration en sortie ; (vers entrée D du 74LS47 - afficheur 7 segments des unités) ; bit 5 du port B (RB5) = 0 : configuration en sortie ; (vers entrée A du 74LS47 - afficheur 7 segments des dizaines) ; bit 6 du port B (RB6) = 0 : configuration en sortie ; (vers entrée B du 74LS47 - afficheur 7 segments des dizaines) ; bit 7 du port B (RB7) = 0 : configuration en sortie ; (vers entrée C du 74LS47 - afficheur 7 segments des dizaines) ; affichage possible de 000 à 399 bank0 movlw B'10110000' movwf INTCON ; bit 7 (GIE) = 1 : autorisation globale des interruptions ; bit 5 (T0IE)= 1 : autorisation de l'interruption de débordement du Timer0 ; bit 4 (INTE) = 1 : Enables the RB0/INT external interrupt ; bit 2 (T0IF) = 0 : on efface le flag 'TMR0 Overflow Interrupt' ; bit 1 (INTF)= 0 : on efface le flag 'RB0/INT External Interrupt' ; les autres bits sont inutilisés (valeur par défaut = 0) clrf PORTA ; sorties du port A au niveau bas clrf PORTB ; sorties du port B au niveau bas ; les afficheurs indiquent donc 000 ; buzzer inactif clrf compteur ; mise à zero du compteur clrf TMR0 ; mise à zero du timer0 clrf afficheur_1 clrf afficheur_10 clrf afficheur_100 goto debut_programme ;xxxxxxxxxxxxxxxxxxxxx ; programme principal ;xxxxxxxxxxxxxxxxxxxxx debut_programme goto 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 END