;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Nom du projet : dé électronique (version B) ; (C) Fabrice Sincère, juin 2008 ; IUT de Nancy-Brabois ; http://pagesperso-orange.fr/fabrice.sincere ; Version 1.0.3 ; Microcontrôleur PIC 16F84A ; Microchip MPLAB IDE 7.41 ; Langage : assembleur ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Errorlevel-302 ; Supprime le message "Ensure that bank bits are correct" ;xxxxxxxxxxx ; Processeur ;xxxxxxxxxxx List p=16F84A #include ;xxxxxxxxxxxxxxxxxxxxxx ; Bits de configuration ;xxxxxxxxxxxxxxxxxxxxxx __config _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC ;code protect OFF ;watchdog timer OFF ;power up timer ON ;oscillateur RC : f OSC1 # 260 kHz ;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 ;xxxxxxxxxxxxxxxxxxxxxxxxxxx ; Déclaration des variables ;xxxxxxxxxxxxxxxxxxxxxxxxxxx CBLOCK 0x0C W_TEMP : 1 ; adresse 0x0C STATUS_TEMP : 1 ; adresse 0x0D compteur1 : 1 compteur2 : 1 valeurfaciale : 1 etat : 1 ; (00000001) : état initial (animation à la mise sous tension) ; (00000010) : rotation ; (00000100) : séquence sonore finrotation : 1 ; bit 0 mis à 1 si le disque est arrêté depuis plus de 2 secondes cycle : 1 ; dans la séquence sonone : n° de cycle de la salve compteursalve : 1 ENDC ;xxxxxxxxxxxxxxxxxxxx ; Démarrage sur reset ;xxxxxxxxxxxxxxxxxxxx org 0x0000 goto initialisation ;xxxxxxxxxxxxxxxxxxxxxxx ; Routine d'interruption ; 2 sources d'interruptions : ; -> TMR0 ; -> RB0/INT ;xxxxxxxxxxxxxxxxxxxxxxx org 0x0004 ; vecteur d'interruption movwf W_TEMP ; sauvegarde des registres W et STATUS swapf STATUS,W movwf STATUS_TEMP ; on teste s'il s'agit de l'interruption TMR0 btfss INTCON , T0IE goto inter1 btfsc INTCON , T0IF goto interruption_TMR0 ; on teste s'il s'agit de l'interruption RB0/INT inter1 btfss INTCON , INTE goto restauration btfsc INTCON , INTF goto interruption_RB0 goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Traitement de l'interruption TMR0 interruption_TMR0 btfsc etat , 0 goto etatinitial btfsc etat , 1 goto testfinrotation goto sequencesonore etatinitial ; Animation à la mise sous tension ; Fréquence de l'interruption (prescaler 1:64) : ; 260 000 / (4*256*64) # 4 Hz ; on teste (compteur2) ; si (compteur2) > 2 alors goto finTMR0 movf compteur2 , W ; W = (compteur2) sublw 0x02 ; W = 0x02 - (compteur2) btfsc STATUS, C ; test du bit C (Carry) goto compteur1_00 ; C = 1 c'est-à-dire (compteur2) <= 0x02 goto finTMR0 compteur1_00 ; compteur1 = .0 ? movlw 0x00 ; W = 0x00 subwf compteur1, W ; W = (compteur1) - 0x00 btfss STATUS, Z ; test du bit Z goto compteur1_01 ; Z = 0 c'est-à-dire (compteur1) != 0x00 movlw B'11111111' movwf PORTB ; on éteint toutes les LEDs goto suiteTMR0 ; compteur1 = .1 ? compteur1_01 movlw 0x01 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_02 ; Z = 0 c'est-à-dire (compteur1) != 0x01 movlw B'11111101' movwf PORTB ; on allume la LED1 goto suiteTMR0 ; compteur1 = .2 ? compteur1_02 movlw 0x02 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_03 ; Z = 0 c'est-à-dire (compteur1) != 0x02 movlw B'11111001' movwf PORTB goto suiteTMR0 ; compteur1 = .3 ? compteur1_03 movlw 0x03 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_04 ; Z = 0 c'est-à-dire (compteur1) != 0x03 movlw B'11110001' movwf PORTB goto suiteTMR0 ; compteur1 = .4 ? compteur1_04 movlw 0x04 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_05 ; Z = 0 c'est-à-dire (compteur1) != 0x04 movlw B'10110001' movwf PORTB goto suiteTMR0 ; compteur1 = .5 ? compteur1_05 movlw 0x05 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_06 ; Z = 0 c'est-à-dire (compteur1) != 0x05 movlw B'10010001' movwf PORTB goto suiteTMR0 ; compteur1 = .6 ? compteur1_06 movlw 0x06 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_07 ; Z = 0 c'est-à-dire (compteur1) != 0x06 movlw B'10000001' movwf PORTB goto suiteTMR0 ; compteur1 = .7 ? compteur1_07 movlw 0x07 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_08 ; Z = 0 c'est-à-dire (compteur1) != 0x07 movlw B'00000001' movwf PORTB ; on allume toutes les LEDs goto suiteTMR0 ; compteur1 = .8 ? compteur1_08 movlw 0x08 subwf compteur1, W btfss STATUS, Z ; test du bit Z goto compteur1_09 ; Z = 0 c'est-à-dire (compteur1) != 0x08 movlw B'11111111' movwf PORTB ; on éteint toutes les LEDs goto suiteTMR0 ; compteur1 = .9 (logiquement) compteur1_09 movlw B'00000001' movwf PORTB ; on allume toutes les LEDs goto suiteTMR0 suiteTMR0 ; on incrémente (compteur1) incf compteur1 , f ; on teste si (compteur1) > 9 movf compteur1 , W ; W = (compteur1) sublw 0x09 ; W = 0x09 - (compteur1) btfsc STATUS, C ; test du bit C (Carry) goto suiteTMR0_1 ; C = 1 c'est-à-dire (compteur1) <= 0x09 clrf compteur1 ; (compteur1) = 0 ; on incrémente (compteur2) incf compteur2 , f suiteTMR0_1 bcf INTCON , T0IF ; on efface le drapeau goto restauration finTMR0 movlw B'11111111' movwf PORTB ; on éteint toutes les LEDs ; on active l'interruption RB0/INT bsf INTCON , INTE ; on désactive l'interruptin TMR0 bcf INTCON , T0IE bcf INTCON , INTF ; on efface le drapeau bcf INTCON , T0IF ; on efface le drapeau goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx testfinrotation btfsc finrotation , 0 goto finrotationoui bsf finrotation , 0 ; on met le drapeau à 1 goto finfinrotation finrotationoui ; on passe à l'étape "séquence sonore" clrf etat bsf etat , 2 ; on désactive l'interruption RB0/INT bcf INTCON , INTE bcf INTCON , INTF ; on efface le drapeau movlw .1 movwf compteursalve movwf cycle bsf PORTA , 1 ; Fréquence de l'interruption (prescaler 1:1) : ; 260 000 / (4*256*1) # 250 Hz bank1 bsf OPTION_REG , PSA bcf OPTION_REG , PS2 bcf OPTION_REG , PS1 bcf OPTION_REG , PS0 ; bit 3 (PSA) = 1 ; bit 2 (PS2) = 0 ; bit 1 (PS1) = 0 ; bit 0 (PS0) = 0 ; Prescaler du Timer0 = 1:1 bank0 goto finfinrotation finfinrotation bcf INTCON , T0IF ; on efface le drapeau goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx sequencesonore ; on teste si (compteursalve) > (valeurfaciale) movf compteursalve , W ; W = (compteursalve) subwf valeurfaciale, W ; W = (valeurfaciale) - (compteursalve) btfss STATUS, C ; test du bit C (Carry) goto finsequencesonore ; C = 0 c'est-à-dire (valeurfaciale) < (compteursalve) ; on teste si (cycle = 0) movf cycle , f ; (cycle) = (cycle) btfss STATUS , Z ; test du bit Z goto test32 ; Z = 0 c'est-à-dire (cycle) != 0x00 ; (cycle = 0): incf cycle , f ; (cycle = 1) ; Fréquence de l'interruption (prescaler 1:1) : ; 260 000 / (4*256*1) # 250 Hz clrf TMR0 bank1 bsf OPTION_REG , PSA bcf OPTION_REG , PS2 bcf OPTION_REG , PS1 bcf OPTION_REG , PS0 ; bit 3 (PSA) = 1 ; bit 2 (PS2) = 0 ; bit 1 (PS1) = 0 ; bit 0 (PS0) = 0 ; Prescaler du Timer0 = 1:1 bank0 goto finfinsequencesonore test32 ; on teste si (cycle) > 32 : movf cycle , W ; W = (cycle) sublw .32 ; W = .32 - (cycle) btfsc STATUS, C ; test du bit C (Carry) goto salveencours ; C = 1 c'est-à-dire (cycle) <= .32 ; (cycle) > 32 : ; (cycle) = 0 ; TMR0 # 1 Hz ; on incrémente (compteursalve) incf compteursalve , f clrf cycle clrf TMR0 ; Fréquence de l'interruption (prescaler 1:64) : ; 260 000 / (4*256*64) # 4 Hz bank1 bcf OPTION_REG , PSA bsf OPTION_REG , PS2 bcf OPTION_REG , PS1 bsf OPTION_REG , PS0 ; bit 3 (PSA) = 0 ; bit 2 (PS2) = 1 ; bit 1 (PS1) = 0 ; bit 0 (PS0) = 1 ; Prescaler du Timer0 = 1:64 bank0 goto finfinsequencesonore salveencours incf cycle , f goto finfinsequencesonore finsequencesonore ; on active l'interruption RB0/INT bsf INTCON , INTE bcf INTCON , INTF ; on efface le drapeau ; on désactive l'interruptin TMR0 bcf INTCON , T0IE bcf INTCON , T0IF ; on efface le drapeau goto restauration finfinsequencesonore ; on inverse le niveau de la sortie RA1 movlw B'00000010' ; W = B'00000010' (masque) xorwf PORTA , f ; fonction logique OU exclusif bcf INTCON , T0IF ; on efface le drapeau goto restauration ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Traitement de l'interruption RB0/INT ; (active sur front montant) interruption_RB0 btfss etat , 1 call debutrotation clrf TMR0 clrf finrotation ; on efface le drapeau ; on incrémente (valeurfaciale) incf valeurfaciale , f ; on teste si (valeurfaciale) > 6 movf valeurfaciale , W ; W = (valeurfaciale) sublw 0x06 ; W = 0x06 - (valeurfaciale) btfsc STATUS, C ; test du bit C (Carry) goto valeurfaciale_1 ; C = 1 c'est-à-dire (valeurfaciale) <= 0x06 movlw 0x01 movwf valeurfaciale ; (valeurfaciale) = 1 goto valeurfaciale_1 ; valeur faciale = 1 ? valeurfaciale_1 movlw 0x01 subwf valeurfaciale, W btfss STATUS, Z ; test du bit Z goto valeurfaciale_2 ; Z = 0 c'est-à-dire (valeurfaciale) != 0x01 movlw B'01111111' movwf PORTB ; on allume la LED7 goto suiteRB0 ; valeur faciale = 2 ? valeurfaciale_2 movlw 0x02 subwf valeurfaciale, W btfss STATUS, Z ; test du bit Z goto valeurfaciale_3 ; Z = 0 c'est-à-dire (valeurfaciale) != 0x02 movlw B'11100111' movwf PORTB goto suiteRB0 ; valeur faciale = 3 ? valeurfaciale_3 movlw 0x03 subwf valeurfaciale, W btfss STATUS, Z ; test du bit Z goto valeurfaciale_4 ; Z = 0 c'est-à-dire (valeurfaciale) != 0x03 movlw B'01100111' movwf PORTB goto suiteRB0 ; valeur faciale = 4 ? valeurfaciale_4 movlw 0x04 subwf valeurfaciale, W btfss STATUS, Z ; test du bit Z goto valeurfaciale_5 ; Z = 0 c'est-à-dire (valeurfaciale) != 0x04 movlw B'10100101' movwf PORTB goto suiteRB0 ; valeur faciale = 5 ? valeurfaciale_5 movlw 0x05 subwf valeurfaciale, W btfss STATUS, Z ; test du bit Z goto valeurfaciale_6 ; Z = 0 c'est-à-dire (valeurfaciale) != 0x05 movlw B'00100101' movwf PORTB goto suiteRB0 ; valeur faciale = 6 (logiquement) valeurfaciale_6 movlw B'10000001' movwf PORTB goto suiteRB0 suiteRB0 ; on inverse le niveau de la sortie RA1 movlw B'00000010' ; W = B'00000010' (masque) xorwf PORTA , f ; fonction logique OU exclusif bcf INTCON , INTF ; on efface le drapeau goto restauration debutrotation ; on arrive ici quand on passe de la phase initiale à la phase de rotation clrf etat bsf etat , 1 ; on active l'interruptin TMR0 bsf INTCON , T0IE ; Fréquence de l'interruption (prescaler 1:256) : ; 260 000 / (4*256*256) # 1 Hz clrf TMR0 bank1 bcf OPTION_REG , PSA bsf OPTION_REG , PS2 bsf OPTION_REG , PS1 bsf OPTION_REG , PS0 ; bit 3 (PSA) = 0 ; bit 2 (PS2) = 1 ; bit 1 (PS1) = 1 ; bit 0 (PS0) = 1 ; Prescaler du Timer0 = 1:256 bank0 bcf INTCON , T0IF ; on efface le drapeau clrf finrotation return ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx restauration swapf STATUS_TEMP,W ; restauration des registres STATUS et W movwf STATUS swapf W_TEMP,f swapf W_TEMP,W retfie ; retour d'interruption ;xxxxxxxxxxxxxxx ; Initialisation ;xxxxxxxxxxxxxxx initialisation bank0 clrf PORTA clrf PORTB bank1 movlw B'11010101' movwf OPTION_REG ; bit 7 (/RBPU) = 1 : désactivation des résistances de pull-up du port B ; bit 6 (INTEDG) = 1 : interruption RB0/INT sur front montant ; bit 5 (T0CS) = 0 : l'horloge interne est l'horloge du timer0 ; bit 4 (T0SE) = 1 : valeur par défaut (option non utilisée) ; bit 3 (PSA) = 0 ; bit 2 (PS2) = 1 ; bit 1 (PS1) = 0 ; bit 0 (PS0) = 1 ; Prescaler du Timer0 = 1:64 ; Watchdog sans prescaler (1:1) movlw B'00011101' movwf TRISA ; bit 7 du port A : non implémenté ; bit 6 du port A : non implémenté ; bit 5 du port A : non implémenté ; bit 4 du port A (RA4/T0CKI) = 1 : broche non connectée (par défaut, configuration en entrée) ; bit 3 du port A (RA3) = 1 : broche non connectée (par défaut, configuration en entrée) ; bit 2 du port A (RA2) = 1 : broche non connectée (par défaut, configuration en entrée) ; bit 1 du port A (RA1) = 0 : configuration en sortie ; bit 0 du port A (RA0) = 1 : broche non connectée (par défaut, configuration en entrée) movlw B'00000001' movwf TRISB ; bit 7 du port B (RB7) = 0 : configuration en sortie ; bit 6 du port B (RB6) = 0 : configuration en sortie ; bit 5 du port B (RB5) = 0 : configuration en sortie ; bit 4 du port B (RB4) = 0 : configuration en sortie ; bit 3 du port B (RB3) = 0 : configuration en sortie ; bit 2 du port B (RB2) = 0 : configuration en sortie ; bit 1 du port B (RB1) = 0 : configuration en sortie ; bit 0 du port B (RB0/INT) = 1 : configuration en entrée bank0 clrf PORTA ; sortie RA1 du port A au niveau 0 movlw B'11111110' movwf PORTB ; sortie RB7 du port B au niveau 1 ; sortie RB6 du port B au niveau 1 ; sortie RB5 du port B au niveau 1 ; sortie RB4 du port B au niveau 1 ; sortie RB3 du port B au niveau 1 ; sortie RB2 du port B au niveau 1 ; sortie RB1 du port B au niveau 1 clrf TMR0 movlw B'10100000' movwf INTCON ; bit 7 (GIE) = 1 : autorisation globale des interruptions ; bit 6 (EEIE) = 0 : interdiction de l'interruption de fin d'écriture de l'EEPROM ; bit 5 (T0IE) = 1 : autorisation de l'interruption de débordement de TMR0 ; bit 4 (INTE) = 0 : interdiction de l'interruption RB0/INT ; bit 3 (RBIE) = 0 : interdiction de l'interruption RB ; bit 2 (T0IF) = 0 : effacement du drapeau de l'interruption TMR0 ; bit 1 (INTF) = 0 : effacement du drapeau de l'interruption RB0/INT ; bit 0 (RBIF) = 0 : effacement du drapeau de l'interruption RB clrf compteur1 clrf compteur2 clrf valeurfaciale ; (valeurfaciale) = .0 clrf etat bsf etat , 0 clrf finrotation goto debut_programme ;xxxxxxxxxxxxxxxxxxxx ; Programme principal ;xxxxxxxxxxxxxxxxxxxx debut_programme ; On attend une interruption goto debut_programme END