;******************************************************************* ; NOM : epatan01.asm ; eclairage OCEM Voiture voyageurs ; Date: 17/10/2007 ; Circuit: plaquette Véroboard ; Auteur: Pat'Ruff' ; Ce programme change l'état d'une sortie parmi 5 (l'éclairage d'un ; compartiment) et attend un délai pseudo aléatoire (1 à 255 s) et ; recommence. Le point de départ est mémorisé avant la coupure ; précédente. ; ATTENTION : version pour 12F629 (pour le 675 modidifiez les lignes ; 14, 15, 31 ! LIST p=PIC12F629 ; Définition de processeur #include ; Définitions des constantes errorlevel -302 __CONFIG _CPD_OFF & _BODEN_OFF & _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT ;********************************************************************* ; DECLARATIONS DE VARIABLES SPECIFIQUES * ;********************************************************************* CBLOCK 0x020 ; début de la zone des variables CPT_SEC : 1 ; compteur en secondes (en gros) DELAI : 1 ; délai en seconde avant prochaine action BUFF_TMP : 1 ; buffer temporaire de calcul POSTDIVTMR0 : 1 ; Post diviseur logiciel timer 0 ADR_EEPROM : 1 ; Adresse d'écriture ou lecture EEPROM DATA_EEPROM : 1 ; Data d'écriture ou lecture EEPROM N_PSEUDOALEA : 1 ; nombre pseudo aléatoire ENDC ; Fin de la zone des variables ; #include ; paramétrage standard ; ensemble des paramètres (registres) ; pour une utilisation standard du PIC ; (pas de convertisseur, ni comparateur...) ; contient également des morceaux de ; programme standard ;********************************************************************* ; PARAMETRES SPECIFIQUES * ;********************************************************************* BANK1 clrf TRISIO ; port en sortie ; clrf WPU ; pas de résistances de rappel ; ; registre controle interruptions INTCON BANK0 et 1 clrf INTCON bsf INTCON,GIE ; interruptions activées en permanence bsf INTCON,PEIE ; autorise interruption périphériques (notamment timer) ; registre interruptions périphériques clrf PIE1 ; bsf PIE1,TMR1IE ; autorise les interruptions Timer1 ; Configuration du Timer 0 (prédiviseurs pour avoir une IT par seconde, ...) ; registre OPTION_REG qui gère le Timer0 clrf OPTION_REG bsf OPTION_REG, PS0 ; PS0 à PS2: prédiviseur Timer0 bsf OPTION_REG, PS1 bsf OPTION_REG, PS2 BANK0 ; Les sorties 0, 1, 2, 4 & 5 sont utilisées (soit toutes !) ; On les initialise les leds des compartiments à actives ; et celles des toilettes à inactives (la 5 inversée sur le schéma): movlw b'00010100' ; bits 0&1 à 0, 2&4 à 1, 5 à 0, le reste N.U. movwf GPIO ; ; Initialisation du nombre pseudo-aléatoire avec la valeur stockée en EEProm movlw 0x00 movwf ADR_EEPROM call LectureEEPROM movwf N_PSEUDOALEA ; ; ; Initialisation du prochain delai, et du Post diviseur Timer 0 movwf DELAI movlw 0x0E movwf POSTDIVTMR0 ; Autorisation des interruptions du Timer 0 bsf INTCON,T0IE ; autorise les interruptions Timer0 ; ;********************************************************************* ; Boucle principale * ;********************************************************************* ; ; ; On attend que le compteur des secondes passe ; de 255 à 0 pour enregistrer en EEPROM ; BouclePrincipale ; Si Compteur IT <> 0 movf CPT_SEC, w btfsc STATUS, Z goto BouclePrincipale ; Si compteur IT = 0 AttenteCptSec movf CPT_SEC, w btfss STATUS, Z goto AttenteCptSec ; Archiver le nombre pseudo-aléatoire movlw 0x00 movwf ADR_EEPROM movf N_PSEUDOALEA, w movwf DATA_EEPROM call EcritureEEPROM ; Aller à la boucle principale goto BouclePrincipale ;********************************************************************* ; Sous programmes ;********************************************************************* ; ;********************************************************************* ; Ecriture en EEPROM ;********************************************************************* ; Entrée: ; L'adresse doit être en ADR_EEPROM ; La data doit être en DATA_EEPROM ; On doit être sur BANK 0 par défaut ; ; Sortie: Rien ; On est sur BANK 0 EcritureEEPROM BANK1 movf ADR_EEPROM, w movwf EEADR ; Init adresse movf DATA_EEPROM, w movwf EEDATA ; Init data bsf EECON1, WREN ; Write enable bcf INTCON, GIE ; Bloque les interruptions movlw 0x55 ; Début séquence ouverture verrou écriture EEPROM movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1, WR ; Ecriture bsf INTCON, GIE ; Ré-autorise les interruptions BANK0 return ; ;********************************************************************* ; Lecture en EEPROM ;********************************************************************* ; Entrée: ; L'adresse doit être en ADR_EEPROM ; On doit être sur BANK 0 par défaut ; ; Sortie: Donnée dans W ; On est sur BANK 0 LectureEEPROM BANK1 movf ADR_EEPROM, w movwf EEADR ; Init adresse bsf EECON1, RD ; Lecture movf EEDATA, w ; mise dans W BANK0 return ;********************************************************************* ; interruption TMR1 ; appelée à chaque interruption TMR1 ;********************************************************************* inttimer1 ; Timer 1 non utilisé dans ce programme return ; ;********************************************************************* ; interruption TMR0 ; appelée à chaque interruption TMR0 ;********************************************************************* inttimer0 ; Décrément du postdiviseur soft du Timer 0 ; Les interruptions timer 0 sont à 1µs * 256 (prédiviseur) * 256 (compteur 8b) ; soit 65 ms. Pour tomber à 1s, il faut encore diviser par 15 decfsz POSTDIVTMR0,f ; si <> 0, rien à faire goto FinITtmr0 movlw d'07' ; Diminuer cette valeur pour accélérer la cadence ; d'15' était la valeur initiale (activité à la seconde) movwf POSTDIVTMR0 ; Incrément du compteur macro des secondes incf CPT_SEC,f ; Décrément et test à 0 du délai decfsz DELAI,f ; si <> 0, rien à faire goto FinITtmr0 ; sinon: ; Mise à jour du nombre pseudo aléatoire: ; X(n+1) = Xn² + Xn + 1, le tout modulo 256 (donc on reste sur 8 bits) movf N_PSEUDOALEA, w movwf BUFF_TMP clrw Calcul_Xn2 addwf N_PSEUDOALEA, w ; Xn² = Xn + Xn + ... + Xn (Xn fois) decfsz BUFF_TMP, f goto Calcul_Xn2 ; ; Xn² est dans W addwf N_PSEUDOALEA, f ; Xn² + Xn est dans N_PSEUDOALEA incf N_PSEUDOALEA, f ; Xn² + Xn +1 est dans N_PSEUDOALEA ; Nouvelle sortie: On prend le nombre pseudo-aléatoire pour le choix rrf N_PSEUDOALEA, w ; on jette le bit pf (tjrs impair) ; on masque à 31=0x1F (donc de 0 à 31) andlw 0x1F ; On multiplie par 5 (donc de 0 à 155) movwf BUFF_TMP addwf BUFF_TMP,f addwf BUFF_TMP,f addwf BUFF_TMP,f addwf BUFF_TMP,f ; On divise par 32 avec 5 décalages (donc de 0 à 4) rrf BUFF_TMP,f rrf BUFF_TMP,f rrf BUFF_TMP,f rrf BUFF_TMP,f rrf BUFF_TMP,f movlw b'00000111' ; on masque les bits inutiles andwf BUFF_TMP,f ; Si = 0 (<=> si Z=1), on inverse la sortie 0 btfss STATUS,Z goto Sortie1 movlw b'00000001' ; inversion sortie 0 xorwf GPIO,f goto CalculDelai ; Décrément, si 0 (donc 1 au départ), on inverse la sortie 1 Sortie1 decfsz BUFF_TMP,f goto Sortie2 movlw b'00000010' ; inversion sortie 1 xorwf GPIO,f goto CalculDelai ; Décrément, si 0 (donc 2 au départ), on inverse la sortie 2 Sortie2 decfsz BUFF_TMP,f goto Sortie4 movlw b'00000100' ; inversion sortie 2 xorwf GPIO,f goto CalculDelai ; Décrément, si 0 (donc 3 au départ), on inverse la sortie 4 Sortie4 decfsz BUFF_TMP,f goto Sortie5 movlw b'00010000' ; inversion sortie 4 xorwf GPIO,f goto CalculDelai ; Dernier cas: On inverse la sortie 5 Sortie5 movlw b'00100000' ; inversion sortie 5 xorwf GPIO,f ; Nouveau délai: on prend Timer 1 poids faible pour l'initialiser CalculDelai movf N_PSEUDOALEA, w movwf DELAI nop FinITtmr0 return END