;********************************************************************** ; Décodage RC5 ; héritage : routine MCS51 ; Recréé pour le PIC par DA en janvier 2004 ; ; HORLOGE : Quartz 4 Mhz ; ;********************************************************************* ; Common macro definitions ; normallement elles sont définies, c'est par précaution #DEFINE CLR bcf #DEFINE SETB bsf #DEFINE CLRC bcf STATUS,C ; clear the Carry flag #DEFINE SETC bsf STATUS,C ; set the Carry flag #DEFINE SKPC btfss STATUS,C ; skip if C=1 #DEFINE SKPNC btfsc STATUS,C ; skip if C=0 #DEFINE SKPZ btfss STATUS,Z ; skip if Z=1 #DEFINE SKPNZ btfsc STATUS,Z ; skip if Z=0 RADIX DEC ; ici on cause décimal par défaut, c'est une sécurité ;********************************************************************** IFDEF __16F84 list p=16F84 ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ; Pas de code protege, pas de watch hdog timer, delai de demarrage, horloge XT. ; __CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _XT_OSC ; Pas de code protege, watch dog timer, delai de demarrage, horloge XT. __IDLOCS h'DADA' #DEFINE IO_Nled_v PORTA,0 ; port RA0 cathode LED vert #DEFINE IO_Nled_j PORTA,1 ; port RA1 cathode LED jaune #DEFINE IO_input PORTA,4 ; port RA4(ST) #DEFINE TRIS_PortA b'00010000' ; entrée détection sur PORT RA4 #DEFINE IO_RX PORTB,0 ; port RB0/Int entrée RS232 inversée (après MAX232) #DEFINE IO_TX PORTB,1 ; port RB1 sortie RS232 inversée (après MAX232) #DEFINE IO_RC PORTB,3 ; port RB3 réseau RC de temporisation #DEFINE IO_Nled_r PORTB,7 ; port RB7 cathode LED rouge #DEFINE TRIS_PortB b'00001001' ; entrée Rx/RB0 et RC/RB3 #DEFINE TRIS_PortB_RCo b'00000001' ; entrée Rx/RB0 et RC/RB3 en sortie ENDIF IFDEF __12C508 ENDIF ;File Register Assignments ***************************************************** ; - PIC12C508 25 bytes de 07h à 1Fh (31) ; - PIC12C509 41 bytes de 07h à 1Fh (bank 0) et 30h à 3F (bank 1) ; - PIC16F84A 68 bytes de 0Ch à 4Fh ; - PIC16C84A 36 bytes de 0Ch à 2Fh Duree EQU 12 Ntau EQU 13 TempsTotal EQU 14 RC5high EQU 15 RC5low EQU 16 RC5adresse EQU 17 RC5commande EQU 18 ;********************************************************************* ;************************************************************ VECTEURS ORG 0x000 ; processor reset vector IFDEF __12C508 movwf OSCCAL GOTO main ; go to beginning of program DATA 0x0FFF ; patch area DATA 0x0FFF ; patch area DATA 0x0FFF ; patch area DATA 0x0FFF ; patch area ENDIF IFDEF __16F84 GOTO main ; go to beginning of program ORG 0x004 ; Timer interrupt vector location RETFIE ; return from interrupt ENDIF ;**************************************************************** DEBUT main btfsc STATUS,NOT_TO call ColdStart WarmStart ; ici il y a eu un time out [11;18;30] NOP ; initialisation des ports IFDEF __12C508 ORG 0x010 ; program V1 ; ORG 0x090 ; program V2 ; ORG 0x110 ; program V3 ; ORG 0x190 ; program V4 ColdStart MOVLW TRIS_GPIO TRIS GPIO MOVLW 0xFF MOVWF GPIO ; par defaut, le port est à 1111 1111 ENDIF IFDEF __16F84 ColdStart SETB STATUS,RP0 ; Bank 1 selectionné MOVLW TRIS_PortA MOVWF TRISA MOVLW TRIS_PortB MOVWF TRISB CLR STATUS,RP0 ; Bank 0 selectionné MOVLW 0xFF MOVWF PORTA ; par defaut, le port est à 1111 1111 MOVWF PORTB ; par defaut, le port est à 1111 1111 ENDIF ; initialisation du registre OPTION ; bit 0,1,2 prédiviseur 0=F/8, 1=F/16, 2=F/32, 3=F/64, 4=F/128, 5=F/256, 6=F/512, 7=F/1024 ; bit 3 PSA=0 prescaler sur timer, PSA=1 prescaler sur watchdog ; bit 4 T0SE timer source edge : T0SE=1 négatif, T0SE=0 positif ; bit 5 T0CS timer clock select : T0CS=1 externe, T0CS=0 interne MOVLW b'11000011' ; prediv Fosc/64 (16µs), PSA=0, T0CS=0 IFDEF __12C508 OPTION ENDIF IFDEF __16F84 SETB STATUS,RP0 ; Bank 1 selectionné MOVWF OPTION_REG CLR STATUS,RP0 ; Bank 0 selectionné ENDIF IFDEF __16F84 ; init liaison RS232 @19200 bauds CALL RS232init ENDIF Time_out MauvaiseMesure MauvaisProtocole Mot_recu ; initialisation des variables CLR IO_Nled_j CLRF Duree CLRF Ntau CLRF TempsTotal MOVLW 0xFF MOVWF RC5high MOVLW 0xF8 MOVWF RC5low BTFSC IO_input ; et on boucle tant que IO_pin=1 GOTO $-1 ; sortie si IO_pin=0, premier front descendant CLRF TMR0 ; reset timer MOVLW 55 ; on cherche le bit de synchro, on démarre biaisé MOVWF Duree GOTO Attente_start ;**************************************************************************** ; attends les fronts descendants puis montants ; et mesure la durée des impulsions positive puis négative ; chaque boucle est équipée d'un compteur pour détecter des time out ; chaque boucle dure 6µs, le time out pète à 256 x Ftimer soit 4096 µs Attente_front10 BTFSS IO_input GOTO $+5 ; sortie si IO_pin=0 MOVF TMR0,W ; W=timer SKPZ GOTO $-4 ; attente front 10 GOTO Time_out ; TMR0 vient de passer à 0 MOVF TMR0,W ; W=timer CLRF TMR0 ; reset timer MOVWF Duree Attente_start NOP ; pour que Timer0 ait le temps de s'incrémenter une fois NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP Attente_front01 BTFSC IO_input GOTO $+5 ; sortie si IO_pin=1 MOVF TMR0,W ; W=timer SKPZ GOTO $-4 ; attente front 10 GOTO Time_out ; TMR0 vient de passer à 0 MOVF TMR0,W ; W=timer CLRF TMR0 ; reset timer ADDWF Duree,F ;**************************************************************************** ; verification de la durée ; Si Duree < tau - epsilon, erreur Ntau = 0 ; Si Duree < (tau - epsilon) et Duree < (tau + epsilon), Ntau = 1 ; Si Duree < 2(tau - epsilon) et Duree < 2(tau + epsilon), Ntau = 2 ; Si Duree < 3(tau - epsilon) et Duree < 3(tau + epsilon), Ntau = 3 ; Si Duree < 4(tau - epsilon) et Duree < 4(tau + epsilon), Ntau = 4 ; Si Duree > 4tau + 4epsilon, erreur Ntau = 0 #DEFINE DemiPeriode 889 ; demi periode du signal IR #DEFINE Tolerance 14 ; tolerance en % #DEFINE Resolution 1600 ; 100*période du LSB du timer #DEFINE T2_low 2*DemiPeriode*(100-Tolerance)/Resolution ; 95 5F #DEFINE T2_high 2*DemiPeriode*(100+Tolerance)/Resolution ; 127 7F #DEFINE T3_low 3*DemiPeriode*(100-Tolerance)/Resolution ; 143 8E #DEFINE T3_high 3*DemiPeriode*(100+Tolerance)/Resolution ; 190 BE #DEFINE T4_low 4*DemiPeriode*(100-Tolerance)/Resolution ; 191 BF #DEFINE T4_high 4*DemiPeriode*(100+Tolerance)/Resolution ; 254 FE ; attention, le time out étant géré sur un timer=FF, ; vaudrait mieux que T4_high soit juste en dessous !! ; avec 16µs de résolution, çà tombe juste..... EvalueDuree CLRF Ntau MOVLW T2_low SUBWF Duree,W ; W = Durée-T2_low SKPC ; skip si C=1, W positif ou nul, Durée >= T2_low GOTO MauvaiseMesure ; saut si C=0 ; W<0 ; Durée < T2_low MOVLW T2_high SUBWF Duree,W ; W = Durée-T2_high SKPC ; skip si C=1, W positif ou nul, Durée >= T2_high GOTO Evalue2 ; retour si C=0 ; W<0 ; Durée < T2_high MOVLW T3_low SUBWF Duree,W ; W = Durée-T3_low SKPC ; skip si C=1, W positif ou nul, Durée >= T3_low GOTO MauvaiseMesure ; saut si C=0 ; W<0 ; Durée < T3_low MOVLW T3_high SUBWF Duree,W ; W = Durée-T3_high SKPC ; skip si C=1, W positif ou nul, Durée >= T3_high GOTO Evalue3 ; retour si C=0 ; W<0 ; Durée < T3_high MOVLW T4_low SUBWF Duree,W ; W = Durée-T4_low SKPC ; skip si C=1, W positif ou nul, Durée >= T4_low GOTO MauvaiseMesure ; saut si C=0 ; W<0 ; Durée < T4_low MOVLW T4_high SUBWF Duree,W ; W = Durée-T4_high SKPC ; skip si C=1, W positif ou nul, Durée >= T4_high GOTO Evalue4 ; retour si C=0 ; W<0 ; Durée < T4_high GOTO MauvaiseMesure ; ici on a Durée >= T4_high ;;; Evalue4 INCF Ntau,F ; Ntau = 4 Evalue3 INCF Ntau,F ; Ntau = 3 Evalue2 INCF Ntau,F ; Ntau = 2 INCF Ntau,F ;**************************************************************************** ; traitement ; TempsTotal = TempsTotal + Durée ; BitLu=255 ; Si TempsTotal pair ; Si Ntau = 2 (Duree+=1 et Durée-=1), BitLu=1 ; Si Ntau = 3 (Durée+=2 et Durée-=1), BitLu=1 ; Si TempsTotal impair ; Si Ntau = 2 (Duree+=1 et Durée-=1), BitLu=0 ; Si Ntau = 3 (Durée+=1 et Durée-=2), BitLu=1, ShiftBitin, BitLu=0 ; Si Ntau = 4 (Durée+=2 et Durée-=2), BitLu=1, ShiftBitin, BitLu=0 ; ShiftBitIn ; si Cy=1, goto Attente_front10 ; MOVF Ntau,W ; TempsTotal = TempsTotal + Ntau ADDWF TempsTotal,F MOVF TempsTotal,W ; TempsTotal pair ou impair ???? ANDLW 1 SKPZ GOTO TempsImpair TempsPair MOVLW 2 ; cas pair et Ntau=2 (11) SUBWF Ntau,W SKPNZ GOTO BitUN MOVLW 3 ; cas pair et Ntau=3 (21) SUBWF Ntau,W SKPNZ GOTO BitUN GOTO MauvaisProtocole TempsImpair MOVLW 2 ; cas impair et Ntau=2 (11) SUBWF Ntau,W SKPNZ GOTO BitZERO MOVLW 3 ; cas impair et Ntau=3 (12) SUBWF Ntau,W SKPNZ GOTO BitUNZERO MOVLW 4 ; cas impair et Ntau=4 (22= SUBWF Ntau,W SKPNZ GOTO BitUNZERO GOTO MauvaisProtocole BitUN SETC RLF RC5low,F ; et on rentre le bit reçu en position basse RLF RC5high,F GOTO BitFin BitUNZERO SETC RLF RC5low,F ; et on rentre le bit reçu en position basse RLF RC5high,F BitZERO CLRC RLF RC5low,F ; et on rentre le bit reçu en position basse RLF RC5high,F BitFin SKPNC GOTO Attente_front10 ; c'est pas fini, on repart dans les boucles d'attentes ;************************************************************************** ; on a fini, on a acquis les 14 bits d'une commande ; BTFSS RC5high,5 ; teste le bit start GOTO MauvaisProtocole ; et s'il est nul, on sort ; normallement çà ne peut pas arriver MOVF RC5low,W ANDLW 0x3F MOVWF RC5commande BTFSS RC5high,4 ; teste le bit derrière le start SETB RC5commande,6 ; et s'il est nul, ajoute 0x40 à la commande BTFSC RC5high,3 ; teste le bit toggle SETB RC5commande,7 ; et si=1, on le copie en position 7 RLF RC5low,F ; décale d'un cran à gauche RLF RC5high,F RLF RC5low,F ; décale d'un cran à gauche RLF RC5high,F MOVF RC5high,W ANDLW 0x9F ; et on écrase les bits start2, toggle MOVWF RC5adresse CALL SendHex CALL SendSp MOVF RC5commande,W CALL SendHex CALL SendCRLF GOTO Mot_recu ;**************************************************************************** IFDEF __16F84 RS232init MOVLW 'T' CALL SendByte MOVLW 'E' CALL SendByte MOVLW 'S' CALL SendByte MOVLW 'T' CALL SendByte MOVLW T2_low CALL SendHex MOVLW T2_high CALL SendHex MOVLW T3_low CALL SendHex MOVLW T3_high CALL SendHex MOVLW T4_low CALL SendHex MOVLW T4_high CALL SendHex CALL SendCRLF RETURN #include ; routine liaison série ENDIF END ; directive 'end of program'