📄 i2c.asm
字号:
$NOMOD51
$include (c8051f330.inc)
sda equ p1.6
SCK equ p1.7
wp equ p1.5
org 0000h
ljmp main
org 0030h
main: anl PCA0MD, #NOT(040h) ;关闭看门狗
MOV SP,#60H
MOV OSCICN,#080H ;设置时钟频率为3.0625M
MOV P0MDOUT,#0FFH
MOV P1MDOUT,#03FH
MOV P0SKIP,#0FFH
MOV P1SKIP,#0FFH
MOV XBR1,#040H
; acall ds1337_ini
mov r0,#00H
mov dpl,#0Eh
acall WR_BYTE
mov r0,#00h
mov dpl,#0fh
acall WR_BYTE
mov r0,#4AH ;存放到一4AH为首地址的连续7个内存单元中。
mov dpl,#00h
mov r6,#7
acall RD_SEN
sjmp $
ds1337_ini: nop
mov 3ah,#000h ;second
mov 3bh,#040h
mov 3ch,#015h
mov 3dh,#002h
mov 3eh,#025h
mov 3fh,#007h
mov 40h,#006h ;year
mov dpl,#00h
mov r0,#3ah ;首地址为3AH
mov r6,#7
acall WR_BLK
; 24C02写一个字节
;Input:R0
;---------------------------------------
WR_BYTE:CLR WP ;允许写EEPROM
CALL START ;开始信号
JC WRBT2
MOV A,#0D0H ; specify write operation
CALL SHOUT ;发送控制字
JC WRBT1 ;从器件不响应,转结束
; MOV A,DPH ;设置从器件片内高地址
; CALL SHOUT
; JC WRBT1 ;从器件不响应,转结束
MOV A,DPL ;设置从器件片内低地址
CALL SHOUT
JC WRBT1 ;从器件不响应,转结束
MOV A,R0 ;从R0取数据
CALL SHOUT ;发送数据
JC WRBT1 ;从器件不响应,转结束
CLR C ;清错误标志
WRBT1: CALL STOP ;停止信号
WRBT2: SETB WP ;禁止写EEPROM
RET
;---------------------------------------
; 24C02块写(WR_BLK)
;入口:待写字节在R0指向的缓冲器中,个数在R6;
;---------------------------------------
WR_BLK: CLR WP ;允许写EEPROM
CALL START ;开始信号
JC WR_BL2
MOV A,#0D0H ; specify write operation
CALL SHOUT ;发送控制字
JC WR_BL1 ;从器件不响应,转结束
; MOV A,DPH ;设置从器件片内高地址
; CALL SHOUT
; JC WR_BL1 ;从器件不响应,转结束
MOV A,DPL ;设置从器件片内低地址
CALL SHOUT
JC WR_BL1 ;从器件不响应,转结束
WR_BL5: MOV A,@R0 ;从R0取数据
CALL SHOUT ;发送数据
JC WR_BL1 ;从器件不响应,转结束
inc R0 ; advance buffer pointer
djnz R6,WR_BL5 ; next byte
CLR C ;清错误标志
WR_BL1: CALL STOP ;停止信号
WR_BL2: SETB WP ;禁止写EEPROM
RET
;---------------------------------------
; E2PROM当前地址读取
;---------------------------------------
RD_CUR: CALL START ;开始信号
JC x45 ;从器件不响应,转结束
MOV A,#0D1H ; specify read operation
CALL SHOUT ;发送控制字
JC x44 ;从器件不响应,转结束
CALL SHIN ;接收数据
CALL NAK ;发送确认位(高)
CLR C ;清错误标志
x44: CALL STOP ;停止信号
x45: RET
;---------------------------------------
; E2PROM随机读取
;---------------------------------------
RD_RND: CALL START ; Send dummy write command to set internal address.
JC x47 ; abort if bus not available
MOV A,#0D0H ; specify write operation
CALL SHOUT ; send device address
JC x46 ; abort if no ACKKnowledge
; MOV A,DPH ; send high byte of address
; CALL SHOUT
; JC x46 ; abort if no ACKKnowledge
MOV A,DPL ; send low byte of address
CALL SHOUT
JC x46 ; abort if no ACKKnowledge
CALL RD_CUR ; Call Current Address Read function.
JMP x47 ; exit
x46: CALL STOP
x47: RET
;---------------------------------------
; E2PROM连续读取(RD_SEN)
;入口:R0为缓冲器的首址,要读的个数在R6;
;出口:读出的数据送入R0指向的缓冲器中
;---------------------------------------
RD_SEN: CALL START ; Send dummy write command to set internal address.
JC RD_S7 ; abort if bus not available
MOV A,#0D0H ; specify write operation
CALL SHOUT ; send device address
JC RD_S6 ; abort if no ACKKnowledge
; MOV A,DPH ; send high byte of address
; CALL SHOUT
; JC RD_S6 ; abort if no ACKKnowledge
MOV A,DPL ; send low byte of address
CALL SHOUT
JC RD_S6 ; abort if no ACKKnowledge
CALL START ;开始信号
JC RD_S7 ;从器件不响应,转结束
MOV A,#0D1H ; specify read operation
CALL SHOUT ;发送控制字
JC RD_S6 ;从器件不响应,转结束
RD_S1: CALL SHIN ;接收数据
MOV @R0,A
cjne R6,#1,RD_S2 ; jump if not last byte
call NAK ; do not ACKKnowledge last byte
jmp RD_S3 ; done
RD_S2: call ACKK ; ACKKnowledge byte
inc R0 ; advance buffer pointer
djnz R6,RD_S1 ; next byte
RD_S3: clr c ; clear error flag
RD_S6: CALL STOP
RD_S7: RET
;---------------------------------------
; I2C总线控制程序
;---------------------------------------
;开始信号。Send START, defined as high-to-low SDA with SCK high.
;出口:SCK=SDA=低;若总线不可用,CY=高.
;---------------------------------------
START: CLR SCK
NOP
SETB SDA
SETB SCK
SETB C ;错误标志置位
JNB SDA,x41 ;Verify bus available.
JNB SCK,x41 ;jump if not high
CLR SDA
NOP ;延时
NOP
CLR SCK
CLR C ;清错误标志
x41: RET
;---------------------------------------
;停止信号。Send STOP, defined as low-to-high SDA with SCK high.
;入口:SCK=低;出口:ADSCK=SDA=高.
STOP: CLR SDA
NOP ;enforce SCK low and data setup
NOP
SETB SCK
NOP ;延时
NOP
SETB SDA
RET
;---------------------------------------
;移位输出ACC到24LC64,高有效位在前
; SCK, SDA expected low on entry. Return with SCK low.
; Returns CY set to indicate failure by slave to ACKKnowledge.
; Destroys A.
SHOUT: MOV R7,#8 ;bit counter
SOUT1: RLC A ;move bit into CY
MOV SDA,C ;output bit
NOP ;enforce SCK low and data setup
SETB SCK ;raise clock
NOP ;延时
NOP
CLR SCK ;drop clock
DJNZ R7,SOUT1 ;next bit
SETB SDA ;release SDA for ACKK
NOP ;延时
NOP
SETB SCK ;raise ACKK clock
NOP ;延时
NOP
MOV C,SDA ;get ACKK bit
CLR SCK ;drop ACKK clock
RET
;---------------------------------------
;移位输入一个字节到ACC。Shift in a byte from the AT24Cxx, most significant bit first.
; SCLK expected low on entry. Return with SCLK low.
; Returns received data byte in A.
SHIN: ;CLR A
SETB SDA ;make SDA an input
MOV R7,#8 ;bit count
SHIN1: NOP ;enforce SCK low and data setup
NOP
SETB SCK ;raise clock
NOP ;延时
NOP
MOV C,SDA ;input bit
RLC A ;move bit into byte
NOP
CLR SCK ;drop clock
DJNZ R7,SHIN1 ;next bit
RET
;---------------------------------------
;发送确认位(低)
; SCLK expected low on entry. Return with SCK, SDA low.
ACKK: CLR SDA ;ACKK bit
NOP ;enforce SCK low and data setup
SETB SCK ;raise clock
NOP ;延时
NOP
CLR SCK ;drop clock
RET
;---------------------------------------
;发送确认位(高)
; SCLK expected low on entry. Return with SCK low, SDA high.
NAK: SETB SDA ;NAK bit
NOP ;enforce SCK low and data setup
SETB SCK ;raise clock
NOP ;延时
NOP
CLR SCK ;drop clock
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -