list p=16f628A ; list directive to define processor #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;***** VARIABLE DEFINITIONS ; 0x70-0x7F : zone de 16 octets ram partagée dans toutes les banques w_temp EQU 0x71 ; variable used for context saving status_temp EQU 0x72 ; variable used for context saving fsr_temp equ 0x73 circ_buf1 equ 0x20 PORTA_buf equ 0x21 tx_buf equ 0x22 ; buffer de réception et envoi rx_buf equ 0x32 ; fixés arbitrairement à 16 octets tx_ptr equ 0x42 rx_ptr equ 0x43 sub_tmp equ 0x44 sub_tmp2 equ 0x45 sub_tmp3 equ 0x46 l_tmp1 equ 0x47 l_tmp2 equ 0x48 l_tmp3 equ 0x49 rx433_cnt equ 0x4a rx433_buf equ 0x4b ; 4 octets rx433_buf_2 equ 0x4f ; tampon pour vérifier les erreurs du signal rx433_ok_cnt equ 0x53 ; compte le nombre de réceptions successives identiques wait_cnt equ 0x54 rx433_cnt2 equ 0x55 tmp equ 0x56 LED_R equ 1 LED_V equ 0 RX equ 0 ;********************************************************************** ORG 0x000 ; processor reset vector goto main ; go to beginning of program ORG 0x004 ; interrupt vector movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register movf FSR, W movwf fsr_temp clrf STATUS btfss INTCON, T0IF goto next_int movf PORTA_buf, W movwf PORTA bcf INTCON, T0IF goto fin_int next_int: btfss PIR1, RCIF goto next_int2 ;bsf PORTA, LED_V movlw B'00000110' andwf RCSTA, W btfss STATUS, Z goto ok_rx bcf RCSTA, CREN bsf RCSTA, CREN ok_rx: movf rx_ptr, W xorlw 0x0F btfss STATUS, Z goto rxbufok clrf rx_ptr clrf rx_buf rxbufok: movlw rx_buf addwf rx_ptr, W movwf FSR movf RCREG, w movwf INDF incf rx_ptr, F incf FSR, F clrf INDF goto fin_int next_int2: fin_int: movf fsr_temp, W movwf FSR movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f ; swapf evite de modifier STATUS swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt main: clrf STATUS clrf PORTA clrf PORTB movlw 0x07 movwf CMCON bsf STATUS, RP0 clrf TRISA movlw B'11111011' movwf TRISB bsf OPTION_REG, NOT_RBPU; Désactive les pull-ups sur PORTB bsf PIE1, RCIE ; Active l'interruption sur réception USART bcf STATUS, RP0 bsf INTCON, GIE ; Active interruptions bsf INTCON, PEIE ; Active interruptions périphériques ; bsf INTCON, T0IE ; Active interruption timer0 ; bsf INTCON, INTE ; Active interruption externe (RB0) bsf STATUS, RP0 ; Setup de l'UART movlw .25 ; 9600 bauds (clock=4MHz, BRGH=1) Baudrate=Fosc/(16*(x+1)) movwf SPBRG movlw B'00100110' ; active la transmission; mode asynchrone; BRGH=1 movwf TXSTA bcf STATUS, RP0 movlw B'10010000' ; Réception activée, Port série activé movwf RCSTA clrf tx_buf clrf rx_buf clrf tx_ptr clrf rx_ptr clrf rx433_ok_cnt clrf rx433_buf_2 ; Ce clear permet d'éviter une validation par hasard avec les valeurs aléatoires au reset again: movlw tx_buf addwf tx_ptr, W movwf FSR next_c: movlw HIGH coucou movwf PCLATH movf tx_ptr, W call coucou movwf INDF movf INDF, F btfsc STATUS, Z goto fin_c incf FSR, F incf tx_ptr, F goto next_c fin_c: bsf PORTA, LED_V call bloq_send clrf tx_buf clrf tx_ptr bcf PORTA, LED_V call wait_1s ; goto again read_433: wait4space: btfss PORTB, RX goto $-1 btfsc PORTB, RX ; On attend un space = état bas pendant 7.86ms (on prend au moins 5ms) goto $-1 clrf wait_cnt call wait_320us incf wait_cnt, F btfsc STATUS, Z ; on évite l'overflow decf wait_cnt, F btfss PORTB, RX goto $-5 movf wait_cnt, W sublw .16 ; 16*.32 = 5ms btfsc STATUS, C goto wait4space bsf PORTA, LED_R movlw rx433_buf movwf FSR movlw .4 movwf rx433_cnt2 rx433_loop: clrf INDF movlw .8 movwf rx433_cnt rx433_byte: rlf INDF, F btfsc PORTB, RX ; on attend le front descendant goto $-1 call wait_480us ; schéma d'émission (inspiré UM3750) : bit = 960us btfss PORTB, RX ; 0 = 320us bas puis 640us haut incf INDF, F ; 1 = 640us bas puis 320us haut call wait_320us decfsz rx433_cnt, F goto rx433_byte incf FSR, F decfsz rx433_cnt2, F goto rx433_loop bcf PORTA, LED_R clrf rx433_cnt2 ; On compare le mot reçu avec rx433_buf_2 cmp_loop: movlw rx433_buf addwf rx433_cnt2, W movwf FSR movf INDF, W movwf tmp movlw rx433_buf_2 addwf rx433_cnt2, W movwf FSR movf INDF, W subwf tmp, F btfss STATUS, Z goto cmp_not_ok incf rx433_cnt2, F movlw 4 subwf rx433_cnt2, W btfss STATUS, Z goto cmp_loop cmp_ok: bsf PORTA, LED_V incf rx433_ok_cnt, F btfsc STATUS, Z ; on évite l'overflow decf rx433_ok_cnt, F goto fin_cmp cmp_not_ok: bcf PORTA, LED_V clrf rx433_ok_cnt clrf rx433_cnt2 ; on fait une copie du nouveau mot pour comparer plus tard mv_loop: movlw rx433_buf addwf rx433_cnt2, W movwf FSR movf INDF, W movwf tmp movlw rx433_buf_2 addwf rx433_cnt2, W movwf FSR movf tmp, W movwf INDF incf rx433_cnt2, F movlw .4 subwf rx433_cnt2, W btfss STATUS, Z goto mv_loop fin_cmp: movf rx433_ok_cnt, W ; Si 3 séquences identiques consécutives sur le module 433MHz, sublw .3 ; on envoie la donnée sur le port série. (Une seule fois) btfss STATUS, Z goto read_433 movf rx433_buf, W sublw B'10101010' ; Identificateur btfss STATUS, Z goto read_433 movf rx433_buf+1, W call hex2ascii movlw ' ' call putchar movf rx433_buf+2, W call hex2ascii movf rx433_buf+3, W call hex2ascii goto fin_chaine ; movlw rx433_buf ; movwf rx433_cnt ; movlw .4 ; movwf rx433_cnt2 ;printloop: ; movf rx433_cnt, W ; movwf FSR ; movf INDF, W ; call hex2ascii ; movlw ' ' ; call putchar ; incf rx433_cnt, F ; decfsz rx433_cnt2, F ; goto printloop ; ; movf rx433_ok_cnt, F ; btfsc STATUS, Z ; goto fin_chaine ; movlw ' ' ; call putchar ; movf rx433_ok_cnt, W ; call hex2ascii ; fin_chaine: movlw '\n' call putchar movlw '\r' call putchar movlw 0 call putchar call bloq_send clrf tx_buf clrf tx_ptr goto read_433 goto main ;******************* SOUS ROUTINES ******************** putchar: movwf sub_tmp movlw tx_buf addwf tx_ptr, W movwf FSR movf sub_tmp, W movwf INDF incf tx_ptr, F incf FSR, F clrf INDF return hex2ascii: ; nombre hexa pasé dans W, écrit dans tx_buf - pas de vérif du buffer movwf sub_tmp movlw tx_buf addwf tx_ptr, W movwf FSR movlw .2 movwf sub_tmp2 h2al: swapf sub_tmp, F movf sub_tmp, W andlw 0x0F movwf sub_tmp3 addlw '0' movwf INDF sublw '9' btfsc STATUS, C goto h2a2 movlw 'A' - '0' - .10 addwf INDF, F h2a2: incf tx_ptr, F incf FSR, F decfsz sub_tmp2, F goto h2al clrf INDF return bin2ascii: ; Convertir un nombre en une chaine le représentant en base 2 movwf sub_tmp movlw tx_buf addwf tx_ptr, W movwf FSR movlw .8 movwf sub_tmp2 h2b1: rlf sub_tmp, F btfss STATUS, C goto $+3 movlw '1' goto $+2 movlw '0' movwf INDF incf tx_ptr, F incf FSR, F decfsz sub_tmp2, F goto h2b1 clrf INDF return bloq_send_rxbuf: movlw rx_buf goto $+2 bloq_send: ; envoie le contenu de tx_buf; bloquant; fin de chaine par 0 movlw tx_buf ; a appeller depuis banque 0 :/ movwf FSR bqsl: movf INDF, W btfsc STATUS, Z return ; movf INDF, W movwf TXREG ; l'envoi est déclenché par le mov bsf STATUS, RP0 btfss TXSTA, TRMT goto $-1 bcf STATUS, RP0 incf FSR, F goto bqsl wait_1s: ; 986ms movlw 5 movwf l_tmp3 clrf l_tmp2 clrf l_tmp1 decfsz l_tmp1, F goto $-1 decfsz l_tmp2, F goto $-4 decfsz l_tmp3, F goto $-7 return wait_1ms: ; ncycles = 5+l_tmp_2*(4+l_tmp1*3) movlw .5 movwf l_tmp2 movlw .65 movwf l_tmp1 decfsz l_tmp1, F goto $-1 decfsz l_tmp2, F goto $-5 return wait_480us: movlw .1 movwf l_tmp2 movlw .157 movwf l_tmp1 decfsz l_tmp1, F goto $-1 decfsz l_tmp2, F goto $-5 return wait_320us: movlw .45 movwf l_tmp2 movlw .1 movwf l_tmp1 decfsz l_tmp1, F goto $-1 decfsz l_tmp2, F goto $-5 return ;************************ DATA ******************* ORG 0x300 ; Pour éviter les problèmes avec PCL qui est 8 bits coucou: addwf PCL, F dt "Coucou\n\r", 0 ; initialize eeprom locations ; ORG 0x2100 ; DE 0x00, 0x01, 0x02, 0x03 END ; directive 'end of program'