?? pcf8574ab.asm
字號:
;實驗29 程序PCF8574AB.ASM
;用I2C(與SUNBUS兼容)虛擬總線的方法編程.調用I2C通用子程序軟件包.
;程序功能:PCF8574是帶SUMBUS總線的串口轉并口的數據轉換芯片.一個8位
;口連結8個開關(K1-K8)作輸入,二個8位輸出鎖存口分別連結8個LED燈,指示二個8位
;輸出.程序安排二個8位輸出口鎖存的數據電平相反.
; 運行參考程序,在連續輸出三組數據:#0AAH,#55H;#0FH,#0F0H及#00H,#0FFH之后,
;處于輸入狀態,等待用戶通過開關K1~K8輸入數據并顯示出來。
$include (C8051F020.inc)
SLA1W EQU 70H ;PCF8574 A片寫的節點地址(地址開關S1:000H)
SLA1R EQU 71H ;PCF8574 A片讀的節點地址
SLA2W EQU 72H ;PCF8574 B片寫的節點地址 (地址開關S2:001H )
SLA2R EQU 73H ;PCF8574 B片讀的節點地址
SLA3W EQU 74H ;PCF8574 C片寫的節點地址 ((地址開關S3:010H)
SLA3R EQU 75H ;PCF8574 C片讀的節點地址
SLA EQU 60H
COM EQU 17H
SLAW EQU 62H
SLAR EQU 63H
NUMBYT EQU 61H ;被傳送的字節數存放單元
MTD EQU 20H ;發送數據緩沖區首地址
MRD EQU 30H ;接收字節緩沖區首地址
VSCL EQU P0.1 ;模擬I2C總線時鐘線
VSDA EQU P0.0 ;模擬I2C總線數據線
ORG 0
SJMP MAIN
MAIN: MOV WDTCN,#0DEH ;禁止看門狗定時器
MOV WDTCN,#0ADH;
MOV XBR2,#40H ;交叉開關使能
ACALL INITA ;作為輸入用的芯片應先初始化。
ACALL OUTPUT1 ;輸出數據0AAH
ACALL DELAY ;延時
ACALL OUTPUT2 ;輸出數據55H
ACALL DELAY ;延時
ACALL OUTPUT3 ;輸出數據0FH
ACALL DELAY ;延時
ACALL OUTPUT4 ;輸出數據0F0H
ACALL DELAY ;延時
ACALL OUTPUT5 ;輸出數據0H
ACALL DELAY ;延時
LOOP: ACALL PCFIO ;從輸入器件U1讀取開關K1~K8的狀態數據并存入
AJMP LOOP ;MRD中,再送U2,U3去。
OUTPUT1: MOV A,#0AAH ;輸出數據0AAH
PUSH ACC
ACALL WRITEB
POP ACC
CPL A
ACALL WRITEC
RET
OUTPUT2: MOV A,#55H ;輸出數據55H
PUSH ACC
ACALL WRITEB
POP ACC
CPL A
ACALL WRITEC
RET
OUTPUT3: MOV A,#0FH ;輸出數據0FH
PUSH ACC
ACALL WRITEB
POP ACC
CPL A
ACALL WRITEC
RET
OUTPUT4: MOV A,#0F0H ;輸出數據0F0H
PUSH ACC
ACALL WRITEB
POP ACC
CPL A
ACALL WRITEC
RET
OUTPUT5: MOV A,#0H ;輸出數據0H
PUSH ACC
ACALL WRITEB
POP ACC
CPL A
ACALL WRITEC
RET
PCFIO : ACALL READA ;從輸入器件U1讀取開關K1~K8的狀態數據并存入MRD中
MOV A,MRD
MOV B,A
ACALL WRITEB ;將讀入的數據送器件B
MOV A,B
CPL A ;將讀入的數據取反后送器件C
ACALL WRITEC
RET
READA: MOV SLAW,#SLA1W ;讀A口
MOV SLAR,#SLA1R
WRA: MOV SLA,SLAR
MOV NUMBYT,#1
LCALL RDNBYT
RET
INITA: MOV SLAW,#SLA1W ;初始化:應置輸入口鎖存器為高電平
MOV SLAR,#SLA1R
MOV MTD,#0FFH
MOV SLA,SLAW
MOV NUMBYT,#1
LCALL WRNBYT
RET
WRITEB: MOV SLAW,#SLA2W ;將數據送器件B
MOV SLAR,#SLA2R
ACALL WRBC
RET
WRITEC: MOV SLAW,#SLA3W ;將數據送器件C
MOV SLAR,#SLA3R
ACALL WRBC
RET
WRBC: MOV MTD,A
MOV SLA,SLAW
MOV NUMBYT,#1
LCALL WRNBYT
RET
DELAY: MOV R7,#50 ;5s
DL2: MOV R6,#100 ;100ms
DL1: MOV R5,#250 ;1ms假定晶振為6MHZ
DL0: DJNZ R5,DL0
DJNZ R6,DL1
DJNZ R7,DL2
RET
;發送一個字節數據(WRBYT)子程序,該子程序是向虛擬IIC總線的數據線VSDA上發送
;一個字節數據的操作。調用本子程序前將要發送的數據送入A中。占用資源:R0,C。
WRNBYT: MOV R3,NUMBYT
LCALL STAA ;啟動IIC總線
MOV A,SLA ;發送SLAW字節
LCALL WRBYT
LCALL CACK ;檢查應答位
JB F0,WRNBYT ;非應答位則重發
MOV R1,#MTD
WRDA: MOV A,@R1
LCALL WRBYT
LCALL CACK
JB F0,WRNBYT
INC R1
DJNZ R3,WRDA
LCALL STOP
RET
;向被控器件發送N個字節數據(WRNBYT)子程序
WRBYT: MOV R0,#08H ;8為數據長度送R0中
WLP: RLC A ;發送數據左移,使發送位入C
JC WR1 ;判斷發送"1"還是"0",發送"1"轉WR1
AJMP WR0 ;發送"0"轉WR0
WLP1: DJNZ R0,WLP ;8位是否發送完,未完轉WLP
RET ;8位發送完結束
WR1: SETB VSDA ;發送"1"程序段
SETB VSCL
NOP
NOP
CLR VSCL
CLR VSDA
AJMP WLP1
WR0: CLR VSDA ;發送"0"程序段
SETB VSCL
NOP
NOP
CLR VSCL
AJMP WLP1
;通用N字節接收子程序(RDNBYT)
RDNBYT:MOV R3,NUMBYT
LCALL STAA ;發送啟動位
MOV A,SLA ;發送尋址字節(讀)
LCALL WRBYT
LCALL CACK ;檢查應答位
JB F0,RDNBYT ;非正常應答時重新開始
RDN: MOV R1,#MRD ;接收數據緩沖區首址MDR入R1
RDN1: LCALL RDBYT ;讀入一個字節到接收數據緩沖中
MOV @R1,A
DJNZ R3,ACK ;N節讀完否?未完轉ACK
LCALL MNACK ;N個字節讀完發送非應答位
LCALL STOP ;發送停止信號
RET ;子程序結束
ACK: LCALL MACK ;發送應答位
INC R1 ;指向下一個接收數據緩沖單元
SJMP RDN1 ;轉讀入下一個字節數據
CACK: SETB VSDA ;置VSDA為輸入方式
SETB VSCL ;使VSDA上數據有效
CLR F0 ;預設F0=0
MOV C,VSDA ;輸入VSDA引腳狀態
JNC CEND ;檢查VSDA狀態,正常應答轉CEND,且F0=0
SETB F0 ;無正常應答,F0=1
CEND: CLR VSCL ;子程序結束,使VSCL=0
RET
MACK: CLR VSDA;發送應答位MACK子程序
SETB VSCL
NOP
NOP
CLR VSCL
SETB VSDA
RET
MNACK: SETB VSDA ;發送非應答位 MNACK子程序
SETB VSCL
NOP
NOP
CLR VSCL
CLR VSDA
RET
;從VSDA上接收一個字節數據(RDBYT)子程序,該子程序用來從VSDA上讀取一個字節數據.執行本程序后,從VSDA上讀取的一個字節存放在R2或A中。資源占用:R0,R2,C。
RDBYT: MOV R0,#08H ;8位數據長度如R0
RLP: SETB VSDA ;置VSDA為輸入方式
SETB VSCL ;使VSDA上數據有效
MOV C,VSDA ;讀入VSDA引腳狀態
MOV A,R2 ;讀入"0"程序段,由C拼裝入R2中
RLC A
MOV R2,A
CLR VSCL ;使VSCL=0可繼續接收數據位
DJNZ R0,RLP ;8位讀完否?未讀完轉RLP
RET
STAA: SETB VSDA;啟動STAA子程序
SETB VSCL
NOP
NOP
CLR VSDA
NOP
NOP
CLR VSCL
RET
STOP:CLR VSDA;停止(STOP)子程序
SETB VSCL
NOP
NOP
SETB VSDA
NOP
NOP
CLR VSDA
CLR VSCL
RET
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -