本帖最后由 EWB5 于 2012-2-2 19:12 编辑
已经弄iic一周了,时好时坏,就是这个汇编程序看不出哪儿不行,用的海象nimi开发板(24M)P2接的是74138;程序如下(自己写的),特意放慢速度,在proteus上运行正常0-7显示,但在板子上不显示0-4,理论上应该一直向后显示的 程序如下:
STORE_PLACE EQU 00H ;24C02芯片内的缓冲区首址
SEND_DATA EQU 30H
RECE_DATA EQU 40H
wr_cmd EQU 0aeH
re_cmd EQU 0afH
NUM1 EQU 8
NUM2 EQU 8
Sda bit p1.2
Scl bit p1.1
WP bit p1.0
ORG 0000h
AJMP MAIN
ORG 0030H
;----------------主函数--------------------------
MAIN:
MOV 30H,#3fH
MOV 31H,#06H
MOV 32H,#5bH
MOV 33H,#4fH;
MOV 34H,#66H
MOV 35H,#6DH
MOV 36H,#7DH
MOV 37H,#07H;
CLR WP
LCALL MAIN_WRITE
LCALL DELAY_S
LCALL MAIN_READ
MOV R0,#RECE_DATA
LOOP: MOV p2,#0fH
MOV p0,@R0
MOV p2,#02H
LCALL DELAY_S
LCALL DELAY_S
INC R0
AJMP LOOP
AJMP $
;*************************页存储num字节的数据***********************
MAIN_WRITE: MOV R5,#NUM1
MOV R0,#SEND_DATA ;发送缓冲区
MOV R1,#STORE_PLACE ;存储地址设置
L0: LCALL START ;启动
L1: MOV A,#wr_cmd ;写控制
LCALL SEND
LCALL CHECK_ACK
JB F0,L1
L2: MOV A,R1 ;存储地址设置
LCALL SEND
LCALL CHECK_ACK
JB F0,L2
L3: MOV A,@R0 ;发送数据
LCALL SEND
LCALL CHECK_ACK
JB F0,L3
LCALL STOP
LCALL DELAY_10MS
LCALL DELAY_10MS
INC R0
INC R1
DJNZ R5,L0 ;发送所有字节
LCALL DELAY_10MS
RET
;*******************Radom读取num字节的数据**************************
MAIN_READ: MOV R5,#NUM2
MOV R0,#RECE_DATA
MOV R1,#STORE_PLACE ;存储缓冲区
L4: LCALL START ;启动
L5: MOV A,#wr_cmd ;写控制
LCALL SEND
LCALL CHECK_ACK
JB F0,L5
L6: MOV A,R1 ;存储地址设置
LCALL SEND
LCALL CHECK_ACK
JB F0,L6
LCALL START ; 再次启动
L7: MOV A,#re_cmd ;读控制
LCALL SEND
LCALL CHECK_ACK
JB F0,L7
L8: LCALL RECE ;读取一个字节数据,结束
LCALL SEND_NOACK
LCALL STOP
MOV @R0,A
INC R0
INC R1
DJNZ R5, L4
LCALL DELAY_10MS;
RET
;----------------IIC启动---------------------------------
START: CLR scl
LCALL DELAY
SETB sda
LCALL DELAY
SETB scl
LCALL DELAY
CLR sda
LCALL DELAY
CLR scl
LCALL DELAY
RET
;---------------IIC停止----------------------------------
STOP: CLR sda
LCALL DELAY
SETB scl
LCALL DELAY
SETB sda
LCALL DELAY
CLR scl
LCALL DELAY
RET
;-------------SEND_ACK是发送应答位子程序---------
SEND_ACK: CLR sda ;拉低sda线
LCALL DELAY
SETB scl ;发出时钟信号
LCALL DELAY
CLR scl
LCALL DELAY
SETB sda;
LCALL DELAY
RET
;------------SEND_NOACK是发送应答位子程序---------
SEND_NOACK: CLR scl
LCALL DELAY
SETB sda ;拉高sda线
LCALL DELAY
SETB scl ;发出时钟信号
LCALL DELAY
CLR scl
LCALL DELAY
CLR sda; ;拉低sda线
LCALL DELAY
RET
;------------CHECK_ACK是检查应答信号---------
CHECK_ACK: CLR F0
SETB sda ;拉高sda为输入方式
LCALL DELAY
SETB scl ;发出一个时钟
LCALL DELAY
CHECK_LOOP: JNB sda,CHECK_ACK_END ;如果sda为0 则收到应答
SETB F0 ;如果sda为1 F0=1;
CHECK_ACK_END:
CLR scl ;否则sda为0,表示接受到应答位,结束时钟
LCALL DELAY
RET
;----------------SEND是发送一个字节8 bit子程序---------------------------
SEND: MOV R7,#8H
WRB0 : RLC A ;左环移,把A的最高位移入cy
JC WRB1
CLR sda
LCALL DELAY
SETB scl ;发出一个时钟
LCALL DELAY
CLR scl
LCALL DELAY
DJNZ R7, WRB0
RET
WRB1: SETB sda
LCALL DELAY
SETB scl ;在scl上产生一个时钟
LCALL DELAY
CLR scl
LCALL DELAY
CLR sda
DJNZ R7, WRB0 ;重复8次,发送一个字节
RET
;---------------RECE是读取一个字节8 bit的数据-----------------------------
RECE: MOV R7,#08H
CLR A
RECE_LOOP: SETB sda
SETB scl ;发出一个时钟
LCALL DELAY
MOV C,sda ;读入sda状态
RLC A ;把该位的状态移入A中
CLR scl
LCALL DELAY
DJNZ R7,RECE_LOOP ;重复8次,读入一个字节
RET
;------------------延时程序----------------------------------------
DELAY : nop ;延时us子程序
nop
nop
nop
nop
nop
nop
RET
DELAY_10MS: MOV R2,#24
del4: MOV R3,#250
del5: DJNZ R3,del5
DJNZ R2,del4
RET
DELAY_S: MOV R2,#10
del1: MOV R3,#200
del2: MOV R4,#250
del3: DJNZ R4,del3
DJNZ R3,del2
DJNZ R2,del1
RET
END
END |