你是用I2C吗?如下:
;启动I2C总线子程序
I2C_START:
MOVLW 0E6H
TRIS RB ;SCL/SDA 为输出
BSF SDA
NOP
BSF SCL ;起始条件建立时间大于4.7us
NOP
NOP
NOP
NOP
NOP
BCF SDA
NOP ;起始条件锁定时大于4us
NOP
NOP
NOP
NOP
BCF SCL ;钳住总线,准备发数据
NOP
RETLW 00H
;结束总线子程序
I2C_STOP:
MOVLW 0E6H
TRIS RB ;SCL/SDA 为输出
BCF SDA
NOP
BSF SCL ;发送结束条件的时钟信号
NOP ;结束总线时间大于4us
NOP
NOP
NOP
NOP
BSF SDA ;结束总线
NOP ;保证一个终止信号和起始信号的空闲时间大于4.7us
NOP
NOP
NOP
RETLW 00H
;发送应答信号子程序
I2C_SACK:
MOVLW 0E6H
TRIS RB ;SCL/SDA 为输出
BCF SDA ;将SDA置0
NOP
NOP
BSF SCL
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
BCF SCL
NOP
NOP
RETLW 00H
;发送非应答信号
I2C_SNACK:
MOVLW 0E6H
TRIS RB ;SCL/SDA 为输出
BSF SDA ;将SDA置1
NOP
NOP
BSF SCL
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
BCF SCL
NOP
NOP
RETLW 00H
; 检查应答位子程序
; 返回值,ACK=1时表示有应答
I2C_CACK:
MOVLW 0F6H
TRIS RB ;SCL 为输出,SDA 为输入
NOP
BSF SCL
BCF ACK
NOP
NOP
BTFSC SDA
GOTO CEND
BSF ACK ;判断应答位
CEND: NOP
BCF SCL
NOP
RETLW 00H
;发送字节子程序
I2C_WRBYTE:
MOVLW 0E6H
TRIS RB ;SCL/SDA 为输出
MOVLW 08H
MOVWF R0
WLP:
RLF WR_DATA,1 ;取数据位
BTFSS STATUS,0
GOTO WR0 ;判断数据位
WR1:
BSF SDA ;发送1
NOP
BSF SCL
NOP
NOP
NOP
NOP
NOP
BCF SCL
GOTO WLP1
WR0:
BCF SDA ;发送0
NOP
BSF SCL
NOP
NOP
NOP
NOP
NOP
BCF SCL
WLP1:
DECFSZ R0,1
GOTO WLP
RETLW 00H
;读取字节子程序
I2C_RDBYTE:
MOVLW 0F6H
TRIS RB ;SCL 为输出,SDA 为输入
MOVLW 08H
MOVWF R0
RLP:
BSF SCL ;时钟线为高,接收数据位
NOP
NOP
BTFSS SDA ;读取数据位
GOTO RLP0
BSF STATUS,0
GOTO RLP1
RLP0:
BCF STATUS,0
RLP1:
RLF RD_DATA,1 ;进行数据位的处理
BCF SCL ;将SCL拉低,时间大于4.7us
NOP
NOP
DECFSZ R0,1 ;未够8位,再来一次
GOTO RLP
RETLW 00H
;向器件指定子地址写N个数据
WRITE_24LC:
CALL I2C_START ;起动总线
MOVLW 0A0H
MOVWF WR_DATA
CALL I2C_WRBYTE ;发送器件从地址
CALL I2C_CACK
BTFSS ACK
GOTO RETWRN ;无应答则退出
MOVF SUBA,0 ;指定子地址
MOVWF WR_DATA
CALL I2C_WRBYTE
CALL I2C_CACK
WRDA:
MOVF INDF,0
MOVWF WR_DATA
CALL I2C_WRBYTE ;开始写入数据
CALL I2C_CACK
BTFSS ACK
GOTO RETWRN ;无应答则退出
INCF FSR,1
DECFSZ NUMBYTE,1 ;判断写完没有
GOTO WRDA
RETWRN: CALL I2C_STOP
RETLW 00H
;向器件指定子地址读取N个数据
READ_24LC:
CALL I2C_START ;起动总线
MOVLW 0A0H
MOVWF WR_DATA
CALL I2C_WRBYTE ;发送器件从地址
CALL I2C_CACK
BTFSS ACK
GOTO RETRDN ;无应答则退出
MOVF SUBA,0 ;指定子地址
MOVWF WR_DATA
CALL I2C_WRBYTE
CALL I2C_CACK
CALL I2C_START ;重新起动总线
MOVLW 0A1H
MOVWF WR_DATA ;准备进行读操作
CALL I2C_WRBYTE
CALL I2C_CACK
BTFSS ACK
GOTO RETRDN ;无应答则退出
RDN1:
CALL I2C_RDBYTE ;读操作开始
MOVF RD_DATA,0
MOVWF INDF
DECFSZ NUMBYTE,1
GOTO SACK
CALL I2C_SNACK ;最后一字节发非应答位
RETRDN:
CALL I2C_STOP ;并结束总线
RETLW 00H
SACK:
CALL I2C_SACK
INCF FSR,1
GOTO RDN1