; Lecteur DALLAS avec liaison RS232 9600 bauds ; 14 janvier 2001 list P=16F876 include ; configuration du processeur __CONFIG _CP_OFF&_DEBUG_OFF&_WRT_ENABLE_ON&_CPD_OFF&_LVP_OFF&_BODEN_ON&_PWRTE_ON&_WDT_ON&_HS_OSC ;____________________________________________________________________________________________________________________ ; variables ;____________________________________________________________________________________________________________________ serie equ 20 part1 equ 21 part2 equ 22 part3 equ 23 part4 equ 24 part5 equ 25 part6 equ 26 dallasCRC equ 27 tmp equ 28 compteur equ 29 valeur equ 2A temp equ 2B rotation equ 2C nboctet equ 2D crc equ 2F adresse equ 30 dataee equ 31 saveW equ 32 savesta equ 33 saveFSR equ 34 flag equ 35 caractere equ 36 adresseH equ 37 adresseL equ 38 dataF equ 39 nbkey equ 3A temp1 equ 3B temp2 equ 3C timer equ 3D ; timer pour tempo 1 seconde seconde equ 3E ; compteur de secondes key equ 3F ; indice de la clef trouvée decompte equ 40 ; decompte pour tempo relais adlow equ 41 ; poids faible adresse R/W pour protocole adhigh equ 42 ; poids fort adresse R/W pour protocole ;____________________________________________________________________________________________________________________ ; constantes ;____________________________________________________________________________________________________________________ skiprom equ 0CC ; commande DALLAS readscratch equ 0BE ; " " convert equ 44 ; " " readrom equ 33 ; " " readram equ 0F0 ; " " Ladress equ 0 Hadress equ 0 ahigh equ 08 alow equ 00 nbclef equ 05 ; nb maximum de clef ACK equ 06 ; acknowledge liaison serie ;____________________________________________________________________________________________________________________ ; etiquettes bits ;____________________________________________________________________________________________________________________ #define _data PORTA,0 #define _rouge PORTB,7 #define _verte PORTB,6 #define _relais PORTB,5 masque equ b'10000000' ; masque de la led qui clignote ; la led qui clignote doit être sur le PORTB #define zero STATUS,Z #define _receivedcar flag,0 #define idem flag,1 #define _clignote flag,2 ;____________________________________________________________________________________________________________________ ; macro commandes ;____________________________________________________________________________________________________________________ bank0 macro bcf STATUS,RP0 bcf STATUS,RP1 endm bank1 macro bsf STATUS,RP0 endm bank2 macro bcf STATUS,RP0 bsf STATUS,RP1 endm bank3 macro bsf STATUS,RP0 bsf STATUS,RP1 endm ;____________________________________________________________________________________________________________________ ; entête programme ;____________________________________________________________________________________________________________________ org 2100 ; initialisation de l'EEPROM de 00,05 org 0 goto debut org 4 goto interrupt ;____________________________________________________________________________________________________________________ ; programme ;____________________________________________________________________________________________________________________ debut: clrwdt clrf flag movlw 5 movwf timer call initwdt ; initialisation du watchdog call initportA ; initialisation PORT A call initportB call initportC ; initialisation PORT C call initV24 ; initialisation RS232 call inittmr1 ; initialisation timer 1 call initint ; initialisation des interruptions movlw 0 movwf adresse clrwdt call readEE ; va lire l'adresse 0 de l'EEPROM xorlw 0 btfsc zero goto firstaccess bsf _rouge main: clrwdt call litcode btfsc STATUS,C goto access btfss _receivedcar goto main bcf _receivedcar movf caractere,w xorlw 'M' ; set mem ? btfsc zero goto setmem xorlw 'M' xorlw 'R' ; read mem ? btfsc zero goto readmem xorlw 'R' xorlw 'W' ; write mem btfsc zero goto writemem goto main setmem: movlw d'255' movwf seconde sm1: clrwdt movf seconde,w ; time out liaison serie une seconde btfsc zero goto main btfss _receivedcar ; attent adresse basse goto sm1 bcf _receivedcar movf caractere,w movwf adlow ; dans le registre movlw d'255' movwf seconde sm2: clrwdt movf seconde,w ; time out liaison serie btfsc zero goto main btfss _receivedcar ; attend adresse haute goto sm2 bcf _receivedcar movf caractere,w movwf adhigh ; dans le registre movlw ACK call transmit ; puis transmettre un ACK goto main readmem: movlw d'255' movwf seconde rm1: clrwdt movf seconde,w btfsc zero goto main btfss _receivedcar goto rm1 bcf _receivedcar movf caractere,w xorlw 'E' btfsc zero goto rEEPROM xorlw 'E' xorlw 'F' btfsc zero goto rflash xorlw'F' xorlw 'R' btfss zero goto main rram: ; lecture dans la ram movlw 8 movwf compteur movlw serie movwf FSR rr1: movf INDF,w call transmit incf FSR,f decfsz compteur,f goto rr1 movlw ACK call transmit goto main rflash: ; lecture dans la flash clrwdt movf adlow,w movwf adresseL movf adhigh,w movwf adresseH call readF call transmit ; envoi de l'octet movlw ACK call transmit movf adlow,w addlw 1 btfsc zero incf adhigh,f movf adlow,w goto main rEEPROM: clrwdt movf adlow,w movwf adresse call readEE ; va lire l'EEPROM call transmit movlw ACK call transmit incf adlow,f goto main writemem: movlw d'255' movwf seconde wm1: clrwdt movf seconde,w btfsc zero goto main btfss _receivedcar goto wm1 bcf _receivedcar movf caractere,w xorlw 'E' btfsc zero goto wEEPROM xorlw 'E' xorlw 'F' btfsc zero goto wFLASH xorlw 'F' xorlw 'R' btfss zero goto main wRAM: ; RAZ des 8 octets du code DALLAS en RAM clrwdt movlw 8 movwf compteur movlw serie movwf FSR wr1: movlw 0 movwf INDF incf FSR,f decfsz compteur,f goto wr1 movlw ACK call transmit goto main wFLASH: ; ecriture dans la FLASH clrwdt movf adlow,w movwf adresseL movf adhigh,w movwf adresseH movlw d'255' movwf seconde wf1: clrwdt movf seconde,w btfsc zero btfss _receivedcar goto wf1 bcf _receivedcar movf caractere,w movwf dataF call writeF movlw ACK call transmit movf adlow,w addlw 1 btfsc zero incf adhigh,f movf adlow,w goto main wEEPROM: ; ecriture dans l'EEPROM movf adlow,w movwf adresse movlw d'255' movwf seconde we1: clrwdt movf seconde,w btfsc zero goto main btfss _receivedcar goto we1 bcf _receivedcar movf caractere,w movwf dataee call writeEE movlw ACK call transmit incf adlow,f goto main firstaccess: ; aucune clef dans la flash bsf _clignote fa1: clrwdt call litcode btfss STATUS,C goto fa1 bcf _clignote bcf _rouge call entercode bsf _verte call setrelais bcf _verte bsf _rouge goto main newaccess: ; adjonction d'une clef movlw 0 ; verifier movwf adresse ; si call readEE ; le nombre maxi de clef addlw 1 ; n'est pas atteint sublw nbclef btfss STATUS,C goto endna bcf _verte bcf _rouge bsf _clignote clrf seconde na0: clrwdt movf seconde,w xorlw 5 btfss zero goto na0 clrf seconde na1: clrwdt movf seconde,w xorlw 0A ; time out = 10 secondes btfsc zero goto endna call litcode btfss STATUS,C goto na1 call entercode bcf _clignote bcf _rouge bsf _verte call setrelais endna: bcf _clignote bcf _verte bsf _rouge goto main access: ; une clef a été présentée clrwdt call findkey btfss STATUS,C goto main ; la clef n'est pas valide bcf _rouge bsf _verte call setrelais bcf _verte bsf _rouge movf key,w btfss zero ; si la precedente clef est la 0 goto main clrwdt call litcode ; alors aller voir si elle est tjrs la btfss STATUS,C goto main ; la clef présente n'est plus la bcf _rouge ; sinon passer en mode programmation bsf _clignote goto newaccess ; adjonction d'une clef setrelais: movlw 1 movwf adresse clrwdt call readEE ; lire l'adresse 1 de l'eeprom xorlw 0 btfsc zero goto bistable ; si adresse(1)=0 alors bistable movwf decompte ; sinon adresse(1)=tempo relais clrf seconde bsf _relais ; enclencher le relais sr1: clrwdt movf seconde,w ; et attendre xorwf decompte,w btfss zero ; la tempo goto sr1 bcf _relais ; declencher le relais return bistable: movf PORTB,w ; complementer xorlw b'00100000' ; B5 ( sortie relais ) movwf PORTB clrf seconde ; et atendre bs1: clrwdt movf seconde,w xorlw 5 ; 5 secondes btfss zero goto bs1 return ;----------------------------------------------------------------------------------- ; ecriture de la clef dans la flash et MAJ index ( adresse 0 de l'EEPROM ) ;----------------------------------------------------------------------------------- entercode: movlw 0 movwf adresse call readEE movwf nbkey movlw nbclef ; nombre maxi de clef xorwf nbkey,w ; à comparer au nombre de clef btfsc zero return ; si egal alors retour movlw alow movwf adresseL movlw ahigh movwf adresseH movf nbkey,w btfsc zero goto ec10 ec1: clrwdt decf nbkey,f movf adresseL,w addlw 8 btfsc STATUS,C incf adresseH,f movwf adresseL movf nbkey,w btfsc STATUS,Z goto ec10 goto ec1 ec10: movlw serie movwf FSR movlw 8 movwf temp1 ; compteur ( nombre d'octets ) ec2: ; ecriture de la clef clrwdt movf INDF,w movwf dataF call writeF incf adresseL,f btfsc STATUS,Z incf adresseH,f incf FSR,f decfsz temp1,f goto ec2 movlw 0 ; mise à jour du flag nbkey movwf adresse call readEE movwf dataee incf dataee,f call writeEE return ;----------------------------------------------------------------------------------- ; recherche de la clef dans la flash ;----------------------------------------------------------------------------------- findkey: clrf key ; clef maitre indice 0 movlw 00 ; à l'adresse 0 de l'EEPROM movwf adresse call readEE movwf nbkey ; nombre de clef movlw ahigh ; poids fort adresse 1ere clef movwf adresseH movlw alow ; poids faible adresse 1ere clef movwf adresseL addlw 7 ; positionner sur l'octet de CRC movwf adresseL fk1: clrwdt call readF ; lire l'octet de crc xorwf dallasCRC,w ; comparer au crc de l'octet courant btfsc STATUS,Z goto fkcrc ; le CRC est le meme fk10: incf key,f ; numero de la clef maitre decfsz nbkey,f ; sinon clef suivante dans la flash goto fk2 bcf STATUS,C ; derniere clef return ; retour fk2: movlw 8 addwf adresseL,f ; ajouter 8 a l'adresse courante btfsc STATUS,C incf adresseH,f ; si roll over increment adresse haute goto fk1 fkcrc: ; le crc est le même ; verif des octets suivants movlw 7 ; tester les 7 autres codes movwf rotation movf adresseL,w ; sauvegarde adresse courante movwf temp1 movf adresseH,w movwf temp2 movlw part6 ; 1er octet du code movwf FSR ; dans registre d'indirection bsf idem fkcrc1: clrwdt incf adresseL,f decf adresseL,f btfsc STATUS,Z ; adresse basse courante=0 ? decf adresseH,f ; oui alors decrementer le poids fort de l'adresse suivante decf adresseL,f ; et decrementer le poids faible call readF ; lecture de la flash movwf dataF movf INDF,w xorwf dataF,w btfss STATUS,Z bcf idem decf FSR,f ; octet suivant du code decfsz rotation,f goto fkcrc1 bsf STATUS,C ; flag clef trouvée btfsc idem ; si idem est mis return ; alors retour movf temp1,w movwf adresseL movf temp2,w movwf adresseH goto fk10 ;----------------------------------------------------------------------------------- ; ecriture lecture dans l'EEPROM ;----------------------------------------------------------------------------------- ; ; ecriture EEPROM ; en entrée dataee=octet à ecrire ; adresse = adresse ; writeEE: movf adresse,w bank2 movwf EEADR bank0 movf dataee,w bank2 movwf EEDATA bank3 bcf EECON1,EEPGD bsf EECON1,WREN bcf INTCON,GIE movlw 55H movwf EECON2 movlw 0AA movwf EECON2 bsf EECON1,WR wee1: clrwdt btfsc EECON1,WR goto wee1 bcf INTCON,EEIF bcf EECON1,WREN bank0 bsf INTCON,GIE return ; ; lecture EEPROM ; en entrée adresse = adresse à lire ; en sortie W=octet lu ; readEE: movf adresse,w bank2 movwf EEADR bank3 bcf EECON1,EEPGD bsf EECON1,RD bcf STATUS,RP0 movf EEDATA,w bank0 return ;----------------------------------------------------------------------------------- ; ecriture lecture dans la FLASH ;----------------------------------------------------------------------------------- ; ; ecriture FLASH ; en entrée adresseH = MSB adresse ; adresseL = LSB adresse ; dataF = octet à ecrire ; writeF: ; suivant doc MICROCHIP page 45 movf adresseH,w bank2 movwf EEADRH bank0 movf adresseL,w bank2 movwf EEADR bank0 movf dataF,w bank2 movwf EEDATA bank3 bsf EECON1,EEPGD bsf EECON1,WREN bcf INTCON,GIE movlw 55 movwf EECON2 movlw 0AA movwf EECON2 bsf EECON1,WR nop nop bsf INTCON,GIE bcf EECON1,WREN bank0 return ; ; lecture FLASH ; en entrée adresseH = MSB adresse ; adresseL = LSB adresse ; en sortie W=octet lu ; readF: ; suivant doc MICROCHIP page 44 movf adresseH,w bank2 movwf EEADRH bank0 movf adresseL,w bank2 movwf EEADR bank3 bsf EECON1,EEPGD bsf EECON1,RD nop nop bank2 movf EEDATA,W bank0 return ;----------------------------------------------------------------------------------- ; lecture du code du bouton ;----------------------------------------------------------------------------------- litcode: call touchreset ; reset du bouton btfss STATUS,C ; bouton present ? goto notpresent ; non movlw readrom ; commande lecture identification call touchbyte ; et envoi call touchreceive ; lecture octet 1 ( LSB temperature ) movwf serie call touchreceive movwf part1 call touchreceive movwf part2 call touchreceive movwf part3 call touchreceive movwf part4 call touchreceive movwf part5 call touchreceive movwf part6 call touchreceive movwf dallasCRC movlw serie ; verification movwf FSR ; que movlw 8 ; les movwf compteur ; octets clrf tmp ; composants lcboucle: movf INDF,w ; le code addwf tmp,f ; ne decfsz compteur,f ; sont goto lcboucle ; pas movf tmp,w ; tous btfsc zero ; à goto notpresent ; 0 call crc8 ; verification du crc8 return ; si le crc est bon le carry est mis notpresent: bcf STATUS,C return ; ; reset hard sur bouton dallas ; touchreset: bcf _data ; met la ligne à 0 call tempo480 tr2: bsf _data ; tempo movlw 03F ; de movwf compteur ; 70 µS tr3: decfsz compteur,f ; au niveau goto tr3 ; haut tr4: call inversedata ; ligne en entrée btfsc _data goto noack ; pas de reponse de dallas bsf STATUS,C call tempo480 bsf _data call inversedata ; ligne en sortie return noack: bcf STATUS,C clrwdt call tempo480 bsf _data call inversedata ; ligne en sortie return ; ; octet de commande bouton ; l'octet de commande est dans W ; touchbyte: movwf valeur movlw 8 ; nombre de bits movwf rotation ; dans registre rotation bit_loop: rrf valeur,f ; rotation par la droite btfsc STATUS,C goto send_one bcf _data ; mise à 0 de la ligne nop nop nop nop call tempo65 bsf _data goto tb1 send_one: bcf _data ; met la ligne à 0 nop ; pendant nop ; au moins nop ; 1 nop ; microseconde bsf _data ; puis met la ligne à 1 call tempo65 tb1: decfsz rotation,f goto bit_loop return ; ; routine de reception d'un octet ; resultat dans W ; touchreceive: movlw 8 ; nombre de movwf rotation ; rotations bitr_loop: bcf _data ; ligne à 0 nop ; pendant nop ; au nop ; moins nop ; 1 µS call inversedata ; data en entrée bcf STATUS,C nop ; tempo nop ; de nop ; 1 µS ( temps de montée ) btfsc _data ; test de la ligne bsf STATUS,C rrf valeur,f ; et stockage bit dans octet call inversedata ; data en sortie bsf _data call tempo65 ; tempo de 65 µS decfsz rotation,f ; 8 fois goto bitr_loop ; bit suivant movf valeur,w ; octet dans W return tempo65: movlw 04C ; tempo de 65 µS movwf compteur tp651: decfsz compteur,f goto tp651 return tempo480: movlw 0DF ; tempo movwf compteur ; de 480 µS t4801: clrwdt nop nop decfsz compteur,f goto t4801 return crc8: clrf crc movlw 7 movwf nboctet movlw serie movwf FSR vcrc1: clrwdt movlw 8 movwf compteur movf INDF,w vcrc2: clrwdt xorwf crc,w movwf temp rrf temp,w movf crc,w btfsc STATUS,C xorlw 18 movwf temp rrf temp,w movwf crc movf INDF,w movwf temp bcf STATUS,C rrf temp,f btfsc STATUS,C bsf temp,7 movf temp,w movwf INDF decfsz compteur,f goto vcrc2 incf FSR,f decfsz nboctet,f goto vcrc1 fin: movf dallasCRC,w xorwf crc,w bsf STATUS,C btfss STATUS,Z bcf STATUS,C return inversedata: bank1 movf TRISA,w xorlw 1 movwf TRISA bank0 return ;----------------------------------------------------------------------------------- ; initialisations ;----------------------------------------------------------------------------------- initportA: bank0 clrf PORTA bank1 movlw 0x06 ; PORT A = digital input/output movwf ADCON1 movlw b'00000000' ; PORT A en sortie movwf TRISA bank0 bsf _data return initportB: bank0 clrf PORTB bank1 movlw b'00000000' movwf TRISB bank0 return initportC: bank0 clrf PORTC bank1 movlw b'10000000' ; RC7 en entrée ( RX ) movwf TRISC bank0 return inittmr1: ; initialisation du timer 1 clrf TMR1L clrf TMR1H movlw b'00110000' ; timer 1 source = Fosc/4 ; prescaler = 1/8 movwf T1CON movlw 0 ; tmr1 := FFFF x 2,89 µS = 0,2 secondes movwf TMR1L movlw 0 movwf TMR1H bank1 bsf PIE1,TMR1IE ; met les interruptions sur timer 1 bank0 bsf T1CON,TMR1ON ; start timer 1 return initint: bsf INTCON,PEIE ; periperal int enable bsf INTCON,GIE ; global int enable return initwdt: ; initialisation du watchdog movlw b'11111100' ; prescaler du wdt à 16x72 mS = 1 seconde bank1 movwf OPTION_REG bank0 return ;----------------------------------------------------------------------------------- ; RS232 ;----------------------------------------------------------------------------------- initV24: bank1 bcf TXSTA,BRGH ; low speed pour diviseur bsf TXSTA,CSRC ; master mode movlw 11H ; valeur 17 movwf SPBRG ; dans diviseur horloge 9600 bauds bcf TXSTA,SYNC ; mode asynchrone bsf TXSTA,TXEN ; emission enable bsf PIE1,RCIE ; interrupt sur reception bank0 bsf RCSTA,CREN ; reception continue enable bsf RCSTA,SPEN ; serial port enable return ; ; envoi d'un caractere sur la liaison ; caractere dans W ; transmit: bank1 transmit1: btfss TXSTA,TRMT ; registre emission vide ? goto transmit1 ; non alors retour bank0 movwf TXREG ; registre emission := accu bank1 transmit2: clrwdt btfss TXSTA,TRMT goto transmit2 bank0 return interrupt: clrwdt movwf saveW movf STATUS,w bank0 movwf savesta ; sauvegarde registre de status movf FSR,w movwf saveFSR btfsc PIR1,RCIF ; caractere dans buffer goto reception btfsc PIR1,TMR1IF ; timer 1 expire goto timer1int goto endint reception: btfsc RCSTA,OERR ; over run error goto orerror bcf PIR1,RCIF movf RCREG,w ; caractere dans W movwf caractere bsf _receivedcar goto endint orerror: bcf RCSTA,CREN bsf RCSTA,CREN movf RCREG,w goto endint timer1int: bcf PIR1,TMR1IF ; RAZ flag decfsz timer,f ; 5 rotations ? goto endint movlw 5 movwf timer incf seconde,f ; seconde=seconde+1 btfss _clignote goto endint movlw masque xorwf PORTB,f endint: movf saveFSR,w movwf FSR bcf STATUS,RP0 movf savesta,w movwf STATUS ; reprise registre statut movf saveW,w ; reprise accu retfie end