📄 wave_generater.asm
字号:
MACK: CLR SDA ;将SDA置0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SETB SCL
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
CLR SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RET
;发送非应答信号
MNACK: SETB SDA ;将SDA置1
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SETB SCL
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
CLR SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RET
;检查应答位子程序
;返回值,ACK=1时表示有应答
CACK: SETB SDA
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SETB SCL
CLR ACK1
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
MOV C,SDA
JC CEND
SETB ACK1 ;判断应答位
CEND: NOP
NOP
NOP
NOP
CLR SCL
NOP
NOP
NOP
NOP
RET
;发送字节子程序
;字节数据放入ACC
;每发送一字节要调用一次CACK子程序,取应答位
WRBYTE: MOV R0,#08H
WLP: RLC A ;取数据位
JC WR1
SJMP WR0 ;判断数据位
WLP1: DJNZ R0,WLP
NOP
NOP
NOP
NOP
RET
WR1: SETB SDA ;发送1
NOP
NOP
NOP
NOP
SETB SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
CLR SCL
SJMP WLP1
WR0: CLR SDA ;发送0
NOP
NOP
NOP
NOP
SETB SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
CLR SCL
SJMP WLP1
;读取字节子程序
;读出的值在ACC
;每取一字节要发送一个应答/非应答信号
RDBYTE: MOV R0,#08H
RLP: SETB SDA
NOP
NOP
NOP
NOP
SETB SCL ;时钟线为高,接收数据位
NOP
NOP
NOP ;+1
NOP ;+1
NOP ;+1
NOP ;+1
NOP ;+1
NOP
MOV C,SDA ;读取数据位
MOV A,R2
CLR SCL ;将SCL拉低,时间大于4.7us
RLC A ;进行数据位的处理
MOV R2,A
NOP
NOP
NOP
NOP ;+1
NOP ;+1
NOP ;+1
NOP ;+1
NOP ;+1
DJNZ R0,RLP ;未够8位,再来一次
RET
;========================================================================================
;========================================================================================
; 以下是用户接口子程序
;
;无子地址器件写字节数据
;入口参数: 数据为ACC、器件从地址SLA
;占用: A、R0、CY
IWRBYTE: PUSH ACC
IWBLOOP: LCALL START ;起动总线
MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
JNB ACK1,RETWRB ;无应答则跳转
POP ACC ;写数据
LCALL WRBYTE
LCALL CACK
LCALL STOP
RET
RETWRB: POP ACC
LCALL STOP
RET
;无子地址器件读字节数据
;入口参数: 器件从地址SLA
;出口参数: 数据为ACC
;占用: A 、R0、R2 、CY
IRDBYTE: LCALL START
MOV A,SLA ;发送器件从地址
INC A
LCALL WRBYTE
LCALL CACK
JNB ACK1,RETRDB
LCALL RDBYTE ;进行读字节操作
LCALL MNACK ;发送非应信号
RETRDB: LCALL STOP ;结束总线
RET
;向器件指定子地址写N字节数据
;入口参数: 器件从地址SLA、器件子地址SUBA 、发送数据缓冲区MTD、发送字节数NUMBYTE
; 占用: A 、R0 、R1 、R3 、CY
IWRNBYTE: MOV A,NUMBYTE
MOV R3,A
LCALL START ;起动总线
MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
JNB ACK,RETWRN ;无应答则退出
MOV A,SUBA ;指定子地址
LCALL WRBYTE
LCALL CACK
MOV R1,#MTD
WRDA: MOV A,@R1
LCALL WRBYTE ;开始写入数据
LCALL CACK
JNB ACK,IWRNBYTE
INC R1
DJNZ R3,WRDA ;判断写完没有
RETWRN: LCALL STOP
RET
;向器件指定子地址读取N字节数据
;入口参数: 器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE
;出口参数: 接收数据缓冲区MTD
;占用:A、 R0、 R1、 R2、 R3、 CY
IRDNBYTE: MOV R3,NUMBYTE
LCALL START
MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
JNB ACK,RETRDN
MOV A,SUBA ;指定子地址
LCALL WRBYTE
LCALL CACK
LCALL START ;重新起动总线
MOV A,SLA
INC A ;准备进行读操作
LCALL WRBYTE
LCALL CACK
JNB ACK,IRDNBYTE
MOV R1,#MRD
RDN1: LCALL RDBYTE ;读操作开始
MOV @R1,A
;NOP ;+1
;NOP ;+1
DJNZ R3,SACK
LCALL MNACK ;最后一字节发非应答位
RETRDN: LCALL STOP ;并结束总线
RET
SACK: LCALL MACK
INC R1
SJMP RDN1
;无子地址器件写N字节数据
;入口参数: 器件从地址SLA、发送数据缓冲区MTD、发送字节数NUMBYTE
; 占用: A 、R0 、R1 、R3 、CY
;不发送子地址SUBA,直接发送多个数据.
IWRNBYTEEXT:
MOV A,NUMBYTE
MOV R3,A
LCALL START ;起动总线
MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
JNB ACK1,RETWRNE ;无应答则退出
MOV R1,#MTD
WRDAE: MOV A,@R1
LCALL WRBYTE ;开始写入数据
LCALL CACK
JNB ACK1,RETWRNE
INC R1
DJNZ R3,WRDAE ;判断写完没有
RETWRNE: LCALL STOP
RET
;无子地址器件读取N字节数据
;入口参数: 器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE
;出口参数: 接收数据缓冲区MTD
;占用:A、 R0、 R1、 R2、 R3、 CY
;说明:此函数不发送子址,也不重新启动总线,而是直接读取多个数据.
IRDNBYTEEXT:
MOV R3,NUMBYTE
LCALL START
MOV A,SLA
INC A
LCALL WRBYTE ;发送器件从地址
LCALL CACK
JNB ACK,RETRDNE
MOV R1,#MRD
RDNE1: LCALL RDBYTE ;读操作开始
MOV @R1,A
DJNZ R3,SACKE
LCALL MNACK ;最后一字节发非应答位
RETRDNE: LCALL STOP ;并结束总线
RET
SACKE: LCALL MACK
INC R1
SJMP RDNE1
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -