各位高手小弟有一问题请教关于I2C
各位高手小弟现在想编一个I2C的读写程序可是老是不行不知为何。
程序如下:
SDA BIT P3.0
SCL BIT P3.1
EPR EQU 10100001B
EPW EQU 10100000B
ORG 0000H
AJMP MAIN
MAIN: MOV SP,#60H
MOV P1,#0FFH
MOV P3,#0FFH
MOV R4,#2FH;对30H到5FH清零
MOV R0,#30H
CLEAR: MOV @R0,#00H
INC R0
DJNZ R4,CLEAR
ST: ACALL DISP
ACALL KEY
AJMP ST
KEY: SETB P3.7
MOV P1,#0F0H
MOV A,P1
CJNE A,#0F0H,KEY0
RET
KEY0: MOV R3,#0F7H
MOV R1,#00H
KEY1: MOV A,R3
MOV P1,A
MOV A,P1
MOV R4,A
SETB C
MOV R5,#04H
KEY2: RLC A
JNC KEYIN
INC R1
DJNZ R5,KEY2
MOV A,R3
SETB C
RRC A
MOV R3,A
JC KEY1
RET
KEYIN: ACALL DL10mS
KEYIN1: MOV A,P1
XRL A,R4
JZ KEYIN1
MOV A,R1
MOV DPTR,#TABLE
MOVC A,@A+DPTR
CJNE A,#0AH,KEYINE1
ACALL XS
RET
KEYINE1:CJNE A,#0BH,KEYINE2
ACALL EEPW
RET
KEYINE2:CJNE A,#0CH,KEYIN2
ACALL EEPR
RET
KEYIN2: XCH A,54H
XCH A,55H
XCH A,56H
XCH A,57H
XCH A,58H
XCH A,59H
MOV A,#0AH
XCH A,30H
XCH A,31H
XCH A,32H
XCH A,33H
XCH A,34H
XCH A,35H
RET
DL10ms: MOV R6,#10
DL1: MOV R7,#250
DJNZ R7,$
DJNZ R6,DL1
RET
DISP: CLR P3.7
MOV A,30H
ORL A,#50H
MOV P1,A
ACALL DL1ms
MOV A,31H
ORL A,#40H
MOV P1,A
ACALL DL1mS
MOV A,32H
ORL A,#30H
MOV P1,A
ACALL DL1ms
MOV A,33H
ORL A,#20H
MOV P1,A
ACALL DL1mS
MOV A,34H
ORL A,#10H
MOV P1,A
ACALL DL1mS
MOV A,35H
ORL A,#00H
MOV P1,A
ACALL DL1mS
RET
DL1ms: MOV R0,#250
DJNZ R0,$
RET
XS: MOV 30H,54H
MOV 31H,55H
MOV 32H,56H
MOV 33H,57H
MOV 34H,58H
MOV 35H,59H
RET
;写串行E2PROM子程序EEPW
; (R3)=器件地址
; (R4)=片内字节地址
; (R1)=欲写数据存放地址指针
; (R7)=连续写字节数n
EEPW: MOV R7,#06H
MOV R1,#30
MOV R3,#0
SETB SDA
SETB SCL
NOP
NOP
CLR SDA;发开始信号
NOP
NOP
MOV A,R3;送器件地址
ACALL SUBS
;MOV A,R4;送片内字节地址
;ACALL SUBS
AGAIN: MOV A,@R1
ACALL SUBS;调发送单字节子程序
INC R1
DJNZ R7,AGAIN;连续写n个字节
CLR SDA;SDA置0, 准备送停止信号
ACALL DELAY;延时以满足传输速率要求
SETB SCL;发停止信号
ACALL DELAY
SETB SDA
RET
SUBS: MOV R0,#07H;发送单字节子程序
LOOP: ;CLR SCL
SETB SCL
RLC A
MOV SDA,C
NOP
;SETB SCL
CLR SCL
ACALL DELAY
DJNZ R0,LOOP ;循环8次送8个bit
;CLR SCL
SETB SCL
ACALL DELAY
;SETB SCL
CLR SCL
ACALL DELAY
REP: MOV C,SDA
JC REP;判应答到否,未到则等待
CLR SCL
RET
DELAY: NOP
NOP
RET
;读串行E2PROM子程序EEPR
;(R1)=欲读数据存放地址指针
;(R3)=器件地址
;(R4)=片内字节地址
;(R7)=连续读字节数
EEPR: MOV R7,#06H
MOV R3,#0
MOV R1,#30
SETB SDA
SETB SCL
NOP
NOP
CLR SDA;发开始信号
NOP
NOP
;MOV A,R3;送器件地址
;ACALL SUBS ;调发送单字节子程序
;MOV A,R4 ;送片内字节地址
;ACALL SUBS
;MOV P3,#0FFH
;CLR SDA ;再发开始信号
MOV A,R3
SETB ACC.0;发读命令
ACALL SUBS
MORE: ACALL SUBR
MOV @R1,A
INC R1
DJNZ R7,MORE
CLR SDA
ACALL DELAY
SETB SCL
ACALL DELAY
SETB SDA ;送停止信号
ACALL DELAY
RET
SUBR: MOV R0,#07H ;接受单字节子程序
LOOP2: SETB SCL
ACALL DELAY
MOV C,SDA
RLC A
CLR SCL
ACALL DELAY
DJNZ R0,LOOP2
CJNE R7,#01H,LOOW
SETB SDA;若是最后一个字节置A=1
AJMP SETOK
LOOW: CLR SDA;否则置A=0
SETOK: ACALL DELAY
SETB SCL
ACALL DELAY
CLR SCL
ACALL DELAY
SETB SDA;应答毕,SDA置1
RET
TABLE: DB 07H,08H,09H,0CH; 7 8 9 C
DB 04H,05H,06H,0DH; 4 5 6 D
DB 01H,02H,03H,0EH; 1 2 3 E
DB 0AH,00H,0BH,0FH; A 0 B F
END
发表时间:2003年7月19日17:14:25