📄 i^2c.asm
字号:
SCL EQU P2.1 ;串行时钟线
SDA EQU P2.0 ;串行数据线
ANSW BIT 10H ;应答信号
SEND_BUF EQU 30H ;发送缓冲区
RECV_BUF EQU 40H ;发送缓冲区
IC_ADDR EQU 50H ;器件地址
IC_SUB_ADDR EQU 51H ;器件子地址
BYTE_NUM EQU 52H ;发送字节数
ATMEL24C02 EQU 0A0H
ORG 0000H
AJMP MAIN
ORG 0080H
START: MOV R4,#0F0H
DJNZ R4,$
MOV 60H,#3
;
MAIN:
MOV IC_ADDR,#ATMEL24C02
MOV IC_SUB_ADDR,#30H
MOV BYTE_NUM,#01H
MOV SEND_BUF,#58H
LCALL WR_N_BYTE
MOV IC_SUB_ADDR,#30H
MOV BYTE_NUM,#01H
MOV SEND_BUF,#58H
LCALL RD_N_BYTE
MOV A,RECV_BUF
XRL A,#58H
JZ EXIT1
CLR P2.3
LCALL DELAY
SETB P2.3
SJMP MAIN
EXIT1: CLR P2.3
LCALL DELAY
SETB P2.3
LCALL DELAY
CLR P2.3
LCALL DELAY
SETB P2.3
MOV R0,60H
DEC R0
MOV 60H,R0
CJNE R0,#0,START
SJMP MAIN
;---------------------------------------------
;向器件指定地址发送N个数据
;入口参数:器件地址:IC_ADDR,器件子地址:IC_SUB_ADDR,发送缓冲区:SEND_BUF ,发送字节数:BYTE_NUM
;占用 A R0 R1 R3 CY
WR_N_BYTE:
LCALL DELAY
MOV R3,BYTE_NUM ;发送字节数
LCALL S_START ;启动总线
MOV A,IC_ADDR ;送器件地址
LCALL WR_BYTE ;发送器件地址
LCALL CHK_ANSW
JNB ANSW,WR_EXIT ;无应答,退出
MOV A,IC_SUB_ADDR ;发送器件存储地址
LCALL WR_BYTE
LCALL CHK_ANSW
JNB ANSW,WR_EXIT ;无应答,退出
LCALL DELAY
CPL p1.0
MOV R1,#SEND_BUF ;发送缓冲区地址
WR_DATA: MOV A,@R1
LCALL WR_BYTE ;写数据
LCALL CHK_ANSW
LCALL DELAY
CPL P1.2
JNB ANSW,WR_N_BYTE
INC R1
LCALL DELAY
CPL P1.4
DJNZ R3,WR_DATA ;判断是否发送完
WR_EXIT: LCALL DELAY
CPL p1.6
LCALL S_STOP
CLR P2.3
LCALL DELAY
SETB P2.3
RET
;---------------------------------------------
;向器件指定地址读取N个数据
;入口参数:器件地址:IC_ADDR,器件子地址:IC_SUB_ADDR,接收字节数:BYTE_NUM
;出口参数:接收缓冲区:RECV_BUF
;占用 A R0 R1 R2 R3 CY
RD_N_BYTE: MOV R3,BYTE_NUM
LCALL DELAY
LCALL S_START ;启动总线
MOV A,IC_ADDR
LCALL WR_BYTE ;发送器件地址
LCALL CHK_ANSW
JNB ANSW,RD_EXIT ;无应答,退出
LCALL DELAY
CPL P1.1
MOV A,IC_SUB_ADDR ;发送器件存储地址
LCALL WR_BYTE
LCALL CHK_ANSW
JNB ANSW,RD_EXIT ;无应答,退出
LCALL DELAY
CPL P1.3
LCALL S_START ;重新启动总线
MOV A,IC_ADDR
INC A ;地址加一,变为读地址
LCALL WR_BYTE
LCALL CHK_ANSW
JNB ANSW,RD_EXIT
LCALL DELAY
CPL P1.5
MOV R1,#RECV_BUF ;接收缓冲区地址
MOV A,@R1
RD_DATA: LCALL RD_BYTE ;读操作开始
MOV @R1,A
DJNZ R3,RD_ANSW ;判断是否完
LCALL SEND_NANSW ;最后一个字节发非应答信号
SJMP RD_EXIT
RD_ANSW: LCALL SEND_ANSW ;发送应答信号
INC R1
SJMP RD_DATA
RD_EXIT: LCALL S_STOP ;结束总线
LCALL DELAY
CPL P1.7
RET
WR_BYTE: MOV R0,#8 ;发送一个字节
WR_LOOP: RLC A
JC WR_1
WR_0: CLR SDA ;发送0
NOP
SETB SCL
LCALL NOP_5
CLR SCL
NOP
SJMP WR_LOOP1
WR_1: SETB SDA ;发送1
NOP
SETB SCL
LCALL NOP_5
CLR SCL
NOP
WR_LOOP1: DJNZ R0,WR_LOOP
NOP
RET
RD_BYTE: MOV R0,#8 ;接收一个字节,暂存于R2
RD_LOOP: SETB SDA
NOP
SETB SCL ;时钟线置高,接收数据
NOP
NOP
MOV C,SDA ;读取数据
MOV A,R2
CLR SCL ;拉低时钟线
RLC A
MOV R2,A
NOP
NOP
NOP
DJNZ R0,RD_LOOP
RET
S_START: SETB SDA ;启动总线
NOP
SETB SCL
LCALL NOP_5
CLR SDA
LCALL NOP_5
CLR SCL ;钳住总线,准备发送
NOP
RET
S_STOP: CLR SDA ;结束总线
NOP
SETB SCL
LCALL NOP_5
SETB SDA
LCALL NOP_5
RET
SEND_ANSW: CLR SDA ;应答信号
NOP
NOP
SETB SCL
LCALL NOP_5
CLR SCL
NOP
RET
SEND_NANSW: SETB SDA ;非应答信号
NOP
NOP
SETB SCL
LCALL NOP_5
CLR SCL
NOP
RET
CHK_ANSW: SETB SDA ;检查应答信号
CLR ANSW
MOV R0,#3
SETB SCL
CHKLOOP: MOV C,SDA
JNC CHK1
DJNZ R0,CHKLOOP
SJMP CHK_OVER
CHK1: SETB ANSW
CHK_OVER: NOP
CLR SCL
RET
NOP_5: NOP
NOP
NOP
NOP
RET
DELAY: MOV R7,#10
DL1: MOV R6,#200
DL2: MOV R5,#250
DL3: DJNZ R5,DL3
DJNZ R6,DL2
DJNZ R7,DL1
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -