?? wds18b20.asm
字號:
;參考程序B: 程序名WDS18B20.ASM程序功能:DS18B20采樣得到的溫度值存入72H--75H中,再傳送到SAA1064驅動的四位數碼管上顯示.
$include (c8051f020.inc)
DAT EQU P0.2
TEMPH EQU 20H
TEMPL EQU 21H
SAA1064ADR EQU 070H ; SAA1064芯片的寫地址
;SMBus狀態:
SMB_BUS_ERROR EQU 00H ;(所有方式)總線錯誤
SMB_START EQU 08H
;(MT&MR)主收發器發送起始位成功.再將從機寫地,址送SMB0DAT
SMB_RP_START EQU 10H
;(MT&MR)主收發器重復發送起始位成功,再將從機讀地址送SMB0DAT
SMB_MTADDACK EQU 18H ;(MT)主收發器發送從地址+W成功;收到 ACK(從
;機應答) ;再將從器件的子地址送入SMB0DAT
SMB_MTADDNACK EQU 20H
;(MT)主收發器發送從地址+W成功;收到 NACK(從機無應答)
SMB_MTDBACK EQU 28H
;(MT)主收發器發送數據字節成功;收到ACK(從機應答)
SMB_MTDBNACK EQU 30H
;(MT)主發送器發送數據成功;收到NACK(從機無應答).
SMB_MTARBLOST EQU 38H ;(MT)總線競爭失敗
SMB_MRADDACK EQU 40H
;(MR)主收發器發送從地址+R成功;收到 ACK(從機應答)
SMB_MRADDNACK EQU 48H
;(MR)主收發器發送從地址+R成功;收到NACK(從機無應答)
SMB_MRDBACK EQU 50H ;(MR)主收發器接收數據成功;主機發送ACK
SMB_MRDBNACK EQU 58H ;(MR)主收發器接收數據成功;主機發送NACK
DSEG ; 數據段;
ORG 30H;
TRANSMIT_BYTE: DS 1 ;保存SMBus待發送的字節
RECEIVE_BYTE: DS 1 ; 保存SMBus剛收到的字節
SLA_ADD: DS 1 ;保存從地址
WRI_ADD: DS 1 ; 保存從地址+ WRITE
READ_ADD: DS 1 ; 保存從地址+ READ
SUBADDR: DS 1 ;要訪問器件的子地址
; 用于暫存數據的單元
DATA_COUNT: DS 1 ;測試計數器變量
DATA_BYTE: DS 1 ; 測試數據
DATA_ADDR: DS 1 ; 測試存儲器地址
BSEG ; 數據段;
ORG 00H
RW: DBIT 1 ;R/W命令位。l=READ,0=WRITE
SM_BUSY: DBIT 1 ;SMBus忙標志(軟件保存)
BYTE_SENT : DBIT 1
CSEG ;代碼段
ORG 00H ;復位
LJMP DS18B20
ORG 03BH ;SMBus中斷向量
LJMP SMBus_ISR
ORG 100H
DS18B20: MOV WDTCN,#0deH ;關看門狗
MOV WDTCN,#0adH
LCALL PORT_Init
MOV XBR2,#40H ;使能交叉開關和弱上拉
MAIN: LCALL RDTEMP
LCALL DELAY ;延時
SETB EA
LCALL DISPLAY ;用SAA1064驅動四位數碼管顯示四位溫度值.
LCALL BELL
SJMP MAIN
EXCHANG: MOV A,21H ;DS18B20采集到的原始數據已存放在20H,21H中.
MOV B,#16 ;數據處理:將原始轉換為十進制數據,存放在
DIV AB ;72H(百位),73H(十位),74H(個位),75H(小數位)中.
MOV 74H,A
MOV A,20H
MOV B,#16
MUL AB
ADD A,74H
MOV B,#10
DIV AB
MOV 74H,B
MOV B,#10
DIV AB
MOV 73H,B
MOV 72H,A
MOV 71H,#0
MOV A,21H
ANL A,#0FH
MOV B,#8
DIV AB
MOV 75H,#0
CJNE A,#1,SSS
MOV 75H,#5
SSS: RET
RDTEMP: CLR EA
LCALL RESET ;復位
MOV A,#0CCH ;發SKIP ROM 命令
LCALL WRITE
MOV A,#44H ;發開始溫度轉換命令
LCALL WRITE
LCALL RESET
MOV A,#0CCH ;發SKIP ROM 命令
LCALL WRITE
MOV A,#0BEH ; 發讀存儲器命令
LCALL WRITE
LCALL READ ; 讀出溫度的低字節
MOV B,A
MOV TEMPL,A
LCALL READ ; 讀出溫度的高字節
MOV TEMPH,A
LCALL EXCHANG
SETB EA
RET
RESET: ;復位子程序
LA: SETB DAT
MOV R2,#200
LB: CLR DAT
DJNZ R2,LB
SETB DAT
MOV R2, #30
LC: DJNZ R2,LC
CLR C
ORL C,DAT
JC LB
MOV R6,#80
LD: ORL C,DAT
JC LP
DJNZ R6,LD
SJMP LA
DJNZ R6,LD
LP: MOV R2,#250
LF: DJNZ R2,LF
RET
WRITE: ;寫字節子程序
MOV R3,#8
WR1: SETB DAT
MOV R4,#8
RRC A
CLR DAT
WR2: DJNZ R4,WR2 ; DELAY 16US
MOV DAT ,C
MOV R4,#30
WR3: DJNZ R4,WR3
DJNZ R3,WR1
SETB DAT
RET
READ: CLR EA ;讀字節子程序
MOV R6,#8
RD1: CLR DAT
MOV R4,#6
NOP
SETB DAT
RD2: DJNZ R4,RD2
MOV C,DAT
RRC A
MOV R5,#30
RD3: DJNZ R5,RD3
DJNZ R6,RD1
SETB DAT
SETB EA
RET
DELAY: MOV R7,#10 ;延時
DL2: MOV R6,#200
DL1: MOV R5,#250
DL0: DJNZ R5,DL0
DJNZ R6,DL1
DJNZ R7,DL2
RET
BELL: CLR P3.5
MOV R7,#1
ACALL DL2
SETB P3.5
MOV R7,#20
ACALL DL2
RET
DISPLAY:CLR SM_BUSY ;為第一次傳輸清除SM_Busy標志
MOV R1,#50H ;從50H--5EH 看中斷過程
; SAA1064W: 依次連續寫入5個數到SAA1064中去:17H,3FH,06H,5BH,4FH
MOV SUBADDR,#00H ; 裝入SAA1064的子地址(SUBADR=00H)
MOV DATA_COUNT,#6H ; 裝入待寫數據塊的長度
MOV SLA_ADD,#SAA1064ADR ; 裝入從器件的寫地址
MOV 71H,#0AH
MOV R0,#71H ; R0做計數器用
LCALL SEND
CLR EA ; 調用數據發送子程序
RET ; SAA1064顯示結束結束,返回主程序
TAB: DB 3fH,06H,5bH,4FH,66H,6DH,7DH,07H,7FH,6FH,17H
;發送子程序SEND;
;SEND子程序執行一次向SAA1064寫入六位數據(0,17H,4FH,5BH,06H,3FH)的過程。
;該子程序管理SM_BUSY位,設置 RW=WRITE,裝載 SLAW,啟動寫操作。
SEND:
PUSH ACC ;保存累加器
JB SM_BUSY,$ ;等待SMBus空閑
CLR RW ; RW= 0(寫)
MOV A,SLA_ADD ; 取SLA_ADD到A
MOV WRI_ADD,A ;將SLA_ADD+ WRITE保存到SLAW
SETB SM_BUSY ; 占用SMBus
SETB STA ; 啟動發送過程
JB SM_BUSY,$ ;等待發送結束(在中斷中處理)
POP ACC
RET
;SMBus 中斷程序 ,處理SMBUS 中斷
SMBus_ISR:
PUSH PSW ; 保護現場
PUSH ACC ;
PUSH DPH ;
PUSH DPL ;
MOV A,SMB0STA ; 將當前SMBus狀態(SMB0STA)裝入累加器
; 每個狀態對應一個地址偏移量
ANL A,#7FH ; 屏蔽最高位
MOV @R1,A ;在50H---60H中存放SMB0STA和SMB0DAT,可查看中斷路徑
INC R1
MOV @R1,SMB0DAT;
INC R1
MOV DPTR,#SMB_STATE_TABLE ; DPTR指向狀態表的起始地址
JMP @A+DPTR ;轉移到當前狀態
;SMBuS狀態表 ;(SMB0STA =00H)
SMB_STATE_TABLE: ; SMB_BUS_ERROR總線錯誤(對所有方式)
ORG SMB_STATE_TABLE+SMB_BUS_ERROR
SETB STO ; 停止位置1,使硬件復位
JMP SMB_ISR_END ; 中斷返回
;SMB_START ; (SMB0STA =08H)
;主發送器/接收器發送起始位成功.再將從機寫地址送SMB0DAT并清除START位.
ORG SMB_STATE_TABLE+SMB_START
MOV SMB0DAT,WRI_ADD ; 裝載從地址+ W````
CLR STA ; 清除START位
JMP SMB_ISR_END ; 中斷返回
;SMB_RP_START ;(SMB0STA =10H)
;主發送器/接收器發送重復起始位成功.
;再將從機讀地址送SMB0DAT并清除START位.
ORG SMB_STATE_TABLE+SMB_RP_START
MOV SMB0DAT,READ_ADD ;裝載從地址+ R
CLR STA ; 清除START位
JMP SMB_ISR_END
;SMB_MTADDACK (SMB0STA =18H)
;主發送器(MT)發送從地址+W成功;收到 ACK(從機應答)
;再將要發的子地址送入SMB0DAT.
ORG SMB_STATE_TABLE+SMB_MTADDACK
MOV SMB0DAT,SUBADDR ;裝載從器件的子地址到SMB0DAT.
SETB BYTE_SENT ;BYTE_SENT=1.在下一次中斷調用時存儲器地址剛被發送
JMP SMB_ISR_END
;SMB_MTADDNACK (SMB0STA =20H)
;主發送器(MT)發送從地址+W成功;收到 NACK(從機無應答)
;用確認查詢重試。發送 STOP+START
ORG SMB_STATE_TABLE + SMB_MTADDNACK
SETB STO
SETB STA
JMP SMB_ISR_END
;SMB_MTDBACK SMB0STA =28H)
;主發送器(MT)發送數據字節成功;收到ACK(從機應答)
;檢查BYTE_SENT:如果為1,說明剛發出的是存儲器地址;為0,剛發出的是數據字節
ORG SMB_STATE_TABLE+SMB_MTDBACK
DJNZ DATA_COUNT,ADDRESS_SENT
;JBC BYTE_SENT,ADDRESS_SENT ;如果BYTE_SENT=1,清除該位并轉到
;ADDRESS_SENT去執行狀態表以外的處理程序
JMP DATA_SENT ; 如果BYTE_SENT=0,數據剛被發出,
; 傳輸過程完成,轉到傳輸結束
;SMB_MTDBNACK ;(SMB0STA =30H)
;主發送器(MT)發送數據成功;收到NACK,從機無應答.
;用確認查詢重試。發送STOP+START重試
ORG SMB_STATE_TABLE+SMB_MTDBNACK
SETB STO
SETB STA
JMP SMB_ISR_END
; SMB_MTARBLOST ;(SMB0STA =38H);競爭失敗.重新啟動傳輸.
ORG SMB_STATE_TABLE+SMB_MTARBLOST
SETB STO
SETB STA
JMP SMB_ISR_END
; SMB_MRADDACK ;(SMB0STA =40H)
;(MR)主收發器發送從地址+R成功;收到 ACK(從機應答).主機發送ACK.
ORG SMB_STATE_TABLE+SMB_MRADDACK
SETB AA ;主機發送ACK,轉入SMB_MRDBACK
JMP SMB_ISR_END
; SMB_MRADDNACK ;(SMB0STA =48H)
;(MR)主收發器發送從地址+R成功;收到NACK(從機無應答),發送重復起始位重試
ORG SMB_STATE_TABLE+SMB_MRADDNACK
SETB STA
JMP SMB_ISR_END
;SMB_MRDBACK (SMB0STA =50H)
;(MR)主收發器接收數據成功;主機發送ACK .
ORG SMB_STATE_TABLE+SMB_MRDBACK
MOV RECEIVE_BYTE, SMB0DAT
CLR AA ;主機發NACK(清除AA),下一次中斷來時轉入;SMB_MRDBNACK(58H)
CLR SM_BUSY;
JMP SMB_ISR_END
;SMB_MRDBNACK ;(SMB0STA =58H)
;(MR)主收發器接收數據成功;主機發送NACK
;讀操作完成。讀數據寄存器并發送STOP
ORG SMB_STATE_TABLE+SMB_MRDBNACK
MOV RECEIVE_BYTE, SMB0DAT
SETB STO
SETB AA ;主機發ACK,為下一次傳輸置位AA
CLR SM_BUSY;
JMP SMB_ISR_END
;狀態表結束,處理"SMB_MTDBACK"狀態碼的程序段。
;對于地址字節剛發出的狀態。通過檢查RW位確定處理方法。
;如果為讀,則轉到RW_READ,如果為寫,則將待發送數據裝入SMBODAT。
ADDRESS_SENT:
MOV DPTR,#TAB ;查表,找到顯示的數據(字型碼)
MOV A,@R0
MOVC A,@A+DPTR
MOV DATA_BYTE ,A
INC R0
CJNE R0,#75H,VV
ADD A,#80H
MOV DATA_BYTE ,A
VV: MOV SMB0DAT,DATA_BYTE ;將要顯示的數據(字型碼)送SAA1064
JMP SMB_ISR_END ; 中斷返回
;對于地址字節剛發出的狀態。重復發送START,啟動存儲器讀操作
RW_READ:
SETB STA ;重復發送START
JMP SMB_ISR_END ;中斷返回
;這是一個寫操作,數據字節已發出。傳輸過程結束。發送STOP,釋放總線,中斷返回
DATA_SENT:
SETB STO ;發送STOP后中斷返回
CLR SM_BUSY ; 釋放 SMBus
JMP SMB_ISR_END ; 中斷返回
;SMBus ISR exit
;恢復現場,清除SI位,從中斷返回
SMB_ISR_END:
CLR SI
POP DPL
POP DPH
POP ACC
POP PSW
RETI
PORT_Init :
MOV OSCICN,#14H ;內部晶振設定為2MHZ
MOV P0MDOUT,#0FFH ;P0口為開漏方式
MOV XBR0,#01H ;通過功能選擇開關將將SDA接P0.0引腳,SCL接P0.1引腳
MOV XBR2 ,#40H; 允許功能選擇開關和弱上拉
; 初始化SMBus程序段
MOV SMB0CN,#04H ; 配置 SMBus在確認周期發送 ACK
MOV SMB0CR,#0F6H ; 設置時鐘速率=100 kHz (內部晶振設定為2MHZ)
ORL SMB0CN,#40H ; 允許SMBus
ORL EIE1,#02H ; 允許SMBus中斷
SETB EA
RET
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -