;***************************************************************************** ; Ce fichier est la base de départ pour une programmation avec * ; le PIC 16F88. Il contient les informations de base pour * ; démarrer. * ; ecrit grace à Bigonoff par gilles.chevalerias@free.fr * ;***************************************************************************** ; * ; NOM: * ; Date: * ; Version: * ; Circuit: * ; Auteur: * ; * ;***************************************************************************** ; * ; Fichier requis: P16F88.inc * ; * ; * ; * ;***************************************************************************** ; * ; Notes: * ; * ; * ; * ; * ;***************************************************************************** ERRORLEVEL -302 ; suppression du message bank select LIST P=PIC16F88 ; Définition de processeur #include ; fichier include __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_OFF & _WDT_OFF & _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. ; Choisir une valeur par groupe. ; Voici les valeurs et leurs définitions : ; Protection du programme ; ----------------------- ;_CP_ALL protection totale ;_CP_OFF Pas de protection ;Selection de la pine pour CCP1 ; ----------------------------- ;_CCP1_RB0 CCP1 sur RB0 ;_CCP1_RB3 CCP1 sur RB3 ; Debuggage ; --------- ;_DEBUG_ON RB6 et RB7 utilisées pour debugger ;_DEBUG_OFF RB6 et RB7 en utilisation normale ; Accès à la flash programme ; -------------------------- ;_WRT_PROTECT_OFF Le programme peut écrire dans toute la flash ;_WRT_PROTECT_256 Le programme ne peut pas écrire dans la flash dans les 256 premier octets ;_WRT_PROTECT_2048 Le programme ne peut pas écrire dans la flash dans les 2048 premier octets ;_WRT_PROTECT_ALL Le programme ne peut pas écrire dans la flash ; Protection de l'EEprom ; ----------------------- ;_CPD_ON Mémoire EEprom protégée ;_CPD_OFF Mémoire EEprom déprotégée ; Programmation sur circuit ; ------------------------- ;_LVP_ON RB3 permet la programmation série de la PIC ;_LVP_OFF RB3 en utilisation normale ; Reset de la PIC si tension <4V ; ------------------------------ ; _BODEN_ON Reset tension en service ; Valide PWRTE_ON automatiquement ; _BODEN_OFF Reset tension hors service ;Utilisation de la pin MCLR ; ------------------------- ;_MCLR_ON RA5/MCLR est utilise pour le reset ;_MCLR_OFF RA5/MCLR est utilise comme une entree/sortie ; Retard à la mise sous tension ; ----------------------------- ;_PWRTE_OFF Démarrage rapide ;_PWRTE_ON Démarrage temporisé ; Watchdog ; -------- ;_WDT_ON Watchdog en service ;_WDT_OFF Watchdog hors service (on peut activer le watchdog dans le programme) ; Oscillateur ; ----------- ;_EXTRC_CLKOUT (RC) RC externe sur RA7 avec Fosc/4 sur RA6 ;_EXTRC_IO (RCIO) RC ecterne sur RA7 avec RA6 en I/O ;_INTRC_CLKOUT (INTIO1) oscillateur interne avec Fosc/4 sur RA6 et I/O sur RA7 ;_INTRC_IO (INTIO2) oscillateur interne avec RA6 et RA7 en I/O ;_EXTCLK (ECIO) oscillateur externe sue RA7 avec RA6 en I/O ;_LP_OSC Oscillateur basse vitesse (? b6-4 : selection de la vitesse oscillateur inerne ; 000 = 31.25 kHz ; 001 = 125 kHz ; 010 = 250 kHz ; 011 = 500 kHz ; 100 = 1 MHz ; 101 = 2 MHz ; 110 = 4 MHz ; 111 = 8 MHz ; OSTS b3 : status de l'oscillateur en cours ; IOFS b2 : flag de stabilisation de l'oscillateur pour un changement ;de frequence en cours de programme à partir de 31.25KHz ; SCS<1:0> b1-0 : selection du mode de l'oscillateur ; 00 = le mode d'oscillateur est defini par FOSC<2:0> (LP, XT, HS, RC, EC) ; 01 = oscillateur secondaire sur RB6, RB7 ; 10 = l'oscillateur interne est utilisé pour l'horloge (2 modes INTRC) ; 11 = Reserved ; Pour utiliser l'oscillateur interne, on selectionne un des modes INTRC dans CONFIG1 ; on selectionne 10 pour les bits SCS<1:0> de OSCCON et la vitesse desiré par les bits IRCF<2:0> de OSCCON ; REGISTRE ANSEL (contrôle du convertisseur A/D) ; ---------------------------------------------- ANSELVAL EQU B'00000000' ; RESERVED b7 : réservé, laisser à 0 ; ANS6 b6 : 1=AN6/RB7 analogique, 0=AN6/RB7 digital ; ANS5 b5 : 1=AN5/RB6 analogique, 0=AN5/RB6 digital ; ANS4 b4 : 1=AN4/RA4 analogique, 0=AN4/RA4 digital ; ANS3 b3 : 1=AN3/RA3 analogique, 0=AN3/RA3 digital ; ANS2 b2 : 1=AN2/RA2 analogique, 0=AN2/RA2 digital ; ANS1 b1 : 1=AN1/RA1 analogique, 0=AN1/RA1 digital ; ANS0 b0 : 1=AN0/RA0 analogique, 0=AN0/RA0 digital ; REGISTRE CMCON (COMPARATEURS) ; ----------------------------- CMCONVAL EQU B'00000111' ; C2OUT b7 :sortie comparateur2 ; C1OUT b6 :sortie comparateur1 ; C2INV b5 :inverseur comparateur2 ; C1INV b4 :inverseur comparateur1 ; CIS b3 :selection entree des comparateurs ; CM2-CM0 b2-0 :mode des comparateurs ;configurer le mode 111 pour utiliser RA0 RA1 RA2 RA3 en I/O ; REGISTRE CVRCON (voltage reference module) ; ------------------------------------ CVRCONVAL EQU B'00000000' ; CVREN b7 :Validation du module ; CVROE b6 :Sortie sur RA2 ; CVRR b5 :Choix de la plage ; RESERVED b4 : réservé, laisser à 0 ; CVR3-CVR0 b3-0 :Choix de la valeur dans la plage ; si CVRR=1 Vref=(CVR[3:0]/24)*Vdd ; si CVRR=0 Vref=Vdd/4+(CVR[3:0]/32)*Vdd ; REGISTRE WDTCON (prediviseur et activation du watchdog) ; ------------------------------------------------------- ; la valeur proposée n'est pas chargée pendant l'init, à vous de le faire si vous en avez besoin ;WDTCONVAL EQU B'00010110' ; par exemple debordement tout les (2,07 secondes*postdiviseur), on peut aller jusqu'à 268 secondes ; RESERVED b7-5 : réservé, laisser à 0 ; WDTPS<3-0> b4-1 : prediviseur du watchdog qui oscille à 31.25 kHz (32µS) ; 0000 = 1:32 ; 0001 = 1:64 ; 0010 = 1:128 ; 0011 = 1:256 ; 0100 = 1:512 ; 0101 = 1:1024 ; 0110 = 1:2048 ; 0111 = 1:4096 ; 1000 = 1:8192 ; 1001 = 1:16394 ; 1010 = 1:32768 ; 1011 = 1:65536 ; SWDTEN b0 : à 1 ce bit met en route le watchdog ; si ce n'est déja fait dans le CONFIG1 ; DIRECTION DES PORTS I/O ; ----------------------- DIRPORTA EQU B'11111111' ; Direction PORTA (1=entrée) DIRPORTB EQU B'11111111' ; Direction PORTB ;***************************************************************************** ; ASSIGNATIONS PROGRAMME * ;***************************************************************************** ; exemple ; ------- ;MASQUE EQU H'00FF' ;***************************************************************************** ; DEFINE * ;***************************************************************************** ; exemple ; ------- ;#DEFINE LED1 PORTB,1 ; LED de sortie 1 ;***************************************************************************** ; MACRO * ;***************************************************************************** ; Changement de banques ; ---------------------- BANK0 macro ; passer en banque0 bcf STATUS,RP0 bcf STATUS,RP1 endm BANK1 macro ; passer en banque1 bsf STATUS,RP0 bcf STATUS,RP1 endm BANK2 macro ; passer en banque2 bcf STATUS,RP0 bsf STATUS,RP1 endm BANK3 macro ; passer en banque3 bsf STATUS,RP0 bsf STATUS,RP1 endm ; opérations en mémoire eeprom ; ----------------------------- REEPROM macro adeeprom ; lire eeprom (adresse dans adeeprom & résultat en w) clrwdt ; reset watchdog bcf STATUS,RP0 ; passer en banque2 bsf STATUS,RP1 movlw adeeprom ; charger adresse eeprom (passage de la valeur en litteral) ;movf adeeprom,w ; charger adresse eeprom (passage de la valeur par une variable) movwf EEADR ; pointer sur adresse eeprom bsf STATUS,RP0 ; passer en banque3 bcf EECON1,EEPGD ; pointer sur eeprom bsf EECON1,RD ; ordre de lecture bcf STATUS,RP0 ; passer en banque2 movf EEDATA,w ; charger valeur lue bcf STATUS,RP1 ; passer en banque0 endm WEEPROM macro addwrite ; la donnée se trouve dans W LOCAL loop BANK2 ; passer en banque2 movwf EEDATA ; placer data dans registre movlw addwrite ; charger adresse d'écriture (passage de la valeur en litteral) ;movf addwrite,w ; charger adresse d'écriture (passage de la valeur par une variable) movwf EEADR ; placer dans registre bsf STATUS , RP0 ; passer en banque3 bcf EECON1 , EEPGD ; pointer sur mémoire data bsf EECON1 , WREN ; autoriser accès écriture bcf INTCON , GIE ; interdire interruptions movlw 0x55 ; charger 0x55 movwf EECON2 ; envoyer commande movlw 0xAA ; charger 0xAA movwf EECON2 ; envoyer commande bsf EECON1 , WR ; lancer cycle d'écriture bsf INTCON , GIE ; réautoriser interruptions loop btfsc EECON1 , WR ; tester si écriture terminée goto loop ; non, attendre bcf EECON1 , WREN ; verrouiller prochaine écriture bcf STATUS , RP0 ; passer en banque0 bcf STATUS , RP1 endm ;***************************************************************************** ; VARIABLES ZONE COMMUNE * ;***************************************************************************** ; Zone de 16 bytes ; ---------------- CBLOCK 0x70 ; Début de la zone (0x70 à 0x7F) w_temp : 1 ; Sauvegarde registre W status_temp : 1 ; sauvegarde registre STATUS FSR_temp : 1 ; sauvegarde FSR (si indirect en interrupt) PCLATH_temp : 1 ; sauvegarde PCLATH (si prog>2K) ENDC ;***************************************************************************** ; VARIABLES BANQUE 0 * ;***************************************************************************** ; Zone de 80 bytes ; ---------------- CBLOCK 0x20 ; Début de la zone (0x20 à 0x6F) ENDC ; Fin de la zone ;Exemples ;-------- ;test :1 ; Zone de 1 byte ;table : 10 ; zone de 10 bytes ;var1 EQU H'006E' ; adresse imposée ;***************************************************************************** ; VARIABLES BANQUE 1 * ;***************************************************************************** ; Zone de 80 bytes ; ---------------- CBLOCK 0xA0 ; Début de la zone (0xA0 à 0xEF) ENDC ; Fin de la zone ;***************************************************************************** ; VARIABLES BANQUE 2 * ;***************************************************************************** ; Zone de 96 bytes ; ---------------- CBLOCK 0x110 ; Début de la zone (0x110 à 0x16F) ENDC ; Fin de la zone ;***************************************************************************** ; VARIABLES BANQUE 3 * ;***************************************************************************** ; Zone de 96 bytes ; ---------------- CBLOCK 0x190 ; Début de la zone (0x190 à 0x1EF) ENDC ; Fin de la zone ;***************************************************************************** ; DEMARRAGE SUR RESET * ;***************************************************************************** org 0x000 ; Adresse de départ après reset goto init ; Initialiser ; //////////////////////////////////////////////////////////////////////////// ; I N T E R R U P T I O N S ; //////////////////////////////////////////////////////////////////////////// ;***************************************************************************** ; ROUTINE INTERRUPTION * ;***************************************************************************** ;----------------------------------------------------------------------------- ; Si on n'utilise pas l'adressage indirect dans les interrupts, on se passera ; de sauvegarder FSR ainsi que la restauration dans restorereg ; Si le programme ne fait pas plus de 2K, on se passera de la gestion de ; PCLATH ainsi que la restauration dans restorereg ;----------------------------------------------------------------------------- ;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é movf FSR , w ; charger FSR movwf FSR_temp ; sauvegarder FSR movf PCLATH , w ; charger PCLATH movwf PCLATH_temp ; le sauver BANK0 ; passer en banque0 ; switch vers différentes interrupts ; inverser ordre pour modifier priorités ; mais attention alors au test PEIE ; effacer les inutiles ;---------------------------------------- ; Interruption TMR0 ; ----------------- btfsc INTCON,TMR0IE ; tester si interrupt timer autorisée btfss INTCON,TMR0IF ; oui, tester si interrupt timer en cours goto intsw1 ; non test suivant call inttmr0 ; oui, traiter interrupt tmr0 bcf INTCON,TMR0IF ; effacer flag interrupt tmr0 goto restorereg ; et fin d'interruption ; SUPPRIMER CETTE LIGNE POUR ; TRAITER PLUSIEURS INTERRUPT ; EN 1 SEULE FOIS ; Interruption RB0/INT ; -------------------- intsw1 btfsc INTCON,INTE ; tester si interrupt RB0 autorisée btfss INTCON,INTF ; oui, tester si interrupt RB0 en cours goto intsw2 ; non sauter au test suivant call intrb0 ; oui, traiter interrupt RB0 bcf INTCON,INTF ; effacer flag interupt RB0 goto restorereg ; et fin d'interruption ; SUPPRIMER CETTE LIGNE POUR ; TRAITER PLUSIEURS INTERRUPT ; EN 1 SEULE FOIS ; interruption RB4/RB7 ; -------------------- intsw2 btfsc INTCON,RBIE ; tester si interrupt RB4/7 autorisée btfss INTCON,RBIF ; oui, tester si interrupt RB4/7 en cours goto intsw3 ; non sauter call intrb4 ; oui, traiter interrupt RB4/7 bcf INTCON,RBIF ; effacer flag interupt RB4/7 goto restorereg ; et fin d'interrupt ; détection interruptions périphériques ; le test peut être supprimé si une seule ; interrupt est traitée à la fois ; -------------------------------------- intsw3 btfss INTCON,PEIE ; tester interruption périphérique autorisée goto restorereg ; non, fin d'interruption ; Interruption réception USART ; ---------------------------- intsw4 BANK1 ; sélectionner banque1 btfss PIE1,RCIE ; tester si interrupt autorisée goto intsw5 ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR1,RCIF ; oui, tester si interrupt en cours goto intsw5 ; non sauter call intrc ; oui, traiter interrupt ; LE FLAG NE DOIT PAS ETRE REMIS A 0 ; C'EST LA LECTURE DE RCREG QUI LE PROVOQUE goto restorereg ; et fin d'interrupt ; Interruption transmission USART ; ------------------------------- intsw5 BANK1 ; sélectionner banque1 btfss PIE1,TXIE ; tester si interrupt autorisée goto intsw6 ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR1,TXIF ; oui, tester si interrupt en cours goto intsw6 ; non sauter call inttx ; oui, traiter interrupt ; LE FLAG NE DOIT PAS ETRE REMIS A 0 ; C'EST L'ECRITURE DE TXREG QUI LE PROVOQUE goto restorereg ; et fin d'interrupt ; Interruption comparateurs ; ------------------------- intsw6 BANK1 ; sélectionner banque1 btfss PIE2,CMIE ; tester si interrupt autorisée goto intsw7 ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR1,CMIF ; oui, tester si interrupt en cours goto intsw7 ; non sauter call intcmp ; oui, traiter interrupt bcf PIR1,CMIF ; effacer flag interupt comparateur goto restorereg ; et fin d'interrupt ; Interruption CCP1 ; ----------------- intsw7 BANK1 ; sélectionner banque1 btfss PIE1,CCP1IE ; tester si interrupt autorisée goto intsw8 ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR1,CCP1IF ; oui, tester si interrupt en cours goto intsw8 ; non sauter call intccp1 ; oui, traiter interrupt bcf PIR1,CCP1IF ; effacer flag interupt goto restorereg ; et fin d'interrupt ; Interruption TMR2 ; ----------------- intsw8 BANK1 ; sélectionner banque1 btfss PIE1,TMR2IE ; tester si interrupt autorisée goto intsw9 ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR1,TMR2IF ; oui, tester si interrupt en cours goto intsw9 ; non sauter call inttmr2 ; oui, traiter interrupt bcf PIR1,TMR2IF ; effacer flag interupt goto restorereg ; et fin d'interrupt ; Interruption TMR1 ; ----------------- intsw9 BANK1 ; sélectionner banque1 btfss PIE1,TMR1IE ; tester si interrupt autorisée goto intswA ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR1,TMR1IF ; oui, tester si interrupt en cours goto intswA ; non sauter call inttmr1 ; oui, traiter interrupt bcf PIR1,TMR1IF ; effacer flag interupt goto restorereg ; et fin d'interrupt ; Interruption EEPROM ; ------------------- intswA BANK1 ; sélectionner banque1 btfss PIE2,EEIE ; tester si interrupt autorisée goto intswB ; non sauter BANK0 ; oui, sélectionner banque0 btfss PIR2,EEIF ; oui, tester si interrupt en cours goto intswB ; non sauter call inteprom ; oui, traiter interrupt bcf PIR2,EEIF ; effacer flag interupt goto restorereg ; et fin d'interrupt ; Interruption convertisseur A/D ; ------------------------------ intswB BANK1 ; sélectionner banque1 btfss PIE1,ADIE ; tester si interrupt autorisée goto restorereg ; non sauter bcf STATUS,RP0 ; oui, sélectionner banque0 btfss PIR1,ADIF ; tester si interrupt en cours goto restorereg ; non sauter call intad ; oui, traiter interrupt bcf PIR1,ADIF ; effacer flag interupt goto restorereg ; et fin d'interrupt ; Manque les interruptions d'oscillateur et SSPIF de port serie synchrone ;restaurer registres ;------------------- restorereg movf PCLATH_temp , w ; recharger ancien PCLATH movwf PCLATH ; le restaurer movf FSR_temp , w ; charger FSR sauvé movwf FSR ; restaurer FSR 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 TIMER 0 * ;***************************************************************************** inttmr0 return ; fin d'interruption timer ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION RB0/INT * ;***************************************************************************** intrb0 return ; fin d'interruption RB0/INT ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION RB4/RB7 * ;***************************************************************************** intrb4 return ; fin d'interruption RB4/RB7 ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION RECEPTION USART * ;***************************************************************************** intrc return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION TRANSMISSION USART * ;***************************************************************************** inttx return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION CCP1 * ;***************************************************************************** intccp1 return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;**************************************************************************** ; INTERUPTION COMPARATEUR * ;**************************************************************************** intcmp return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION TIMER 2 * ;***************************************************************************** inttmr2 return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION TIMER 1 * ;***************************************************************************** inttmr1 return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION EEPROM * ;***************************************************************************** inteprom return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ;***************************************************************************** ; INTERRUPTION CONVERTISSEUR A/D * ;***************************************************************************** intad return ; fin d'interruption ; peut être remplacé par ; retlw pour retour code d'erreur ; //////////////////////////////////////////////////////////////////////////// ; P R O G R A M M E ; //////////////////////////////////////////////////////////////////////////// ;***************************************************************************** ; INITIALISATIONS * ;***************************************************************************** init ; initialisation PORTS (banque 0 et 1) ; ------------------------------------ BANK0 ; sélectionner banque0 clrf PORTA ; Sorties PORTA à 0 clrf PORTB ; sorties PORTB à 0 BANK1 ; passer en banque1 movlw DIRPORTA ; Direction PORTA movwf TRISA ; écriture dans registre direction movlw DIRPORTB ; Direction PORTB movwf TRISB ; écriture dans registre direction ; Registre de l'oscillateur ; ------------------------- movlw OSCCONVAL ; charger le masque movwf OSCCON ; initialiser registre ; Registre d'options (banque 1) ; ----------------------------- movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option ; registres interruptions (banque 1) ; ---------------------------------- movlw INTCONVAL ; charger valeur registre interruption movwf INTCON ; initialiser interruptions movlw PIE1VAL ; Initialiser registre movwf PIE1 ; interruptions périphériques 1 movlw PIE2VAL ; Initialiser registre movwf PIE2 ; interruptions périphériques 2 movlw CVRCONVAL ; charger masque movwf CVRCON ; initialiser le registre tension de reference movlw CMCONVAL ; charger masque movwf CMCON ; initialiser le registre du comparateur movlw ANSELVAL ; charger masque movwf ANSEL ; initialiser le registre du convertisseur ; Effacer RAM banque 0 ; --------------------- BANK0 ; sélectionner banque 0 movlw 0x20 ; initialisation pointeur movwf FSR ; d'adressage indirect init1 clrf INDF ; effacer ram incf FSR,f ; pointer sur suivant btfss FSR,7 ; tester si fin zone atteinte (>7F) goto init1 ; non, boucler ; autoriser interruptions (banque 0) ; ---------------------------------- clrf PIR1 ; effacer flags 1 clrf PIR2 ; effacer flags 2 bsf INTCON,GIE ; valider interruptions goto start ; programme principal ;***************************************************************************** ; PROGRAMME PRINCIPAL * ;***************************************************************************** start clrwdt ; effacer watch dog goto start ; boucler END ; directive fin de programme