;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Nom du projet : Métronome à son programmable ; Auteur : Fabrice Sincère ; Date : 22/06/2007 ; Microcontrôleur : Microchip PIC 16F628A ; Langage : Assembleur ; IDE : Microchip MPLAB ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Errorlevel-302 ; Supprime le message "Ensure that bank bits are correct" ;xxxxxxxxxxx ; Processeur ;xxxxxxxxxxx List p=16F628A #include ;xxxxxxxxxxxxxxxxxxxxxx ; Bits de configuration ;xxxxxxxxxxxxxxxxxxxxxx __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 20 MHz) ;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 RA2input macro ; configuration de la broche RA2 en entrée ; (lecture de la sortie DO de l'eeprom) bsf STATUS,RP0 ; passage en banque 1 bsf TRISA , 2 ; configuration de la broche RA2 en entrée bcf STATUS,RP0 ; passage en banque 0 endm RA2output macro ; configuration de la broche RA2 en sortie ; (écriture sur l'entrée DI de l'eeprom) bsf STATUS,RP0 ; passage en banque 1 bcf TRISA , 2 ; configuration de la broche RA2 en sortie bcf STATUS,RP0 ; passage en banque 0 endm ;xxxxxxxxxxxxxxxxxxxxxxxxxxx ; Déclaration des variables ;xxxxxxxxxxxxxxxxxxxxxxxxxxx CBLOCK 0x070 ; début de la zone des registres d'usage général du 16F628A ; (banque quelconque : 0,1,2 ou 3) ; 0x070 - 0x07F : 16 variables W_TEMP : 1 ; adresse 0x0C STATUS_TEMP : 1 ; adresse 0x0D RA4_bak : 1 ; niveau de la broche RA4 (lors de la précédente lecture) ; seul le bit 0 est utilisé (0000000x) instructionH :1 ; contient les 6 premiers bits de l'instruction READ ; à transmettre à l'EEPROM 9386 (broche DI) ; 00 1(start bit) 10 (opcode) A10 A9 A8 instructionL :1 ; contient les 8 derniers bits de l'instruction READ ; à transmettre à l'EEPROM 9386 (broche DI) ; A7 A6 A5 A4 A3 A2 A1 A0 (bits d'adresse) dataREAD : 1 ; 8 bits de données lus dans l'eeprom ; c'est aussi les 8 bits à transmettre au DAC08 ENDC ;xxxxxxxxxxxxxxxxxxxx ; Démarrage sur reset ;xxxxxxxxxxxxxxxxxxxx org 0x0000 goto initialisation ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine d'interruption ; 1 source d'interruption : TMR0 en mode timer ; Durée de la temporisation : ; 227*0,2 µs (quartz 20 MHz) * 2 (prescaler 1:2) ; = 90,8 µs ; = 11,013 kHz ; Ecart de 0,1 % avec 11,025 kHz (fréquence d'échantillonnage du son) ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx org 0x0004 ; vecteur d'interruption movwf W_TEMP ; sauvegarde des registres W et STATUS swapf STATUS,W movwf STATUS_TEMP movlw D'31' addwf TMR0 , f ; on incrémente le TMRO de 31 ; si qui permet d'avoir une interruption ; tous les 2*(256-31+2)=2*227 cycles au lieu de 2*256 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Communication avec l'EEPROM 9386 (2048 x 8 bits) ; Instruction READ ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx bsf PORTA, 0 ; CS = 1 ; bit 5 de (instructionH) bcf PORTA, 1 ; CLK = 0 btfsc instructionH , 5 bsf PORTA , 2 ; DI = 1 btfss instructionH , 5 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 4 de (instructionH) bcf PORTA, 1 ; CLK = 0 btfsc instructionH , 4 bsf PORTA , 2 ; DI = 1 btfss instructionH , 4 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 3 de (instructionH) bcf PORTA, 1 ; CLK = 0 btfsc instructionH , 3 bsf PORTA , 2 ; DI = 1 btfss instructionH , 3 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 2 de (instructionH) bcf PORTA, 1 ; CLK = 0 btfsc instructionH , 2 bsf PORTA , 2 ; DI = 1 btfss instructionH , 2 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 1 de (instructionH) bcf PORTA, 1 ; CLK = 0 btfsc instructionH , 1 bsf PORTA , 2 ; DI = 1 btfss instructionH , 1 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 0 de (instructionH) bcf PORTA, 1 ; CLK = 0 btfsc instructionH , 0 bsf PORTA , 2 ; DI = 1 btfss instructionH , 0 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 7 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 7 bsf PORTA , 2 ; DI = 1 btfss instructionL , 7 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 6 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 6 bsf PORTA , 2 ; DI = 1 btfss instructionL , 6 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 5 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 5 bsf PORTA , 2 ; DI = 1 btfss instructionL , 5 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 4 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 4 bsf PORTA , 2 ; DI = 1 btfss instructionL , 4 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 3 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 3 bsf PORTA , 2 ; DI = 1 btfss instructionL , 3 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 2 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 2 bsf PORTA , 2 ; DI = 1 btfss instructionL , 2 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 1 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 1 bsf PORTA , 2 ; DI = 1 btfss instructionL , 1 bcf PORTA , 2 ; DI = 0 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns ; bit 0 de (instructionL) bcf PORTA, 1 ; CLK = 0 btfsc instructionL , 0 bsf PORTA , 2 ; DI = 1 btfss instructionL , 0 bcf PORTA , 2 ; DI = 0 bsf PORTA , 1 ; CLK = 1 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; lecture des 8 bits de données clrf dataREAD bcf PORTA , 2 ; DI = 0 bcf PORTA , 1 ; CLK = 0 nop ; dummy bit bsf PORTA , 1 ; CLK = 1 RA2input ; configuration de RA2 en entrée bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 ; lecture DO bsf dataREAD , 7 ; D7 = 1 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 6 ; D6 = 1 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 5 ; D5 = 1 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 4 ; D4 = 1 bsf PORTA, 1 ; CLK = 1 nop ; une petite pause de 200 ns bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 3 ; D3 = 1 bsf PORTA, 1 ; CLK = 1 nop bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 2 ; D2 = 1 bsf PORTA, 1 ; CLK = 1 nop bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 1 ; D1 = 1 bsf PORTA, 1 ; CLK = 1 nop bcf PORTA, 1 ; CLK = 0 btfsc PORTA , 2 bsf dataREAD , 0 ; D0 = 1 bcf PORTA, 0 ; CS = 0 RA2output ; configuration de RA2 en sortie ; xxxxxxxxxxxxxxxxxxxx ; Ecriture dans le DAC ; xxxxxxxxxxxxxxxxxxxx movf dataREAD , W movwf PORTB ; xxxxxxxxxxxxxxxxxxxxxxx ; on incrémente l'adresse incf instructionL , f movf instructionL , f btfss STATUS , Z goto restauration ; (instructionL) différent de 0 ;(instructionL) = 0 incf instructionH , f movlw B'00111000' subwf instructionH , w btfss STATUS , Z goto restauration ; adresse différente de 2048 ; adresse = 2048 (fin de l'eeprom) ; interdiction de l'interruption TMR0 en mode timer bcf INTCON , T0IE movlw B'10000000' movwf PORTB ; sortie du DAC à 0 V restauration bcf INTCON , T0IF ; on efface le drapeau de l'interruption TMR0 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 movlw B'00000111' movwf CMCON ; inactivation des comparateurs analogiques bank1 movlw B'11010000' movwf OPTION_REG ; bit 7 (/RBPU) = 1 : valeur par défaut (option non utilisée) ; bit 6 (INTEDG) = 1 : valeur par défaut (option non utilisée) ; bit 5 (T0CS) = 0 : l'horloge de TMR0 est l'horloge interne ; bit 4 (T0SE) = 1 : valeur par défaut (option non utilisée) ; bit 3 (PSA) = 0 ; bit 2 (PS2) = 0 ; bit 1 (PS1) = 0 ; bit 0 (PS0) = 0 ; Prescaler du Timer0 = 1:2 ; Watchdog sans prescaler (1:1) movlw B'11111000' movwf TRISA ; bit 7 du port A : configuration en entrée (par exemple) ; bit 6 du port A : configuration en entrée (par exemple) ; bit 5 du port A : configuration en entrée (par exemple) ; bit 4 du port A (RA4/T0CKI) = 1 : 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) = 0 : configuration en sortie ; bit 1 du port A (RA1) = 0 : configuration en sortie ; bit 0 du port A (RA0) = 0 : configuration en sortie movlw B'00000000' 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) = 0 : configuration en sortie bank0 clrf PORTA ; sortie RA2 du port A au niveau 0 ; sortie RA1 du port A au niveau 0 ; sortie RA0 du port A au niveau 0 movlw B'10000000' movwf PORTB ; sortie RB7 du port B au niveau 1 ; sortie RB6 du port B au niveau 0 ; sortie RB5 du port B au niveau 0 ; sortie RB4 du port B au niveau 0 ; sortie RB3 du port B au niveau 0 ; sortie RB2 du port B au niveau 0 ; sortie RB1 du port B au niveau 0 ; sortie RB0/INT du port B au niveau 0 ; sortie du DAC à 0 volt clrf TMR0 clrf RA4_bak movlw B'10000000' movwf INTCON ; bit 7 (GIE) = 1 : autorisation globale des interruptions ; bit 6 (PEIE) = 0 : interdiction des interruptions périphériques ; bit 5 (T0IE) = 0 : interdiction 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 goto debut_programme ;xxxxxxxxxxxxxxxxxxxx ; Programme principal ;xxxxxxxxxxxxxxxxxxxx debut_programme ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; détection d'un front montant sur la broche RA4 btfss PORTA , 4 goto debut0 ; RA4 = 0 ; RA4 = 1 btfsc RA4_bak , 0 goto debut1 ; valeur précédente de RA4 = 1 ; on arrive ici si front montant (RA4 passe de 0 à 1) bsf RA4_bak , 0 ; sauvegarde du niveau de RA4 (1) ; première instruction 00110000 00000000 ; (lecture de l'adresse 0) clrf instructionL movlw B'00110000' movwf instructionH RA2output ; configuration de RA2 en sortie ; autorisation de l'interruption TMR0 en mode timer bsf INTCON , T0IE goto debut_programme debut0 bcf RA4_bak , 0 ; sauvegarde du niveau de RA4 (0) goto debut_programme debut1 bsf RA4_bak , 0 ; sauvegarde du niveau de RA4 (1) goto debut_programme END