LIST P=PIC16C84, R=HEX
INCLUDE pic16f84.inc
LIST
;pines
#define SDA PORTB,4
#define SDATRIS TRISB,4
#define SCL PORTB,5
#define SCLTRIS TRISB,5
;variables en RAM
ORG 0C
CNT RES 1 ;CNT ... contador para la TX/RX de bytes!
CNT1 RES 1 ;CNT1 ... contador
cont2 RES 1 ;cont2 ... contador para la rutina de 5ms
cont3 RES 1 ;cont3 ... contador para la rutina de 5ms
ADDRESS RES 1 ;ADDRESS ... dirección donde se Lee/Escribe los datos
DATO RES 1 ;DATO ... dato donde se lee/escribe
I2CBUF RES 1 ;I2CBUF ... buffer para enviar o recibir el dato
I2CDI RES 1 ;I2CDI ... Dato de entrada (bit)
I2CDO RES 1 ;I2CDO ... Dato de salida (bit)
I2CACKF RES 1 ;I2CACKF ... Registro de ACK
;fin de variables en RAM
ORG 0
GOTO INI
;******************************************************************************
; RUTINAS DE COMUNICACION SERIE (MODULO I2C)
;******************************************************************************
;
; GENERA START BIT
;
START_I2C
BSF STATUS,RP0; selecciona banco1
BCF SDATRIS ; SDA salida
BCF SCLTRIS ; SCL salida
BCF STATUS,RP0; selecciono banco0
BSF SDA
BCF SCL ; bajo clock
NOP ;
BSF SCL ; subo clock
GOTO $+1 ;
GOTO $+1 ;
GOTO $+1 ;
NOP ;
BCF SDA ; bajo datos
GOTO $+1 ;
GOTO $+1 ;
GOTO $+1 ;
NOP ;
BCF SCL ; y bajo clock para generar start bit
GOTO $+1 ;
GOTO $+1 ;
RETURN ;
;
; GENERA STOP BIT
;
STOP_I2C
BSF STATUS,RP0; selecciona banco1
BCF SDATRIS ; SDA salida
BCF SCLTRIS ; SCL salida
BCF STATUS,RP0; selecciono banco0
BCF SDA ; bajo datos
GOTO $+1 ;
GOTO $+1 ;
BSF SCL ; subo clock
GOTO $+1 ;
GOTO $+1 ;
BSF SDA ; subo datos
GOTO $+1 ;
GOTO $+1 ;
BCF SCL ; bajo clock
GOTO $+1 ;
GOTO $+1 ;
RETURN ; y retorno
;
; ENVIA UN BIT POR SDA
;
BITOUT_I2C
BSF STATUS,RP0; selecciona banco1
BCF SDATRIS ; SDA salida
BCF SCLTRIS ; SCL salida
BCF STATUS,RP0; selecciono banco0
BTFSS I2CDO,7 ; enviar un 1 ?
GOTO I2CBLO ; no, envio un 0...
BSF SDA ; pongo SDA en 1
GOTO CLKOUT ;
I2CBLO
BCF SDA ; pongo SDA en 0
CLKOUT
BSF SCL ; y clockeo
GOTO $+1 ;
GOTO $+1 ;
GOTO $+1 ;
BCF SCL ;
RETURN ; y salgo
;
; RECIBE UN BIT POR SDA
;
BITIN_I2C
BSF I2CDI,7 ; asumo que llega un 1
BSF STATUS,RP0; selecciona banco1
BSF SDATRIS ; SDA entrada
BCF SCLTRIS ; SCL salida
BCF STATUS,RP0; selecciono banco0
BSF SCL ; subo clock
GOTO $+1 ;
GOTO $+1 ;
GOTO $+1 ;
BTFSS SDA ; recibio un 1 ?
BCF I2CDI,7 ; no, es 0
BCF SCL ; bajo clock
RETURN ; y salgo
;
; RUTINA DE TRANSMISION POR I2C
;
I2C_TX
MOVLW d'8' ; son 8 bits a contar
MOVWF CNT ;
I2C_TXLP
BCF I2CDO,7 ; asumo que sale un 0
BTFSC I2CBUF,7; sacar un 0 ?
BSF I2CDO,7 ; no, sale un 1...
CALL BITOUT_I2C; envio bit
RLF I2CBUF,F; acomodo para sacar proximo bit
DECFSZ CNT,F ; salieron los 8 ?
GOTO I2C_TXLP; no, continuo sacando...
CALL BITIN_I2C; leo bit de acknowledge
BCF I2CACKF,7 ; asumo que es 0
BTFSC I2CDI,7 ; es 0 ?
BSF I2CACKF,7 ; no, envio un 1
RETURN ; y salgo
;
; RUTINA DE RECEPCION POR I2C
;
I2C_RX
CLRF I2CBUF ; borro buffer
MOVLW d'8' ; son 8 bits a leer
MOVWF CNT ;
BCF STATUS,C ; borro flag de carry
I2C_RXLP
RLF I2CBUF,F; roto un bit a la izquierda
CALL BITIN_I2C; y leo bit enviado
BTFSC I2CDI,7 ; llego un 0 ?
BSF I2CBUF,0; no, escribo un 1 en el buffer
DECFSZ CNT,F ; llegaron los 8 bits ?
GOTO I2C_RXLP; no, sigo reciviendo...
BCF I2CDO,7 ;
BTFSC I2CACKF,7 ;
BSF I2CDO,7 ;
CALL BITOUT_I2C; envio bit de acknowledge
RETURN ; y salgo
;
; LECTURA DE LA MEMORIA 24Cxx
;
RD24CXX
CALL START_I2C; envio condicion de start
MOVLW 0A0 ; traigo direccion de esclavo
MOVWF I2CBUF ; y cargo en buffer
CALL I2C_TX ; direcciono memoria
MOVFW ADDRESS ; traigo direccion a leer
MOVWF I2CBUF ;
CALL I2C_TX ; y envio a memoria
CALL START_I2C; envio condicion de start
MOVLW 0A1 ; direcciono memoria para lectura
MOVWF I2CBUF ; cargo en buffer
CALL I2C_TX ; y envio
BCF I2CACKF,7 ; preparo para acknowledge en 0
CALL I2C_RX ; y leo byte direccionado
CALL STOP_I2C; genero condicion de stop
MOVFW I2CBUF ; cargo dato leido en
MOVWF DATO ; registro de datos de memoria
RETURN ; y salgo
;
; ESCRITURA DE LA MEMORIA 24Cxx
;
WR24CXX
CALL START_I2C; genero bit de start
MOVLW 0A0 ; cargo direccion del esclavo
MOVWF I2CBUF ; en buffer
CALL I2C_TX ; envio...
MOVFW ADDRESS ; cargo direccion a escribir
MOVWF I2CBUF ; en buffer
CALL I2C_TX ; envio...
MOVFW DATO ; cargo dato a escribir
MOVWF I2CBUF ; en buffer
CALL I2C_TX ; envio...
CALL STOP_I2C; genero bit de stop
MOVLW d'60' ;
MOVWF CNT1 ;
WR24POLL
CALL START_I2C;
MOVLW ADDRESS ;
MOVWF I2CBUF ;
CALL I2C_TX ;
BTFSS SDA ;
GOTO WR24P_EXIT;
DECFSZ CNT1,F ;
GOTO WR24POLL;
RETLW 0xFF ;
WR24P_EXIT
CALL DEL5MS; espero 10 mseg para dar tiempo a memoria
CALL DEL5MS
RETLW 0x00 ; y salgo
;
; Retardo de 5MS
;
DEL5MS MOVLW d'6' ; 1 set numero de repeticion (B)
MOVWF cont2 ; 1 |
PLoop1 MOVLW d'207' ; 1 set numero de repeticion (A)
MOVWF cont3 ; 1 |
PLoop2 CLRWDT ; 1 clear watchdog
DECFSZ cont3, 1; 1 + (1) es el tiempo 0 ? (A)
GOTO PLoop2 ; 2 no, loop
DECFSZ cont2, 1; 1 + (1) es el tiempo 0 ? (B)
GOTO PLoop1 ; 2 no, loop
PDelL1 GOTO PDelL2 ; 2 ciclos delay
PDelL2 CLRWDT ; 1 ciclo delay
RETURN ; 2+2 Fin.
;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*;
;
; RUTINA QUE MUESTRA EN EL PUERTO B
;
MOSTRAR
BSF STATUS,RP0; selecciona banco1
CLRF PORTB ; SDA entrada
BCF STATUS,RP0; selecciono banco0
MOVFW DATO
MOVWF PORTB
RETURN
;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*;
;
; PRINCIPAL
;
INI
MOVLW 47 ;
MOVWF DATO ;inicializamos las variables del dato a meter y
MOVLW 05 ;también la dirección inicial
MOVWF ADDRESS ;
CALL WR24CXX
CALL RD24CXX
CALL MOSTRAR
GOTO $
END;