📄 i2cbus.asm
字号:
FLAG EQU RLT ; I2C状态标志寄存器
ERCODE EQU RLTH ; 错误码备份
TXBUF EQU SOU ; 发送数据缓冲器
RXBUF EQU SOUH ; 接收数据缓冲器
BCOUNT EQU CNT ; 位计数
;
TIMER0 EQU 18 ; Delay timer0
TIMER1 EQU 19 ; Delay timer1
; FLAG Bits
ERR EQU 0 ; 出错标志
DI EQU 1 ; 输入位缓存
DO EQU 2 ; 输出位缓存
ACK EQU 3 ; 应答位
;TXDONE EQU 4 ; 发送结束标志
;RXDONE EQU 5 ; 接受结束标志
ADDR EQU 30H ; EEPROM字地址
DATAI EQU 31H ; 存储器数据输入寄存器
DATAO EQU 32H ; 存储器数据输出寄存器
SLAVE EQU 33H ; Device address (1010xxx0)
;#DEFINE SDA PORTB,2 ; RB2, 数据输入输出
;#DEFINE SCL PORTB,1 ; RB1, 串行时钟
#DEFINE SDA PORTC,4 ; RB2, 数据输入输出
#DEFINE SCL PORTC,3 ; RB1, 串行时钟
;PAGE
;-----------------------------------------------------------------------------
; I2C单片机通讯错误状态表以及子程序
;-----------------------------------------------------------------------------
; input : W = 错误码
; output : ERCODE = 错误码
; FLAG[ERR] = 1
;
; 错误码 错误类型
; ------- ------------------------------------------------------
; 1 : SCL 被从器件拉低 (总线忙)
; 2 : SDA 被从器件拉低 (总线忙)
; 3 : 没有收到从器件的应答 (没有握手信号)
; 4 : SDA 线没有释放,以至主控器件无法产生结束位
;-----------------------------------------------------------------------------
;根据错误状态表检测SCL和SDA的电平。代码用在总线裁决上。
ERRCODE
BTFSS FLAG,ERR ; 是否保留上次的错误码
MOVWF ERCODE ; 保存错误码
BSF FLAG,ERR ; 设置出错标志
RETLW 0
;-----------------------------------------------------------------------------
; 开始总线通讯程序
;-----------------------------------------------------------------------------
;产生启动位 (SCL高电平期间,SDA出现下降沿),并检查时钟信号线状态.
BSTART BSF SDA ; SDA为保持为高
BSF SCL ; 设置SCL为高电平
BSF STATUS,RP0
MOVLW B'00111111' ; 设置 SCL, SDA 为输出
MOVWF TRISB
BCF TRISC,3 ;
BCF TRISC,4 ;
BCF STATUS,RP0
MOVLW 1 ; 准备出错状态码 1
BTFSS SCL ; SCL被从器件锁定为低电平?
CALL ERR ; 是
BCF SDA ; 产生启动位
NOP ; 时序调整
NOP
NOP
NOP
NOP
NOP
BCF SCL ; 开始时钟序列
RETLW 0
;PAGE
;-----------------------------------------------------------------------------
; 结束总线通信程序
;-----------------------------------------------------------------------------
;
;产生结束位 (SCL高电平期间,SDA从低电平到高电平)
;并检测总线状态
BSTOP BCF SDA ; SDA=0
BSF SCL ; SCL=1
BSF STATUS,RP0
MOVLW B'00111111' ; SCL, SDA输出状态
MOVWF TRISB
BCF TRISC,3;
BCF TRISC,4;
BCF STATUS,RP0
NOP
NOP
NOP
MOVLW 1 ; 准备出错代码 1
BTFSS SCL ; SCL高电平?
CALL ERR ; 不是,则SCL被从器件锁定为低电平
BSF SDA ; SDA 从低变高
MOVLW 4 ; 准备出错代码 4
BTFSS SDA ; 高电平?
CALL ERR ; 不是,SDA没有被释放
RETLW 0
;-----------------------------------------------------------------------------
; 移入1位数据子程序
;-----------------------------------------------------------------------------
BITIN
BSF SDA ; SDA设为输入
BSF STATUS,RP0
BSF TRISB,2
BSF TRISC,4;
BCF STATUS,RP0
BSF SCL ; 时钟上升为高电平
MOVLW 1
BTFSC SCL ; 判断是否出错
GOTO BIT1
BTFSS FLAG,ERR ; 保留上次的错误码
MOVWF ERCODE ; 保存错误码
BSF FLAG,ERR ; 设置错误标志
BIT1 BCF FLAG,DI
BTFSC SDA ; 读SDA
BSF FLAG,DI
NOP ; 延时
BCF SCL ; 时钟返回低电平
RETLW 0
;PAGE
;-----------------------------------------------------------------------------
; 移出1位数据子程序
;-----------------------------------------------------------------------------
BITOUT BSF STATUS,RP0
BCF TRISB,2 ;SDA设为输出
BCF TRISC,4
BCF STATUS,RP0
BTFSS FLAG,DO
GOTO BIT0
BSF SDA ; 输出1
MOVLW 2
BTFSC SDA ; 检测错误类型2
GOTO CLK1
BTFSS FLAG,ERR ; 保留上次的错误码
MOVWF ERCODE ; 保存错误码
BSF FLAG,ERR ; 设置出错标志
GOTO CLK1 ; SDA被拉低
BIT0 BCF SDA ; 输出0
NOP ; 延时
NOP
NOP
CLK1 BSF SCL
MOVLW 1 ; 错误码 1
BTFSC SCL ; SCL被锁定为低电平?
GOTO BIT2 ; 不是
BTFSS FLAG,ERR ; 是
MOVWF ERCODE ; 保存错误码
BSF FLAG,ERR ; 设定出错标志
BIT2
NOP
NOP
BCF SCL ; SCL返回低电平
RETLW 0
;PAGE
;-----------------------------------------------------------------------------
; 接收数据程序
;-----------------------------------------------------------------------------
I2CRX
MOVLW .8 ; 8 位数据
MOVWF BCOUNT
CLRF RXBUF
RXLP
RLF RXBUF,F ; 数据移到缓冲器
SKPC
BCF RXBUF,0 ; 进位位 ---> RXBUF[0]
SKPNC
BSF RXBUF,0
CALL BITIN
BTFSC FLAG,DI
BSF RXBUF,0 ; 移入位 =1
DECFSZ BCOUNT,F ; 8 位结束?
GOTO RXLP
BCF FLAG,DO
BTFSC FLAG,ACK
BSF FLAG,DO ; 发送应答信号
CALL BITOUT
RETLW 0
;-----------------------------------------------------------------------------
; 发送数据程序
;-----------------------------------------------------------------------------
; 输入: TXBUF
; 输出: 无
;-----------------------------------------------------------------------------
I2CTX
MOVLW .8
MOVWF BCOUNT
TXLP
BCF FLAG,DO ; 移出数据.
BTFSC TXBUF,7 ;
BSF FLAG,DO ; 否则数据位 = 1
CALL BITOUT ; 移出一位
RLF TXBUF,F ; ITXBUF左移
SKPC ; ITXBUF[6] ---> ITXBUF[7]
BCF TXBUF,0 ; ITXBUF[7] ---> 进位位
SKPNC ; 进位位 ---> TXBUF[0]
BSF TXBUF,0
DECFSZ BCOUNT,F ; 8位移完?
GOTO TXLP ; 没有
CALL BITIN ; 接收应答位
MOVLW 3
BTFSC FLAG,DI ; 检测有无应答
CALL ERRCODE ; 没有应答
RETLW 0
;PAGE
;-----------------------------------------------------------------------------
; BYTE-WRITE, write one byte to EEPROM device
;-----------------------------------------------------------------------------
; Input : DATAO= data to be written
; ADDR = destination address
; SLAVE = device address (1010xxx0)
; Output : Data written to EEPROM device
;-----------------------------------------------------------------------------
;
; 080 ; The location for BYTE-WRITE routine can be
; ; assigned anywhere between (377-777) octal.
WPORTBYTE
MOVLW 10100000B ; Get SLAVE address
MOVWF TXBUF ; to TX buffer
CALL BSTART ; Generate START bit
CALL I2CTX ; Output SLAVE address
MOVF ADDR,W ; Get WORD address
MOVWF TXBUF ; into buffer
CALL I2CTX ; Output WORD address
MOVF DATAO,W ; Move DATA
MOVWF TXBUF ; into buffer
CALL I2CTX ; Output DATA and detect acknowledgement
CALL BSTOP ; Generate STOP bit
GOTO $
;
;
;
;-----------------------------------------------------------------------------
; BYTE-READ, read one byte from serial EEPROM device
;-----------------------------------------------------------------------------
; Input : ADDR = source address
; SLAVE = device address (1010xxx0)
; Output : DATAI = data read from serial EEPROM
;-----------------------------------------------------------------------------
;
; ORG 0C0 ; The location for BYTE-READ routine can be
; ; assigned anywhere between (377-777) octal.
RDBYTE
MOVLW 10100000B ; Move SLAVE address
MOVWF TXBUF ; into buffer (R/W = 0)
CALL BSTART ; Generate START bit
CALL I2CTX ; Output SLAVE address. Check ACK.
MOVF ADDR,W ; Get WORD address
MOVWF TXBUF
CALL I2CTX ; Output WORD address. Check ACK.
CALL BSTART ; START READ (if only one device is
MOVLW 10100001B ; connected to the I2C bus)
MOVWF TXBUF
BSF TXBUF,0 ; Specify READ mode (R/W = 1)
CALL I2CTX ; Output SLAVE address
CALL I2CRX ; READ in data and acknowledge
CALL BSTOP ; Generate STOP bit
MOVF RXBUF,W ; Save data from buffer
MOVWF DATAI ; to DATAI file.
goto $
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -