求解51单片机I2C对24c02读写汇编程序
电路如图所示,图中高亮SDL实际为SCL时钟,SCL接51单片机p2.1口,SDA姐51单片机p2.0口,VCC为5V求一个能实现对24c02任意一个地址写入一个数据,再...
电路如图所示,图中高亮SDL实际为SCL时钟,SCL接51单片机p2.1口,SDA姐51单片机p2.0口,VCC为5V
求一个能实现对24c02任意一个地址写入一个数据,再把这个数据从24c02里面读出来并把读出来的数据传送给P1口,因为P1口节的是led灯,要求用汇编写
如下是我自己写的汇编程序,发现怎么也成功不了,求高人指点迷津,给一个能够通过测试的读写24c02程序
org 0000h
ljmp main
start:
setb sda
setb scl
lcall delay
clr sda
lcall delay
clr scl
ret
waitack:
clr scl
setb sda
lcall delay
setb scl
lcall delay
mov c,sda
jc waitack
clr sda
clr scl
ret
stop:
clr sda
setb scl
lcall delay
setb sda
lcall delay
clr scl
clr sda
ret
write_data:
mov r0,#00h
mov b,a
lcall write_byte
ret
write_byte:
lcall start
mov a,#0a0h
lcall sendbyte
lcall waitack
mov a,r0
lcall sendbyte
lcall waitack
mov a,b
lcall sendbyte
lcall waitack
lcall stop
ret
sendbyte:
mov r7,#08h
s_byte:
rlc a
mov sda,c
setb scl
lcall delay
clr scl
djnz r7,s_byte
ret
read_data:
mov r0,#00h
lcall read_byte
call stop
mov temp,a
ret
read_byte:
call start
mov a,#0a0h
lcall sendbyte
lcall waitack
mov a,r0
lcall sendbyte
lcall waitack
lcall start
mov a,#0a1h
lcall sendbyte
lcall waitack
lcall rcvbyte
ret
rcvbyte:
mov r7,#08h
clr a
setb sda
r_byte:
clr scl
lcall delay
setb scl
lcall delay
mov c,sda
rlc a
setb sda
djnz r7,r_byte
ret
delay:
nop
nop
ret
main:
scl bit p2.1
sda bit p2.0
temp equ 30h
mov sp,#60h
mov p1,#0ffh
mov b,0aah;
lcall write_data
lcall read_data
mov p1,a
end 展开
求一个能实现对24c02任意一个地址写入一个数据,再把这个数据从24c02里面读出来并把读出来的数据传送给P1口,因为P1口节的是led灯,要求用汇编写
如下是我自己写的汇编程序,发现怎么也成功不了,求高人指点迷津,给一个能够通过测试的读写24c02程序
org 0000h
ljmp main
start:
setb sda
setb scl
lcall delay
clr sda
lcall delay
clr scl
ret
waitack:
clr scl
setb sda
lcall delay
setb scl
lcall delay
mov c,sda
jc waitack
clr sda
clr scl
ret
stop:
clr sda
setb scl
lcall delay
setb sda
lcall delay
clr scl
clr sda
ret
write_data:
mov r0,#00h
mov b,a
lcall write_byte
ret
write_byte:
lcall start
mov a,#0a0h
lcall sendbyte
lcall waitack
mov a,r0
lcall sendbyte
lcall waitack
mov a,b
lcall sendbyte
lcall waitack
lcall stop
ret
sendbyte:
mov r7,#08h
s_byte:
rlc a
mov sda,c
setb scl
lcall delay
clr scl
djnz r7,s_byte
ret
read_data:
mov r0,#00h
lcall read_byte
call stop
mov temp,a
ret
read_byte:
call start
mov a,#0a0h
lcall sendbyte
lcall waitack
mov a,r0
lcall sendbyte
lcall waitack
lcall start
mov a,#0a1h
lcall sendbyte
lcall waitack
lcall rcvbyte
ret
rcvbyte:
mov r7,#08h
clr a
setb sda
r_byte:
clr scl
lcall delay
setb scl
lcall delay
mov c,sda
rlc a
setb sda
djnz r7,r_byte
ret
delay:
nop
nop
ret
main:
scl bit p2.1
sda bit p2.0
temp equ 30h
mov sp,#60h
mov p1,#0ffh
mov b,0aah;
lcall write_data
lcall read_data
mov p1,a
end 展开
3个回答
展开全部
;**************************************
;AT24C04测试程序 供参考
;工作频率: 12.000MHz
;**************************************
SCL BIT P2.0 ;AT24C04的时钟线
SDA BIT P2.1 ;AT24C04的数据线
BUF EQU 30H ;数据缓存区
;**************************************
ORG 0
JMP Reset
ORG 100H
Reset:
CALL AT24C04_WritePage ;写一页数据
CALL Delay5ms ;写一页数据需延时5ms
CALL AT24C04_ReadPage ;读一页数据
JMP $
;**************************************
;向AT24C04写1页(16字节)数据
;将TESTDATA开始的16个测试数据写如设备的00~0F地址中
;入口参数:无
;出口参数:无
;**************************************
AT24C04_WritePage:
CALL AT24C04_Start ;起始信号
MOV A,#0A0H ;发送设备地址+写信号
CALL AT24C04_SendByte ;发送
MOV A,#00H ;发送存储单元地址
CALL AT24C04_SendByte ;发送
MOV R0,#16 ;16字节计数器
MOV DPTR,#TESTDATA ;测试数据首地址
WriteNext:
CLR A ;读取测试数据
MOVC A,@A+DPTR
CALL AT24C04_SendByte ;写入设备
INC DPTR ;准备下一个数据的地址
DJNZ R0,WriteNext ;判断16字节是否完成
CALL AT24C04_Stop ;停止信号
RET
TESTDATA:
DB 000H,011H,022H,033H,044H,055H,066H,077H
DB 088H,099H,0AAH,0BBH,0CCH,0DDH,0EEH,0FFH
;**************************************
;从AT24C04读取1页(16字节)数据
;将设备的00~0F地址中的数据读出存放在DATA区的BUF中
;入口参数:无
;出口参数:无
;**************************************
AT24C04_ReadPage:
CALL AT24C04_Start ;起始信号
MOV A,#0A0H ;发送设备地址+写信号
CALL AT24C04_SendByte ;发送
MOV A,#00H ;发送存储单元地址
CALL AT24C04_SendByte ;发送
CALL AT24C04_Start ;起始信号
MOV A,#0A1H ;发送设备地址+读信号
CALL AT24C04_SendByte ;发送
MOV R0,#16 ;16字节计数器
MOV R1,#BUF ;数据缓冲区首地址
ReadNext:
CALL AT24C04_RecvByte ;读取数据
MOV @R1,A ;保存数据
CJNE R0,#2,$+3 ;判断回应ACK还是NAK
CALL AT24C04_SendACK ;发送应答信号
INC R1 ;缓冲区地址加1
DJNZ R0,ReadNext ;判断16字节是否完成
CALL AT24C04_Stop ;停止信号
RET
;**************************************
;延时5微秒
;不同的工作环境,需要调整此函数
;入口参数:无
;出口参数:无
;**************************************
Delay5us: ;2 当改用1T的MCU时,请调整此延时函数
NOP ;1
RET ;2
;**************************************
;延时5毫秒
;不同的工作环境,需要调整此函数
;入口参数:无
;出口参数:无
;**************************************
Delay5ms: ;2 当改用1T的MCU时,请调整此延时函数
PUSH ACC ;2
PUSH DPL ;2
PUSH DPH ;2
MOV DPTR,#-500 ;2
Delay5ms1:
NOP ;1
NOP ;1
NOP ;1
NOP ;1
INC DPTR ;2
MOV A,DPL ;1
ORL A,DPH ;1
JNZ Delay5ms1 ;2
POP DPH ;2
POP DPL ;2
POP ACC ;2
RET ;2
;**************************************
;起始信号
;入口参数:无
;出口参数:无
;**************************************
AT24C04_Start:
SETB SDA
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
CLR SDA ;产生下降沿
CALL Delay5us ;延时
CLR SCL ;拉低时钟线
RET
;**************************************
;停止信号
;入口参数:无
;出口参数:无
;**************************************
AT24C04_Stop:
CLR SDA
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
SETB SDA ;产生上升沿
CALL Delay5us ;延时
RET
;**************************************
;发送应答信号
;入口参数:C (0:ACK 1:NAK)
;出口参数:无
;**************************************
AT24C04_SendACK:
MOV SDA,C ;写应答信号
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
RET
;**************************************
;接收应答信号
;入口参数:无
;出口参数:C
;**************************************
AT24C04_RecvACK:
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
MOV C,SDA ;读应答信号
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
RET
;**************************************
;向IIC总线发送一个字节数据
;入口参数:ACC
;出口参数:无
;**************************************
AT24C04_SendByte:
PUSH 0
MOV 0,#8 ;8位计数器
SendNext:
RLC A ;移出数据的最高位
MOV SDA,C ;送数据口
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
DJNZ 0,SendNext ;判断8位数据是否发送完成
POP 0
JMP AT24C04_RecvACK ;接收应答信号
; RET
;**************************************
;从IIC总线接收一个字节数据
;入口参数:无
;出口参数:ACC
;**************************************
AT24C04_RecvByte:
SETB SDA ;使能内部上拉,准备读取数据
PUSH 0
MOV 0,#8 ;8位计数器
RecvNext:
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
MOV C,SDA ;读数据口
RLC A ;保存数据
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
DJNZ 0,RecvNext ;判断8位数据是否接收完成
POP 0
RET
;**************************************
END
;AT24C04测试程序 供参考
;工作频率: 12.000MHz
;**************************************
SCL BIT P2.0 ;AT24C04的时钟线
SDA BIT P2.1 ;AT24C04的数据线
BUF EQU 30H ;数据缓存区
;**************************************
ORG 0
JMP Reset
ORG 100H
Reset:
CALL AT24C04_WritePage ;写一页数据
CALL Delay5ms ;写一页数据需延时5ms
CALL AT24C04_ReadPage ;读一页数据
JMP $
;**************************************
;向AT24C04写1页(16字节)数据
;将TESTDATA开始的16个测试数据写如设备的00~0F地址中
;入口参数:无
;出口参数:无
;**************************************
AT24C04_WritePage:
CALL AT24C04_Start ;起始信号
MOV A,#0A0H ;发送设备地址+写信号
CALL AT24C04_SendByte ;发送
MOV A,#00H ;发送存储单元地址
CALL AT24C04_SendByte ;发送
MOV R0,#16 ;16字节计数器
MOV DPTR,#TESTDATA ;测试数据首地址
WriteNext:
CLR A ;读取测试数据
MOVC A,@A+DPTR
CALL AT24C04_SendByte ;写入设备
INC DPTR ;准备下一个数据的地址
DJNZ R0,WriteNext ;判断16字节是否完成
CALL AT24C04_Stop ;停止信号
RET
TESTDATA:
DB 000H,011H,022H,033H,044H,055H,066H,077H
DB 088H,099H,0AAH,0BBH,0CCH,0DDH,0EEH,0FFH
;**************************************
;从AT24C04读取1页(16字节)数据
;将设备的00~0F地址中的数据读出存放在DATA区的BUF中
;入口参数:无
;出口参数:无
;**************************************
AT24C04_ReadPage:
CALL AT24C04_Start ;起始信号
MOV A,#0A0H ;发送设备地址+写信号
CALL AT24C04_SendByte ;发送
MOV A,#00H ;发送存储单元地址
CALL AT24C04_SendByte ;发送
CALL AT24C04_Start ;起始信号
MOV A,#0A1H ;发送设备地址+读信号
CALL AT24C04_SendByte ;发送
MOV R0,#16 ;16字节计数器
MOV R1,#BUF ;数据缓冲区首地址
ReadNext:
CALL AT24C04_RecvByte ;读取数据
MOV @R1,A ;保存数据
CJNE R0,#2,$+3 ;判断回应ACK还是NAK
CALL AT24C04_SendACK ;发送应答信号
INC R1 ;缓冲区地址加1
DJNZ R0,ReadNext ;判断16字节是否完成
CALL AT24C04_Stop ;停止信号
RET
;**************************************
;延时5微秒
;不同的工作环境,需要调整此函数
;入口参数:无
;出口参数:无
;**************************************
Delay5us: ;2 当改用1T的MCU时,请调整此延时函数
NOP ;1
RET ;2
;**************************************
;延时5毫秒
;不同的工作环境,需要调整此函数
;入口参数:无
;出口参数:无
;**************************************
Delay5ms: ;2 当改用1T的MCU时,请调整此延时函数
PUSH ACC ;2
PUSH DPL ;2
PUSH DPH ;2
MOV DPTR,#-500 ;2
Delay5ms1:
NOP ;1
NOP ;1
NOP ;1
NOP ;1
INC DPTR ;2
MOV A,DPL ;1
ORL A,DPH ;1
JNZ Delay5ms1 ;2
POP DPH ;2
POP DPL ;2
POP ACC ;2
RET ;2
;**************************************
;起始信号
;入口参数:无
;出口参数:无
;**************************************
AT24C04_Start:
SETB SDA
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
CLR SDA ;产生下降沿
CALL Delay5us ;延时
CLR SCL ;拉低时钟线
RET
;**************************************
;停止信号
;入口参数:无
;出口参数:无
;**************************************
AT24C04_Stop:
CLR SDA
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
SETB SDA ;产生上升沿
CALL Delay5us ;延时
RET
;**************************************
;发送应答信号
;入口参数:C (0:ACK 1:NAK)
;出口参数:无
;**************************************
AT24C04_SendACK:
MOV SDA,C ;写应答信号
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
RET
;**************************************
;接收应答信号
;入口参数:无
;出口参数:C
;**************************************
AT24C04_RecvACK:
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
MOV C,SDA ;读应答信号
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
RET
;**************************************
;向IIC总线发送一个字节数据
;入口参数:ACC
;出口参数:无
;**************************************
AT24C04_SendByte:
PUSH 0
MOV 0,#8 ;8位计数器
SendNext:
RLC A ;移出数据的最高位
MOV SDA,C ;送数据口
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
DJNZ 0,SendNext ;判断8位数据是否发送完成
POP 0
JMP AT24C04_RecvACK ;接收应答信号
; RET
;**************************************
;从IIC总线接收一个字节数据
;入口参数:无
;出口参数:ACC
;**************************************
AT24C04_RecvByte:
SETB SDA ;使能内部上拉,准备读取数据
PUSH 0
MOV 0,#8 ;8位计数器
RecvNext:
SETB SCL ;拉高时钟线
CALL Delay5us ;延时
MOV C,SDA ;读数据口
RLC A ;保存数据
CLR SCL ;拉低时钟线
CALL Delay5us ;延时
DJNZ 0,RecvNext ;判断8位数据是否接收完成
POP 0
RET
;**************************************
END
意法半导体(中国)投资有限公司
2023-06-12 广告
2023-06-12 广告
STM32F103是一款高性能的嵌入式芯片,由意法半导体(STMicroelectronics)公司生产。它是STM32系列芯片之一,具有紧凑、低功耗、高性能等特点,被广泛应用于嵌入式系统中。STM32F103的主要特点包括:1. 集成了A...
点击进入详情页
本回答由意法半导体(中国)投资有限公司提供
展开全部
ORG 0000H
LJMP MAIN
SCL BIT P2.1
SDA BIT P2.0
TEMP EQU 30H
BYTE_ADDR EQU 31H
;---------------I2C通讯程序----------------
;------------------------------------------
;---------------读取I2C数据----------------
;读取一个字节
;输入:BYTE_ADDR,读取字节地址
;输出:A
;------------------------------------------
I2CREAD:
LCALL I2C_START ;起始
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送芯片地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
LCALL I2C_START ;起始
MOV A,#0A1H
LCALL I2C_TXBYTE ;发送地址数据+读信号
LCALL I2C_RXACK ;接收ACK
LCALL I2C_RXBYTE ;接收数据
SETB C ;读一个字节C=1
LCALL I2C_TXACK ;发送NAK
LCALL I2C_STOP ;读取完成
RET
;----------------------------
;R4=读出字节数
;BYTE_ADDR=读出初始地址
;R1=数据指针
;----------------------------
I2C_PAGE_RD:
LCALL I2C_START ;起始
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送芯片地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
LCALL I2C_START ;起始
MOV A,#0A1H
LCALL I2C_TXBYTE ;发送地址数据+读信号
LCALL I2C_RXACK ;接收ACK
NXT_BYTE:
LCALL I2C_RXBYTE ;接收数据
MOV @R1,A
INC R1
CLR C ;连续读C=0
LCALL I2C_TXACK ;发送NAK
LCALL I2C_DELAY
DJNZ R4,NXT_BYTE
LCALL I2C_NOACK ;NOACK
LCALL I2C_STOP ;读取完成
RET
;----------------写一字节I2C数据------------
;写入一个字节
;输入:BYTE_ADDR,写入字节地址;A=写入数据
;输出:无
;------------------------------------------
I2CWRITE:
PUSH ACC
LCALL I2C_START ;开始写
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
POP ACC
LCALL I2C_TXBYTE ;写数据
LCALL I2C_RXACK ;接收ACK
LCALL I2C_STOP ;写完成
LCALL I2C_DLYMS ;延时1ms
RET
;----------------------------
;R4=写入字节数
;BYTE_ADDR=写入初始地址
;R1=数据指针
;----------------------------
I2C_PAGE_WR:
LCALL I2C_START ;开始写
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
NEXT_DATA: ;WRITE 16 BYTES TO
MOV A,@R1 ;EEPROM
LCALL I2C_TXBYTE ;写数据
LCALL I2C_RXACK ;接收ACK
INC R1
DJNZ R4,NEXT_DATA
LCALL I2C_STOP ;写完成
LCALL I2C_DLYMS ;延时1ms
RET
;----------------------------
;发送I2C起始信号
;----------------------------
I2C_START:
SETB SCL ;时钟高电平时数据下降沿为启动信号
LCALL I2C_DELAY
SETB SDA
LCALL I2C_DELAY
CLR SDA ;数据线下降沿
LCALL I2C_DELAY ;延时
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
RET
;----------------------------
;发送I2C停止信号
;----------------------------
I2C_STOP:
CLR SDA
LCALL I2C_DELAY ;延时
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
SETB SDA ;数据线上升沿
LCALL I2C_DELAY ;延时
CLR SCL
RET
;----------------------------
;发送ACK/NAK信号
;----------------------------
I2C_TXACK:
MOV SDA,C ;送ACK数据
LCALL I2C_DELAY ;延时
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
SETB SDA ;发送完成
RET
;----------------------------
;接收ACK/NAK信号
;----------------------------
I2C_RXACK:
SETB SDA ;准备读数据
LCALL I2C_DELAY ;延时
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
MOV C,SDA ;读取ACK信号
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
RET
;----------------------------
I2C_NOACK:
SETB SDA ;NO ACKNOWLEDGE
LCALL I2C_DELAY
SETB SCL
LCALL I2C_DELAY
CLR SCL
LCALL I2C_DELAY
RET
;----------------------------
;发送一字节数据
;----------------------------
I2C_TXBYTE:
MOV R7,#8 ;8位计数
TXNEXT:
RLC A ;移出数据位
MOV SDA,C ;数据送数据口
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
DJNZ R7,TXNEXT ;送下一位
RET
;----------------------------
;接收一字节数据
;----------------------------
I2C_RXBYTE:
MOV R7,#8 ;8位计数
RXNEXT:
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
MOV C,SDA
RLC A
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
DJNZ R7,RXNEXT ;收下一位
RET
;----------------------------
I2C_DELAY: ;
NOP
NOP
RET ;
;----------------------------
I2C_DLYMS:
PUSH 0
PUSH 1
MOV R1,#2
I2CDL:
MOV R0,#248
DJNZ R0,$
DJNZ R1,I2CDL
POP 1
POP 0
RET
;----------------------------
MAIN:
MOV SP,#60H
MOV A,#0AAH
MOV BYTE_ADDR,#0
LCALL I2CWRITE
LCALL I2CREAD
MOV P1,A
SJMP $
END
;----------------------------
LJMP MAIN
SCL BIT P2.1
SDA BIT P2.0
TEMP EQU 30H
BYTE_ADDR EQU 31H
;---------------I2C通讯程序----------------
;------------------------------------------
;---------------读取I2C数据----------------
;读取一个字节
;输入:BYTE_ADDR,读取字节地址
;输出:A
;------------------------------------------
I2CREAD:
LCALL I2C_START ;起始
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送芯片地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
LCALL I2C_START ;起始
MOV A,#0A1H
LCALL I2C_TXBYTE ;发送地址数据+读信号
LCALL I2C_RXACK ;接收ACK
LCALL I2C_RXBYTE ;接收数据
SETB C ;读一个字节C=1
LCALL I2C_TXACK ;发送NAK
LCALL I2C_STOP ;读取完成
RET
;----------------------------
;R4=读出字节数
;BYTE_ADDR=读出初始地址
;R1=数据指针
;----------------------------
I2C_PAGE_RD:
LCALL I2C_START ;起始
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送芯片地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
LCALL I2C_START ;起始
MOV A,#0A1H
LCALL I2C_TXBYTE ;发送地址数据+读信号
LCALL I2C_RXACK ;接收ACK
NXT_BYTE:
LCALL I2C_RXBYTE ;接收数据
MOV @R1,A
INC R1
CLR C ;连续读C=0
LCALL I2C_TXACK ;发送NAK
LCALL I2C_DELAY
DJNZ R4,NXT_BYTE
LCALL I2C_NOACK ;NOACK
LCALL I2C_STOP ;读取完成
RET
;----------------写一字节I2C数据------------
;写入一个字节
;输入:BYTE_ADDR,写入字节地址;A=写入数据
;输出:无
;------------------------------------------
I2CWRITE:
PUSH ACC
LCALL I2C_START ;开始写
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
POP ACC
LCALL I2C_TXBYTE ;写数据
LCALL I2C_RXACK ;接收ACK
LCALL I2C_STOP ;写完成
LCALL I2C_DLYMS ;延时1ms
RET
;----------------------------
;R4=写入字节数
;BYTE_ADDR=写入初始地址
;R1=数据指针
;----------------------------
I2C_PAGE_WR:
LCALL I2C_START ;开始写
MOV A,#0A0H
LCALL I2C_TXBYTE ;发送地址数据+写信号
LCALL I2C_RXACK ;接收ACK
MOV A,BYTE_ADDR
LCALL I2C_TXBYTE ;发送RAM地址数据
LCALL I2C_RXACK ;接收ACK
NEXT_DATA: ;WRITE 16 BYTES TO
MOV A,@R1 ;EEPROM
LCALL I2C_TXBYTE ;写数据
LCALL I2C_RXACK ;接收ACK
INC R1
DJNZ R4,NEXT_DATA
LCALL I2C_STOP ;写完成
LCALL I2C_DLYMS ;延时1ms
RET
;----------------------------
;发送I2C起始信号
;----------------------------
I2C_START:
SETB SCL ;时钟高电平时数据下降沿为启动信号
LCALL I2C_DELAY
SETB SDA
LCALL I2C_DELAY
CLR SDA ;数据线下降沿
LCALL I2C_DELAY ;延时
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
RET
;----------------------------
;发送I2C停止信号
;----------------------------
I2C_STOP:
CLR SDA
LCALL I2C_DELAY ;延时
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
SETB SDA ;数据线上升沿
LCALL I2C_DELAY ;延时
CLR SCL
RET
;----------------------------
;发送ACK/NAK信号
;----------------------------
I2C_TXACK:
MOV SDA,C ;送ACK数据
LCALL I2C_DELAY ;延时
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
SETB SDA ;发送完成
RET
;----------------------------
;接收ACK/NAK信号
;----------------------------
I2C_RXACK:
SETB SDA ;准备读数据
LCALL I2C_DELAY ;延时
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
MOV C,SDA ;读取ACK信号
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
RET
;----------------------------
I2C_NOACK:
SETB SDA ;NO ACKNOWLEDGE
LCALL I2C_DELAY
SETB SCL
LCALL I2C_DELAY
CLR SCL
LCALL I2C_DELAY
RET
;----------------------------
;发送一字节数据
;----------------------------
I2C_TXBYTE:
MOV R7,#8 ;8位计数
TXNEXT:
RLC A ;移出数据位
MOV SDA,C ;数据送数据口
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
DJNZ R7,TXNEXT ;送下一位
RET
;----------------------------
;接收一字节数据
;----------------------------
I2C_RXBYTE:
MOV R7,#8 ;8位计数
RXNEXT:
SETB SCL ;时钟->高
LCALL I2C_DELAY ;延时
MOV C,SDA
RLC A
CLR SCL ;时钟->低
LCALL I2C_DELAY ;延时
DJNZ R7,RXNEXT ;收下一位
RET
;----------------------------
I2C_DELAY: ;
NOP
NOP
RET ;
;----------------------------
I2C_DLYMS:
PUSH 0
PUSH 1
MOV R1,#2
I2CDL:
MOV R0,#248
DJNZ R0,$
DJNZ R1,I2CDL
POP 1
POP 0
RET
;----------------------------
MAIN:
MOV SP,#60H
MOV A,#0AAH
MOV BYTE_ADDR,#0
LCALL I2CWRITE
LCALL I2CREAD
MOV P1,A
SJMP $
END
;----------------------------
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
我们也用这个2402,但如果我发我们的这个软件给你,估计你也要看好久,
我大概看了你的软件,看起来好像没有什么问题,但有几个地方,我想你看一下,
DELAY 子程式,你用两个NOP,NOP ,这个DELAY 到底是多长时间?不知道你用的单片机是什么型号,但我想两个NOP ,估计也就是1US 的时间,可能还没有到1US ,DATASHEET 要求CLK ,low pulse 估计要2US 以上的吧,所以你先把这个DELAY 加长,起码DATASHEET 要求2US ,你加到5US 去看看如何,然后还有一个问题就是WAITACK 那,如果一直读不到ACK ,那你也要有个时间跳出去,是10MS ,还是多少,DATASHEET 好像写的最大时间是5MS的了吧!
如果还不行,你用示波器来对你发的东西的波形到底和你写的是不是一样。
我大概看了你的软件,看起来好像没有什么问题,但有几个地方,我想你看一下,
DELAY 子程式,你用两个NOP,NOP ,这个DELAY 到底是多长时间?不知道你用的单片机是什么型号,但我想两个NOP ,估计也就是1US 的时间,可能还没有到1US ,DATASHEET 要求CLK ,low pulse 估计要2US 以上的吧,所以你先把这个DELAY 加长,起码DATASHEET 要求2US ,你加到5US 去看看如何,然后还有一个问题就是WAITACK 那,如果一直读不到ACK ,那你也要有个时间跳出去,是10MS ,还是多少,DATASHEET 好像写的最大时间是5MS的了吧!
如果还不行,你用示波器来对你发的东西的波形到底和你写的是不是一样。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询