;----------------------- ;MCU:AT89C52,Fosc=22.1184MHZ ;程序内容:向AT24C16写一个字节的数据,再读出来,并送到P1口看是否正确 ;------------------------
SDA bit P1.4 SCL bit P1.5
ADDRH EQU 20H ADDRL EQU 21H ADDWH EQU 22H ADDWL EQU 23H _DATA EQU 24H
ORG 0000H LJMP START
ORG 0030H START: MOV SP,#60H
MOV ADDRH,#00H MOV ADDRL,#00H MOV ADDWH,#00H MOV ADDWL,#00H
MOV _DATA,#0FH LCALL W_24C16
LCALL R_24C16 MOV A,25H MOV P1,A ;送到I/O口检测收到的数据是否正确
; RET SJMP $
;--------------------------- ;读AT24C16一个字节数据子程序 ;--------------------------- R_24C16: LCALL _SIGNAL ;调用发起始信号子程序 MOV A,ADDRH ;取要读数据的高位地址 CLR C RLC A ;I/O口模拟I2C只能按位读,左环移一位空出R/W位: 0 0 0 0 A10 A9 A8 R/W ORL A,#0a0H ;保留器件地址1010,AT24C系列的EEPROM的型号地址均为1010 ;1 0 1 0 A10 A9 A8 R/W ;AT24C16的片选信号A2A1A0均用硬件拉低的 ;第一个1表示起始信号,最后一个1表示先写高位地址 CALL SEND ;发送高位地址 MOV A,ADDRL ;取低位地址 LCALL SEND ;发送低位地址 LCALL _SIGNAL ;调用发起始信号子程序,准备传数据 MOV A,#0A1H LCALL SEND ;发送本器件地址 LCALL READ CALL STOP ;调用终止子程序 RET
;--------------------------- ;读数据子程序 ;--------------------------- READ: MOV R7,#08H CLR SCL READ_LOP: CALL DELAY5US SETB SDA SETB SCL CALL DELAY5US MOV C,SDA MOV A,R2 RLC A MOV R2,A CALL DELAY5US CLR SCL DJNZ R7,READ_LOP MOV 25H,A CLR SDA ;应答信号 CALL DELAY5US SETB SCL RET
;--------------------------- ;向AT24C16写入一个字节数据子程序 ;---------------------------
W_24C16:
CALL _SIGNAL ;调用发起始信号子程序 MOV A,ADDWH ;存储单元地址高位0000,0 A10 A9 A8 CLR C RLC A ;左环移一位空出R/W位: 0 0 0 0 A10 A9 A8 R/W ORL A,#0a0H ;保留器件地址1010,AT24C系列的EEPROM的型号地址均为1010;;第一个1表示起始信号,最后一个0表示先写高位地址 ;1 0 1 0 A10 A9 A8 0 CALL SEND ;调用发送子程序,发送第一个字节 MOV A,ADDWL ;存储单元地址低8位 0 0 0 0 0 0 0 0 CALL SEND ;发送低位地址 MOV A,_DATA ;把放在DATA里面要发送的数据给A CALL SEND ;发送数据 CALL STOP ;调用发送终止信号子程序 RET ;传输结束后必须发送终止子程序
;--------------------------- ;发送I2C总线终止信号子程序,关闭24C16 ;--------------------------- STOP: CLR SDA ;SCL=1时,SDA由0变为1,即为终止信号 SETB SCL CALL DELAY5US SETB SDA CALL DELAY5US CLR SCL CLR SDA CALL DELAY5US RET
;--------------------------- ;发送子程序 ;--------------------------- SEND: MOV R7,#08H ;用I/O模拟I2C时,必须按位传输,每个字节8位 CLR SCL SEND_LOP: RLC A ;大循环左移 MOV SDA,C ;只能按位来传输 CALL DELAY5US SETB SCL ;;给SCL一个上升沿 CALL DELAY5US CLR SCL ;开始发送下一位,且SDA上的值只能在SCL为0时才能更改 DJNZ R7,SEND_LOP SETB SDA ;每次发完一个字节后都要发应答信号 CALL DELAY5US SETB SCL CALL DELAY5US SEND_LOP1: ;等待AT24C16的应答信号 MOV C,SDA ;应答信号一来则SDA变0 JC SEND_LOP1 CLR SCL RET
;--------------------------- ;发起始信号子程序 ;---------------------------
_SIGNAL: SETB SCL ;SCL=1时,SDA由1变为0,即为起始信号 SETB SDA CALL DELAY5US CLR SDA CALL DELAY5US CLR SCL CALL DELAY5US RET
;----------------------- ;延时5us子程序 ;-----------------------
DELAY5US: NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP RET
END
|