📄 i2cv10.inc
字号:
;***********************************************************
;程序名称: I2C访问子程序
;程序开发: 前锋集团技术中心 江海波
;编写时间: 2004年12月17日
;软件环境: 供税控收款器QF561型的上层C语言使用
;硬件环境: QF561型税控器,硬件环境V1.0
; I2C芯片为MICROCHIP公司24LC256
; 基于I2C接口的EEPROM
;MCU: TOSHIBA TMP93CS41@max 16M/1
;程序版本: V1.00
;最后修订时间: 2004年12月17日
;修订部分说明:
;----------------------------------------------------------
;**********************************************************
;定义伪指令,当软,硬件结构改变时修改本位置上的指令即可完成程序修改
;----------------------------------------------------------
;I2C总线的数据线被定义在端口i2c_sda_port的i2c_sda_bit位上
i2c_sda_port equ PA
i2c_sda_bit equ 7
;由于涉及方向转换,该端口的方向控制字为
i2c_s_p_cr equ PACR ;---I2C Sda Port Control Register
;----------------------------------------------------------
;I2C总线的时钟线被定义在端口i2c_scl_port的i2c_scl_bit位上
i2c_scl_port equ PA
i2c_scl_bit equ 6
;----------------------------------------------------------
;I2C-EEPROM的写保护端被定义在i2c_pro_port的i2c_pro_bit位上
i2c_pro_port equ PA
i2c_pro_bit equ 5
;----------------------------------------------------------
;两片EEPROM的选择由上层选择,其将读写数据头在
ee_rw equ 0x100 ;---EEprom Read or Write flag
;----------------------------------------------------------
;数据操作的地址高位由C语言给出,被放置在地址
data_addr_h equ 0x101 ;---DATA ADDRess High
;----------------------------------------------------------
;数据操作的地址低位由C语言给出,被放置在地址
data_addr_l equ 0x102 ;---DATA ADDRess Low
;----------------------------------------------------------
;数据操作的地址长度由C语言给出,其高段被放置在地址
data_leng_h equ 0x103 ;---DATA LENGth High
;----------------------------------------------------------
;数据操作的地址长度由C语言给出,其低段被放置在地址
data_leng_l equ 0x104 ;---DATA LENGth Low
;----------------------------------------------------------
;接收到的数据和要发送的数据的缓冲区首地址在:
i2c_buffer equ 0x145
;----------------------------------------------------------
;为了方便程序调试和硬件Debug模式下的调试工作,程序安排了一个错误标志
;这个标志被定义在地址:
i2c_error_flag equ 0x144
;----------------------------------------------------------
;由于I2C口线操作涉及方向改变,我们定义了一个内存空间以保存其方向字信息
i2c_port_cr equ PACR_RAM
;----------------------------------------------------------
;i2c_output和i2c_input两个函数亦需要做相应的调整
;----------------------------------------------------------
;通用寄存器分配:
;w:全局变量,用于发送和接受一个字节
;c:临时变量,仅在当前程序中使用,一般作为局部计数器
;b:临时变量,发送一个字节时做计数器用
;hl:全局变量,做发送/接收字节个数的计数器用
;xix:数据指针,指向缓冲区
;----------------------------------------------------------
;**********************************************************
;----------------------全局函数声明------------------------
PUBLIC __i2cee_byte_rd ;---单字节随机地址读,由上层C语言调用
PUBLIC __i2cee_byte_wr ;---单字节随机地址写,由上层C语言调用
PUBLIC __i2cee_seri_rd ;---多字节连续地址读,由上层C语言调用
PUBLIC __i2cee_seri_wr ;---单字节连续地址写,由上层C语言调用
;**********************************************************
;**********************端口方向控制************************
i2c_output: ;调用本函数,使得SDA为输出口
or (i2c_port_cr),0x80 ;SDA线为输出口
ld (i2c_s_p_cr),(i2c_port_cr) ;口线设置
ret
i2c_input: ;调用本函数,使得SDA为输入口
and (i2c_port_cr),0x7F ;SDA线为输入口
ld (i2c_s_p_cr),(i2c_port_cr) ;口线设置
ret
;**********************I2C用延迟函数***********************
i2c_delay_5us: ;延迟5us,主要用于启动
ld c,0x03
i2c_d_5_loop:
nop
nop
djnz c,i2c_d_5_loop
ret
i2c_delay_3us: ;延迟3us,主要用于发送函数
ld c,0x02
i2c_d_3_loop:
nop
djnz c,i2c_d_3_loop
ret
;**********************I2C发送函数*************************
i2c_send: ;调用本函数,发送W寄存器中的一个字节到总线上
call i2c_output ;口线设置为输出
ld b,0x08 ;计数器,循环8次
i2c_s_loop:
rlc 1,w
stcf i2c_sda_bit,(i2c_sda_port) ;数据送到DSA线上
call i2c_delay_3us
set i2c_scl_bit,(i2c_scl_port) ;SCK=1
call i2c_delay_5us
res i2c_scl_bit,(i2c_scl_port) ;SCK=0
djnz b,i2c_s_loop ;循环发送8个BIT位
res i2c_sda_bit,(i2c_sda_port) ;SDA=0
ret ;此时SDA=0,SCL=0
;**********************I2C接收函数*************************
i2c_rec:
call i2c_input ;口线设置为输入
ld b,0x08
i2c_r_loop:
call i2c_delay_5us
set i2c_scl_bit,(i2c_scl_port) ;SCK=1
call i2c_delay_5us ;NOTE1
ldcf i2c_sda_bit,(i2c_sda_port) ;采样SDA线,接收一个BIT位
rl 1,w
res i2c_scl_bit,(i2c_scl_port) ;SCK=0
djnz b,i2c_r_loop ;循环接收8个BIT位
ret ;此时SDA不定,SCL=0
;NOTE1:按照环境温度-40摄氏度到+125摄氏度设计
;***********************发送启动位*************************
i2c_start:
call i2c_output ;口线设置为输出
set i2c_scl_bit,(i2c_scl_port) ;口线初始化,SCL=1
call i2c_delay_5us
set i2c_sda_bit,(i2c_sda_port) ;口线初始化,SDA=1
call i2c_delay_5us ;NOTE2
res i2c_sda_bit,(i2c_sda_port) ;发送启动位,SDA=0
call i2c_delay_5us
res i2c_scl_bit,(i2c_scl_port) ;发送启动位,SCL=0
ret ;此时SDA=0,SCL=0
;NOTE2:由PHILIPS的I2C协议2.0版,停止位和下一个启动位之间的时间间隔不得小于
;4.7us由于这里采用了一个停止位来做初始化,所以加入本延迟时间
;**********************发送停止位**************************
i2c_stop:
call i2c_output ;口线设置为输出
set i2c_scl_bit,(i2c_scl_port) ;发送停止位,SCL=1
call i2c_delay_5us
set i2c_sda_bit,(i2c_sda_port) ;发送停止位,SDA=1
ret
;***********************应答检测***************************
i2c_ack_get: ;---I2C ACKnowledge GET
call i2c_input ;口线设置为输入
set i2c_scl_bit,(i2c_scl_port) ;发生应答检测脉冲SCL=1
ldcf i2c_sda_bit,(i2c_sda_port) ;采样总线
jp c,i2c_ack_er ;总线为1,说明无应答
ld (i2c_error_flag),0x04 ;检测到了应答信号,写标志
i2c_ack_er:
res i2c_scl_bit,(i2c_scl_port) ;SCL=0
ret ;此时SDA=0,SCL=0
;*********************应答发生*****************************
i2c_ack_gen: ;---I2C ACKnowledge GENerate
call i2c_output ;口线设置为输出
res i2c_sda_bit,(i2c_sda_port) ;SDA=0,开始应答
set i2c_scl_bit,(i2c_scl_port) ;发生应答检测脉冲,SCL=1
call i2c_delay_5us
res i2c_scl_bit,(i2c_scl_port) ;结束应答检测脉冲,SCL=0
ret ;此时SDA=0,SCL=0
i2c_nack_gen: ;---I2C NotACKnowledge GENerate
call i2c_output ;口线设置为输出
set i2c_sda_bit,(i2c_sda_port) ;SDA=1,开始非应答
set i2c_scl_bit,(i2c_scl_port) ;发生应答检测脉冲,SCL=1
call i2c_delay_5us
res i2c_scl_bit,(i2c_scl_port) ;结束应答检测脉冲,SCL=0
res i2c_sda_bit,(i2c_sda_port) ;结束应答检测脉冲,SDA=0
ret ;此时SDA=0,SCL=0
;**********************************************************
;-----------Main Of I2C EEPROM Transmit Function-----------
;********************单字节随机地址读************************
__i2cee_byte_rd: ;---signal byte,randum address read
di ;关闭中断
call i2c_start ;启动总线
ld w,(ee_rw) ;载入C语言传递来的控制字
and w,0xFE ;发送控制字,方向为送出
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_h) ;载入读取位置的高地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_l) ;载入读取位置的低地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
call i2c_start ;启动总线
ld w,(ee_rw) ;载入C语言传递来的控制字
or w,0x01 ;发送控制字,方向为读入
call i2c_send ;发送
ld (i2c_error_flag),0x07 ;初始化错误标志,为无应答
call i2c_ack_get ;接收应答信号
call i2c_rec ;接收
ld (i2c_buffer),w ;将收到的数据存在缓冲区
call i2c_nack_gen ;发送非应答信号
call i2c_stop ;停止总线
ei 0x00 ;完成任务后开中断
ret
;*******************单字节随机地址写***********************
__i2cee_byte_wr:
di ;关闭中断
res i2c_pro_bit,(i2c_pro_port) ;关写保护
call i2c_start ;启动总线
ld w,(ee_rw) ;载入C语言传递来的控制字
and w,0xFE ;发送控制字,方向为送出
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_h) ;载入读取位置的高地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_l) ;载入读取位置的低地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(i2c_buffer) ;从缓冲区载入要发送的数据
call i2c_send
ld (i2c_error_flag),0x07 ;初始化错误标志,为无应答
call i2c_ack_get ;接收应答信号
call i2c_stop ;停止总线
set i2c_pro_bit,(i2c_pro_port) ;开写保护
ei 0x00 ;完成任务后开中断
ret
;******************多字节连续地址读************************
__i2cee_seri_rd:
di ;关闭中断
call i2c_start ;启动总线
ld w,(ee_rw) ;载入C语言传递来的控制字
and w,0xFE ;发送控制字,方向为送出
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_h) ;载入读取位置的高地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_l) ;载入读取位置的低地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld xix,i2c_buffer ;载入缓冲区首地址
ld h,(data_leng_h) ;载入长度计数器高位
ld l,(data_leng_l) ;载入长度计数器低位
call i2c_start ;启动总线
ld w,(ee_rw) ;载入C语言传递来的控制字
or w,0x01 ;发送控制字,方向为读入
call i2c_send ;发送
ld (i2c_error_flag),0x07 ;初始化错误标志,为无应答
call i2c_ack_get ;接收应答信号
i2cee_b_r_loop: ;---I2C EEprom Bytes Read LOOP
call i2c_rec ;接收一个字节
ld (xix+),w ;将收到的数据存在缓冲区
cp hl,0x0001 ;判断,最后一个字节接收后不产生应答脉冲
jp z,i2cee_b_r_fini ;最后一个字节到
call i2c_ack_gen ;发生应答信号
djnz hl,i2cee_b_r_loop ;循环接收
i2cee_b_r_fini: ;---I2C EEprom Byte Read FINIsh
call i2c_nack_gen ;发生非应答信号
call i2c_stop ;停止总线
ei 0x00 ;完成任务后开中断
ret
;******************多字节连续地址写************************
__i2cee_seri_wr:
di ;关闭中断
res i2c_pro_bit,(i2c_pro_port) ;关写保护
call i2c_start ;启动总线
ld w,(ee_rw) ;载入C语言传递来的控制字
and w,0xFE ;发送控制字,方向为送出
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_h) ;载入读取位置的高地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld w,(data_addr_l) ;载入读取位置的低地址
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
ld xix,i2c_buffer ;载入缓冲区首地址
ld xde,0x00
ld e,(data_leng_h)
add xix,xde
ld l,(data_leng_l) ;载入长度计数器低位NOTE3
i2cee_b_w_loop: ;---I2C EEprom Bytes Write LOOP
ld (i2c_error_flag),0x07 ;初始化错误标志,为无应答
ld w,(xix+) ;从缓冲区载入要发送的数据
call i2c_send ;发送
call i2c_ack_get ;接收应答信号
djnz l,i2cee_b_w_loop ;循环发送
call i2c_stop ;停止总线
set i2c_pro_bit,(i2c_pro_port) ;开写保护
ei 0x00 ;完成任务后开中断
ret
;NOTE3:由于页面限制,一次写入的字节总数不会超过64字节.
;**********************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -