?? i2c存儲器讀寫實驗.asm
字號:
;;; I2C存儲器讀寫實驗
;;; MCU:89S51 COLCK:11.0592MHZ
;;;
;;; 實驗目的: 1. 通過實驗了解I2C的工作原理和用軟件模擬I2C總線的編程方法
;;; 2. 通過實驗了解數據存入I2C E2PROM的過程,實現數據掉電保存.
;;; 實驗內容:把數據存入E2PROM中的指定的地址,而后在把指定地址
;;; 的數據讀出來比較,如相等表示數據讀寫正常,rxd1發光提示,反之沒提示.
;;; 而后把讀到的數據送入電腦顯示
;;;
;;; ***********************************************************************
;;; 接線說明:
;;; J10(25x2雙排插針)第6腳(SD0)和第18腳(CPU的P1.1)連
;;; J10(25x2雙排插針)第8腳(SC0)和第316腳(CPU的P1.0)連
;;; 接上串口線,打開"串口監視軟件",波特率設為19200
;;;***********************************************************************
rxd1 BIT P3.0
SCL BIT p1.0 ; SCL I2C總線位
SDA BIT p1.1 ;SDA I2C總線位
SLA DATA 37H ;SLA 器件從地址
SUBA DATA 38H ;SUBA器件子地址
MRD DATA 40H ;MRD 接收數據緩沖區首址
MTD DATA 48H ;MTD 發送數據緩沖區首址
ACK BIT 30H ;ACK為調試/測試位,ACK為0時表示無器件應答
NUMBYTE DATA 36H ;NUMBYTE讀/寫的字節數
ORG 0000H
AJMP MAIN
ORG 0080H
MAIN: ACALL A200MS
MOV R1,#04
MOV R0,#MTD
MOV A,#30h;00H
DELETE0: ;發送緩沖區賦值分別為00H-03H
MOV @R0,A
INC R0
INC A
DJNZ R1,DELETE0
;存儲空間的首地址:B是高地址A 是低地址如把數據存到高于255地址的存儲空間如288(120H)
;那B=01H,A=20H ,如把數據存到不高于255地址存儲空間如28,那B=0H,A=14H
DELETE1: MOV A,#20H
MOV B,#00H
; I2C(24XX 存儲器)
MOV SLA,#10100000B
MOV SUBA, A ;指定子地址
MOV A,B
RL A
ADD A,SLA
MOV SLA,A ;器件從地址
MOV NUMBYTE, #04h ;接收字節數NUMBYTE
nop
ACALL IWRNBYTE ;調用I2C寫程序
ACALL A200MS ;
;;;;;;;;;;;
MOV R0,#MRD
MOV R2,#04H
CLRR: CLR A ;接受數據緩沖區清零
MOV @R0,A
INC R0
DJNZ R2,CLRR
;存儲空間的首地址:B是高地址A 是低地址
KEYBJASM1: MOV A,#20H
MOV B,#00H
; 讀數據 I2C(24XX 存儲器)
MOV SLA,#10100000B
MOV SUBA, A ;指定子地址
MOV A,B
RL A
ADD A,SLA
MOV SLA,A ;器件從地址
MOV NUMBYTE, #04h ;接收字節數NUMBYTE
nop
LCALL IRDNBYTE ;向I2C(24XX)器件指定子地址讀N個數據
;;; 數據比較
MOV R2,#04H ;賦要比較數據的個數
MOV R0,#MTD ;發送數據緩沖區首地址
MOV R1,#MRD ;接受數據緩沖區首地址MRD
BJMD1: MOV A,@R0
XRL A,@R1 ;兩個數據比較(用異或來比較是否相等)
JNZ BJMD0 ;不相等就轉BJMD0
INC R0 ;數據緩沖區首地址+1
INC R1
DJNZ R2,BJMD1 ;數據沒比較完就繼續
CLR rxd1 ;兩組數據相等rxd1發光提示
; 串行口發送到電腦顯示 波特率為19200.
; 串行口發送到電腦顯示 波特率為19200.
RS232: MOV TMOD,#20H ;設定T1為定時方式2
MOV TH1,#0FDH ;定時初值
MOV TL1,#0FDH ;
MOV PCON,#80H ;波特率為19200
SETB TR1 ;;;;;啟動定時器
MOV SCON,#50H ;串口方式1
MOV R0,#MRD ;#BLK1;;數據地址指針
MOV R7,#4H ;數據長度
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
AAA0: MOV A,@R0
ANL A,#0F0H
SWAP A
MOV DPTR,#CARDASCII
MOVC A,@A+DPTR ;把數據轉換成ASCII顯示
MOV SBUF,A ;發送一個數據
MOV A,@R0
ANL A,#0FH
AAA1: JBC TI,AAA2;;;
SJMP AAA1;;;;
AAA2: MOV DPTR,#CARDASCII
MOVC A,@A+DPTR ;把數據轉換成ASCII顯示
MOV SBUF,A ;發送一個數據
AAA3: JBC TI,AAA4;;;
SJMP AAA3;;;;
AAA4: MOV A,#16
MOV DPTR,#CARDASCII
MOVC A,@A+DPTR ;把數據轉換成ASCII顯示
MOV SBUF,A ;發送一個數據
AAA5: JBC TI,AAA6;;;
SJMP AAA5;;;;
AAA6: MOV A,#17
MOV DPTR,#CARDASCII
MOVC A,@A+DPTR ;把數據轉換成ASCII顯示
MOV SBUF,A ;發送一個數據
INC R0 ;數據地址指針加1
AAA7: JBC TI,AAA8;;;
SJMP AAA7;;;;
AAA8: DJNZ R7,AAA0
;;;;;;
jb p1.0,$
ajmp KEYBJASM1
AJMP $
BJMD0: SETB rxd1 ;兩組數據不相等
AJMP RS232
A200MS: ;200MS延時
MOV R6,#00
A200MS1: MOV R7,#0EFH
A200MS2: NOP
DJNZ R7,A200MS2
DJNZ R6,A200MS1
RET
;;;;;;;;;
CARDASCII :DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,41H,42H,43H,44H,45H,46H,48H,20H
;HEX:00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0AH,0BH,0CH,0DH,0EH,0FH,0HH,空格.
;--------------------------------------------------------------------------------------------------------
;VI2C_ASM.ASM
;I2C 軟件包的底層子程序,使用前要定義好SCL和SDA。在標準80C51模式
;(12 Clock)下,對主頻要求是不高于12MHz(1個機器周期1us);若Fosc>12MHz
;則要增加相應的NOP指令數。在使用本軟件包時,請在你的程序的未尾加入
;$INCLUDE (VI2C_ASM.ASM)即可。
;--------------------------------------------------------------------------------------------------------
;啟動I2C總線子程序
START: SETB SDA
NOP
SETB SCL ;起始條件建立時間大于4.7us
NOP
NOP
NOP
NOP
NOP
CLR SDA
NOP ;起始條件鎖定時大于4us
NOP
NOP
NOP
NOP
CLR SCL ;鉗住總線,準備發數據
NOP
RET
;結束總線子程序
STOP: CLR SDA
NOP
SETB SCL ;發送結束條件的時鐘信號
NOP ;結束總線時間大于4us
NOP
NOP
NOP
NOP
SETB SDA ;結束總線
NOP ;保證一個終止信號和起始信號的空閑時間大于4.7us
NOP
NOP
NOP
RET
;發送應答信號子程序
MACK: CLR SDA ;將SDA置0
NOP
NOP
SETB SCL
NOP ;保持數據時間,即SCL為高時間大于4.7us
NOP
NOP
NOP
NOP
CLR SCL
NOP
NOP
RET
;發送非應答信號
MNACK: SETB SDA ;將SDA置1
NOP
NOP
SETB SCL
NOP
NOP ;保持數據時間,即SCL為高時間大于4.7us
NOP
NOP
NOP
CLR SCL
NOP
NOP
RET
; 檢查應答位子程序
; 返回值,ACK=1時表示有應答
CACK: SETB SDA
NOP
NOP
SETB SCL
CLR ACK
NOP
NOP
MOV C,SDA
JC CEND
SETB ACK ;判斷應答位
CEND: NOP
CLR SCL
NOP
RET
;發送字節子程序
;字節數據放入ACC
;每發送一字節要調用一次CACK子程序,取應答位
WRBYTE: MOV R0,#08H
WLP: RLC A ;取數據位
JC WR1
SJMP WR0 ;判斷數據位
WLP1: DJNZ R0,WLP
NOP
RET
WR1: SETB SDA ;發送1
NOP
SETB SCL
NOP
NOP
NOP
NOP
NOP
CLR SCL
SJMP WLP1
WR0: CLR SDA ;發送0
NOP
SETB SCL
NOP
NOP
NOP
NOP
NOP
CLR SCL
SJMP WLP1
;讀取字節子程序
;讀出的值在ACC
;每取一字節要發送一個應答/非應答信號
RDBYTE: MOV R0,#08H
RLP: SETB SDA
NOP
SETB SCL ;時鐘線為高,接收數據位
NOP
NOP
MOV C,SDA ;讀取數據位
MOV A,R2
CLR SCL ;將SCL拉低,時間大于4.7us
RLC A ;進行數據位的處理
MOV R2,A
NOP
NOP
NOP
DJNZ R0,RLP ;未夠8位,再來一次
RET
; 無子地址器件寫字節數據
; 入口參數: 數據為ACC、器件從地址SLA
; 占用: A、R0、CY
IWRBYTE: PUSH ACC
IWBLOOP: LCALL START ;起動總線
MOV A,SLA
LCALL WRBYTE ;發送器件從地址
LCALL CACK
JNB ACK,RETWRB ;無應答則跳轉
POP ACC ;寫數據
LCALL WRBYTE
LCALL CACK
LCALL STOP
RET
RETWRB: POP ACC
LCALL STOP
RET
;無子地址器件讀字節數據
;入口參數: 器件從地址SLA
;出口參數: 數據為ACC
;占用 A 、R0、R2 、CY
IRDBYTE: LCALL START
MOV A,SLA ;發送器件從地址
INC A
LCALL WRBYTE
LCALL CACK
JNB ACK,RETRDB
LCALL RDBYTE ;進行讀字節操作
LCALL MNACK ;發送非應信號
RETRDB: LCALL STOP ;結束總線
RET
;向器件指定子地址寫N個數據
;入口參數: 器件從地址SLA、器件子地址SUBA 、發送數據緩沖區MTD、發送字節數NUMBYTE
; 占用: A 、R0 、R1 、R3 、CY
IWRNBYTE: MOV A,NUMBYTE
MOV R3,A
LCALL START ;起動總線
MOV A,SLA
LCALL WRBYTE ;發送器件從地址
LCALL CACK
JNB ACK,RETWRN ;無應答則退出
MOV A,SUBA ;指定子地址
LCALL WRBYTE
LCALL CACK
MOV R1,#MTD
WRDA: MOV A,@R1
LCALL WRBYTE ;開始寫入數據
LCALL CACK
JNB ACK,IWRNBYTE
INC R1
DJNZ R3,WRDA ;判斷寫完沒有
RETWRN: LCALL STOP
RET
;向器件指定子地址讀取N個數據
;入口參數: 器件從地址SLA、器件子地址SUBA、接收字節數NUMBYTE
;出口參數: 接收數據緩沖區MTD
;占用:A、 R0、 R1、 R2、 R3、 CY
IRDNBYTE: MOV R3,NUMBYTE
LCALL START
MOV A,SLA
LCALL WRBYTE ;發送器件從地址
LCALL CACK
JNB ACK,RETRDN
MOV A,SUBA ;指定子地址
LCALL WRBYTE
LCALL CACK
LCALL START ;重新起動總線
MOV A,SLA
INC A ;準備進行讀操作
LCALL WRBYTE
LCALL CACK
JNB ACK,IRDNBYTE
MOV R1,#MRD
RDN1: LCALL RDBYTE ;讀操作開始
MOV @R1,A
DJNZ R3,SACK
LCALL MNACK ;最后一字節發非應答位
RETRDN: LCALL STOP ;并結束總線
RET
SACK: LCALL MACK
INC R1
SJMP RDN1
;***************************************************************************************
; 請注意 *
; *
;占用內部資源: R0,R1,R2,R3,ACC,Cy。 *
; 在你的程序里要做以下定義: *
;使用前須定義變量: SLA 器件從地址 SUBA器件子地址 NUMBYTE讀/寫的字節數 ,位變量ACK *
;使用前須定義常量: SDA SCL 總線位 MTD 發送數據緩沖區首址 MRD 接收數據緩沖區首址 *
;(ACK為調試/測試位,ACK為0時表示無器件應答) *
;***************************************************************************************
end
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -