📄 hi2c_asm.inc
字号:
; P89LPC932硬件I2C软件包(主)
;
; 1 使用I2C总线软件包时P1.2,P1.3切勿写为0,并要设置为开漏输出。
; 2 总线定义为P1.2=SCL,P1.3=SDA,需外接上拉电阻2-10k。
; 3 相应寄存器:
; 地址寄存器 I2ADR 用于存放自身从地址(从方式时才有用)
; 数据寄存器 I2DAT 接收/发送数据用
; 控制寄存器 I2CON 用于硬件I2C的设置、使能、启动、结束,
; 应答控制,中断标志等。
; 状态寄存器 I2STAT 指示I2C总线的操作状态码,高5位有效,
; 若I2C中断志置位,可查询此寄存器判断
; 总线情况。
; SCL占空比寄存器 I2SCLH、I2SCLL 设置SCL的频率发生。
;
; 此软件包是以查询方式完成各种总线操作的,在使用前应对总线进行检查,并
;使用看门狗,以防等待总线而造成死机。
; 更新时间:2002.11.05
;
;申请总线
;功能:进行I2C总线的初始化--包括时钟选择,I2C使能,发送起始信号等等。
; I2EN为1,设置为主机;CRSEL位为0,使用内部SCL发生器。
GETBUS:
MOV I2SCLH,#15 ;设置SCL高电平的PCLK周期数
MOV I2SCLL,#15 ;设置SCL低电平的PCLK周期数,6MHz时为100Kbit/S
MOV I2CON,#64H ;使用内部SCL发生器,I2EN和AA置位,起动总线
JNB SI,$ ;等待起始信号的发送
RET
;发送数据函数
;功能:用于向总线发送数据
;入口参数:ACC 待发送的数据
SENDBYTE:
MOV I2DAT,A ;发送数据
MOV I2CON,#44H ;清除SI位等等
JNB SI,$ ;等待数据的发送
RET
;===================================================================================
; 用户接口子程序
;进行无子地址写单字节
;入口参数:ACC,SLA
;出口参数:ACK为1时表明操作正确
;R7
IWRBYTE:
CLR ACK
ACALL GETBUS ;启动总线
; PUSH ACC ;先保护待发送的数据
MOV R7,A
MOV A,SLA ;器件寻址
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#18H,IWRBEND ;发送器件地址,若无应答则退出操作(18H是总线状态码)
; POP ACC
MOV A,R7
ACALL SENDBYTE ;发送数据
MOV A,I2STAT
CJNE A,#28H,IWRBEND
SETB ACK ;设置出口标志位
IWRBEND:MOV I2CON,#54H ;结束总线
RET
;进行随机地址多字节写
;入口参数:器件从地址SLA 子地址SUBA 发送数据区MTD 写入字节数NUMBYTE
;出口参数:ACK 为1时操作正确。
;占用R0,R1,ACC
IWRNBYTE:
CLR ACK
MOV R0,#MTD
MOV R1,NUMBYTE
ACALL GETBUS ;启动总线
MOV A,SLA
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#18H,IWRNEND
MOV A,SUBA
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#28H,IWRNEND ;无应答则退出
IWRN_L1:MOV A,@R0
ACALL SENDBYTE ;发送数据
MOV A,I2STAT
CJNE A,#28H,IWRNEND ;无应答则退出
INC R0
DJNZ R1,IWRN_L1
SETB ACK ;置标志位
IWRNEND:MOV I2CON,#54H
RET
;进行无子地址多字节写
;入口参数:器件从地址SLA 发送数据区MTD 读入字节数NUMBYTE
;出口参数:ACK 为1时操作正确。
;占用R0,R1,ACC
IWRNBYTEEXT:
CLR ACK
MOV R0,#MTD
MOV R1,NUMBYTE
ACALL GETBUS ;启动总线
MOV A,SLA
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#18H,IWRNEEND
IWRNE_L1:MOV A,@R0
ACALL SENDBYTE ;发送数据
MOV A,I2STAT
CJNE A,#28H,IWRNEEND ;无应答则退出
INC R0
DJNZ R1,IWRNE_L1
SETB ACK ;置标志位
IWRNEEND:MOV I2CON,#54H
RET
;进行立即地址单字节读
;出口参数:读出值在ACC
;出口参数:ACK 为1时操作正确。
;注:SLA要为写的地址,因为此子程序会自动加1
IRDBYTE:
CLR ACK
ACALL GETBUS
MOV A,SLA
INC A ;读操作的器件寻址
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#40H,IRDBEND
MOV I2CON,#40H ;接收一字节数据即发送非应答位
JNB SI,$ ;等待接收数据
MOV A,I2STAT
CJNE A,#58H,IRDBEND
MOV A,I2DAT ;读取数据
SETB ACK
IRDBEND:MOV I2CON,#54H
RET
;进行随机地址多字节读
;入口参数:器件从地址SLA 子地址SUBA 接收数据区MRD 读入字节数NUMBYTE
;出口参数:ACK 为1时操作正确。
;占用R0,R1,ACC
IRDNBYTE:
CLR ACK
MOV R0,#MRD
MOV R1,NUMBYTE
ACALL GETBUS
MOV A,SLA
ACALL SENDBYTE ;器件寻址
MOV A,I2STAT
CJNE A,#18H,IRDNEND ;无器件应答即退出
MOV A,SUBA ;写入器件子地址
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#28H,IRDNEND ;总线出错即退出
MOV I2CON,#64H ;重新启动总线
JNB SI,$
MOV A,SLA
INC A ;读操作的器件寻址
ACALL SENDBYTE
MOV A,I2STAT
CJNE A,#40H,IRDNEND
IRDN_L1: DJNZ R1,IRDN_L2
MOV I2CON,#40H ;取最后一个数据后发送非应答位
JNB SI,$
MOV A,I2STAT
CJNE A,#58H,IRDNEND
MOV A,I2DAT ;将数据取出
MOV @R0,A ;数据存入MRD区中(R0指针指向MRD区)
SETB ACK
IRDNEND: MOV I2CON,#54H
RET
IRDN_L2: MOV I2CON,#44H ;接收数据并发送应答位
JNB SI,$
MOV A,I2STAT
CJNE A,#50H,IRDNEND ;总线出错即退出
MOV A,I2DAT ;取数据
MOV @R0,A ;数据存入MRD区
INC R0
SJMP IRDN_L1
;进行无子地址多字节读
;入口参数:器件从地址SLA 接收数据区MRD 读入字节数NUMBYTE
;出口参数:ACK 为1时操作正确。
;占用R0,R1,ACC
IRDNBYTEEXT:
CLR ACK
MOV R0,#MRD
MOV R1,NUMBYTE
ACALL GETBUS
MOV A,SLA
INC A
ACALL SENDBYTE ;器件寻址
MOV A,I2STAT
CJNE A,#40H,IRDNEEND
IRDNE_L1:DJNZ R1,IRDNE_L2
MOV I2CON,#40H ;取最后一个数据后发送非应答位
JNB SI,$
MOV A,I2STAT
CJNE A,#58H,IRDNEEND
MOV A,I2DAT
MOV @R0,A ;数据存入MRD区中(R0指针指向MRD区)
SETB ACK
IRDNEEND:MOV I2CON,#54H
RET
IRDNE_L2:MOV I2CON,#44H ;接收数据并发送应答位
JNB SI,$
MOV A,I2STAT
CJNE A,#50H,IRDNEEND ;总线出错即退出
MOV A,I2DAT ;取数据
MOV @R0,A ;数据存入MRD区
INC R0
SJMP IRDNE_L1
;使用前须在你的程序里要做以下定义:
;定义变量: SLA 器件从地址 SUBA器件子地址 NUMBYTE读/写的字节数 ,位变量ACK
;定义常量: MTD 发送数据缓冲区首址 MRD 接收数据缓冲区首址
;
;定义LPC932的I2C相关寄存器的定义
;I2ADR DATA 0DBH
;I2DAT DATA 0DAH
;I2CON DATA 0D8H
;I2STAT DATA 0D9H
;I2SCLH DATA 0DDH
;I2SCLL DATA 0DCH
;STA BIT I2CON.5
;SI BIT I2CON.3
;
;软件包接口
;(1)IRDBYTE 立即地址读单字节子程序
; 入口:器件从地址SLA
; 出口:读出数据ACC,应答位ACK。
; 占用资源:ACC,CY
;
;(2)IRDNBYTE 随机地址读多字节子程序
; 入口:器件从地址SLA,器件子地址SUBA,读出字节数NUMBYTE
; 出口:读出数据依次放在MRD区,应答位ACK。
; 占用资源:R0,R1,ACC,CY
;
;(3)IWRBYTE 立即地址写单字节子程序
; 入口: 器件从地址SLA,写入的数据ACC
; 出口: 应答位ACK。
; 占用资源:ACC,CY,一字节堆栈
;
;(4)IWRNBYTE 立即地址写多字节子程序
; 入口: 器件从地址SLA,写入的数据依次放在MTD区
; 出口: 应答位ACK。
; 占用资源:R0,R1,ACC,CY
;(ACK为调试/测试位,ACK为0时表示无器件应答或总线出错)
;
;(5)IWRNBYTEEXT 进行无子地址多字节写
; 入口:器件从地址SLA 发送数据区MTD 读入字节数NUMBYTE
; 出口:ACK 为1时操作正确。
; 占用资源:R0,R1,ACC
;
;(6)IRDNBYTEEXT 进行无子地址多字节读
; 入口:器件从地址SLA 接收数据区MRD 读入字节数NUMBYTE
; 出口:ACK 为1时操作正确。
; 占用资源:R0,R1,ACC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -