本人學(xué)單片機(jī)差不多四個多月了,前幾天買了一個B20的溫度傳感器,因?qū)r序很嚴(yán)格,先在網(wǎng)上找了不少的源程序,沒辦法只有自己寫了,下面的程序是我自己寫的,給朋友們參考下.時鐘和溫度切換顯示,改天拍個照片發(fā)上來給朋友們看看:
Counter EQU 57H ;計數(shù)器,顯示程序通過它得知現(xiàn)正顯示哪個數(shù)碼管
DISPBUF EQU 58H ;顯示緩沖區(qū)從58H 開始
SEC EQU 56H ;秒計數(shù)單元
Min EQU 55H ;分計數(shù)單元
Hour EQU 54H ;時計數(shù)單元
Coun EQU 53H ;4ms 信號計數(shù)器,每計250 次為1s
ccccc equ 51h
DQ bit P1.6
;TEMPER_L EQU 29H ;用于保存讀出溫度的低8位
;TEMPER_H EQU 28H ;用于保存讀出溫度的高8位
FLAG1 EQU 38H ;是否檢測到DS18B20標(biāo)志位
a_bit equ 20h ;數(shù)碼管個位數(shù)存放內(nèi)存位置
b_bit equ 21h ;數(shù)碼管十位數(shù)存放內(nèi)存位置
c_bit equ 22h ;數(shù)碼管小數(shù)部份存放的位置
d_bit equ 23h ;數(shù)碼管小數(shù)部份存放的位置
e_bit equ 24h ;溫度標(biāo)志位顯示暫存
ORG 0000H
AJMP START
ORG 000BH ;定時器T0 的入口
AJMP DISP ;中斷入口
ORG 30H
START: MOV SP,#5FH ;設(shè)置堆棧
MOV P0,#0FFH
MOV P2,#0FFH ;初始化,所顯示器,LED 滅
mov dptr,#distab ;段碼送DPTR
MOV TMOD,#00010001B ;定時器T0 工作于模式1(16 位定時/計數(shù)模式)
MOV TH0,#4ch
MOV TL0,#00h
SETB EA
SETB TR0
SETB ET0
MOV Counter,#0 ;計數(shù)器初始化
MOV DISPBUF+0,#0 ;前五位始終顯示0
MOV DISPBUF+1,#0
MOV DISPBUF+2,#0
MOV DISPBUF+3,#0
MOV DISPBUF+4,#0
MOV SEC,#0
MOV Min,#0
MOV Hour,#0ch
mov Coun,#0
mov ccccc,#0
MOV A,#0
clr p2.6
clr p2.7
setb P3.7
mov 35h,#0
mov 37h,#0
mov 36h,#0
mov 40h,#0
LOOP: LCALL GET_TEMPER ;調(diào)用讀溫度子程序
lcall come
LCALL DISPLAY ;調(diào)用數(shù)碼管顯示子程序
LCALL GET_TEMPER ;調(diào)用讀溫度子程序
lcall come
LCALL DISPLAY ;調(diào)用數(shù)碼管顯示子程序
mov r3,#25
llop: mov r4,#250
lllp: MOV A,HOUR
MOV B,#10
DIV AB
MOV DISPBUF,A
MOV DISPBUF+1,B ;顯示時
MOV A,MIN
MOV B,#10
DIV AB
MOV DISPBUF+2,A
MOV DISPBUF+3,B ;顯示分
MOV A,SEC
MOV B,#10
DIV AB
MOV DISPBUF+4,A
MOV DISPBUF+5,B ;顯示秒
lcall display1
djnz r4,lllp
djnz r3,llop
AJMP LOOP ;在此中間可以按排任意程序,這里僅作示范
DISP: ;定時器T0 的中斷響應(yīng)程序
PUSH ACC ;ACC 入棧
PUSH PSW ;PSW 入棧
MOV TH0,#4ch
MOV TL0,#00h
INC COUN ;4ms 計數(shù)器
MOV A,COUN
CJNE A,#20,DISPEXIT ;不到1s,則轉(zhuǎn)
MOV COUN,#0 ;計數(shù)器清零
INC SEC ;到1s,秒計數(shù)單元加1
MOV A,SEC
CJNE A,#60,DISPEXIT ;不到1min,轉(zhuǎn)
MOV SEC,#0 ;秒計數(shù)器清零
INC MIN
MOV A,MIN
CJNE A,#60,DISPEXIT
MOV MIN,#0 ;分計數(shù)器清零
INC HOUR
MOV A,HOUR
CJNE A,#24,DISPEXIT
MOV HOUR,#0
DISPEXIT:
POP PSW
POP ACC
RETI
;******************************************************
display1:
mov a,DISPBUF ;取十位數(shù)
MOVC A,@A+DPTR ;查十位數(shù)的7段代碼
mov p0,a ;送出十位的7段代碼
setb p2.0 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.0
mov a,DISPBUF+1 ;取個位數(shù)
MOVC A,@A+DPTR ;查個位數(shù)的7段代碼
mov p0,a ;送出個位的7段代碼
clr p0.7
setb p2.1 ;開個位顯示
acall d1ms ;顯示1ms
clr p2.1
setb p0.7
mov a,DISPBUF+2 ;取十位數(shù)
MOVC A,@A+DPTR ;查十位數(shù)的7段代碼
mov p0,a ;送出十位的7段代碼
setb p2.2 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.2
mov a,DISPBUF+3 ;取十位數(shù)
MOVC A,@A+DPTR ;查十位數(shù)的7段代碼
mov p0,a ;送出十位的7段代碼
clr p0.7
setb p2.3 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.3
setb p0.7
mov a,DISPBUF+4 ;取個位數(shù)
MOVC A,@A+DPTR ;查個位數(shù)的7段代碼
mov p0,a ;送出個位的7段代碼
setb p2.4 ;開個位顯示
acall d1ms ;顯示1ms
clr p2.4
mov a,DISPBUF+5 ;取十位數(shù)
MOVC A,@A+DPTR ;查十位數(shù)的7段代碼
mov p0,a ;送出十位的7段代碼
setb p2.5 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.5
ret
/*************************************************
這是DS18B20復(fù)位初始化子程序
****************************************************/
INIT_1820:
SETB DQ
NOP
CLR DQ
;主機(jī)發(fā)出延時537微秒的復(fù)位低脈沖
MOV R1,#3
TSR1: MOV R0,#107
DJNZ R0,$
DJNZ R1,TSR1
SETB DQ ;然后拉高數(shù)據(jù)線
NOP
NOP
NOP
MOV R0,#25H
TSR2:
JNB DQ,TSR3 ;等待DS18B20回應(yīng)
DJNZ R0,TSR2
LJMP TSR4 ; 延時
TSR3:
SETB FLAG1 ; 置標(biāo)志位,表示DS1820存在
;CLR P1.7 ;檢查到DS18B20就點亮P1.7LED
LJMP TSR5
TSR4:
CLR FLAG1 ; 清標(biāo)志位,表示DS1820不存在
;CLR P1.1
LJMP TSR7
TSR5:
MOV R0,#117
TSR6:
DJNZ R0,TSR6 ; 時序要求延時一段時間
TSR7:
SETB DQ
RET
/***************************************************************
讀出轉(zhuǎn)換后的溫度值
****************************************************/
GET_TEMPER:
SETB DQ
LCALL INIT_1820 ;先復(fù)位DS18B20
JB FLAG1,TSS2
;CLR P1.2
RET ; 判斷DS1820是否存在?若DS18B20不存在則返回
TSS2:
;CLR P1.3 ;DS18B20已經(jīng)被檢測到!!!!!!!!!!!!!!!!!!
MOV A,#0CCH ; 跳過ROM匹配
LCALL WRITE_1820
MOV A,#44H ; 發(fā)出溫度轉(zhuǎn)換命令
LCALL WRITE_1820
LCALL DISPLAY ;這里通過調(diào)用顯示子程序?qū)崿F(xiàn)延時一段時間,等待AD轉(zhuǎn)換結(jié)束,12位的話750微秒
LCALL INIT_1820 ;準(zhǔn)備讀溫度前先復(fù)位
MOV A,#0CCH ; 跳過ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ; 發(fā)出讀溫度命令
LCALL WRITE_1820
LCALL READ_18200 ; 將讀出的溫度數(shù)據(jù)保存到35H/36H
;CLR P1.4
RET
/**********************************************************
寫DS18B20的子程序(有具體的時序要求)
****************************************************/
WRITE_1820:
MOV R2,#8 ;一共8位數(shù)據(jù)
CLR C
WR1:
CLR DQ
MOV R3,#5
DJNZ R3,$
RRC A
MOV DQ,C
MOV R3,#21
DJNZ R3,$
SETB DQ
NOP
DJNZ R2,WR1
SETB DQ
RET
/*******************************************************
讀DS18B20的程序,從DS18B20中讀出兩個字節(jié)的溫度數(shù)據(jù)
****************************************************/
READ_18200:
MOV R4,#2 ; 將溫度高位和低位從DS18B20中讀出
MOV R1,#29H ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00:
MOV R2,#8 ;數(shù)據(jù)一共有8位
RE01:
CLR C
SETB DQ
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R3,#8
RE10:
DJNZ R3,RE10
MOV C,DQ
MOV R3,#21
RE20:
DJNZ R3,RE20
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
/****************************************************
溫度計算部份
****************************************************/
come: mov a,29h ;低字節(jié)送入A
mov 37h,29h ;送37進(jìn)行小數(shù)部份的運算
swap a ;高低交換
anl a,#0fh ;與出溫度低四位
mov 31h,a ;先存32H
;與出溫度的低四位
mov a,28h ;高字節(jié)送入A
mov 36h,28h ;送36進(jìn)行溫度標(biāo)志位的運算
swap a ;交換高低
anl a,#0f0h ;與出溫度高四位
add a,35h ;高低相加
mov 29h,a
;與出溫度的高四位,并合起來放在29h
mov a,29H ;將29H中的十六進(jìn)制數(shù)轉(zhuǎn)換成10進(jìn)制
mov b,#10 ;10進(jìn)制/10=10進(jìn)制
div ab
mov b_bit,a ;十位在a
mov a_bit,b ;個位在b
;把整數(shù)部份轉(zhuǎn)成十進(jìn)制,并除10分成個位和十位
mov a,37h ;低字節(jié)送入A
anl a,#0fh ;與出低四位小數(shù)
mov b,#6
mul ab ;*6取整數(shù),分辯率為0.06
mov 28h,a
mov a,28H ;將28H中的十六進(jìn)制數(shù)轉(zhuǎn)換成10進(jìn)制
mov b,#10 ;10進(jìn)制/10=10進(jìn)制
div ab
mov d_bit,a ;十位在a
mov c_bit,b ;個位在b
;在低溫度字節(jié)里與出小數(shù)部份,并*6,分成顯示.1和.01
;*************************************************************
;下面部份為把高字節(jié)的溫度標(biāo)志位加以區(qū)別,為1則顯示"L"為0則顯示"H"
mov a,31h ;高字節(jié)送A
rr a
rr a
rr a ;右移三位,
anl a,#01h ;與出溫度正負(fù)標(biāo)志位
mov 40h,a
jbc 40h,looop ;如果為1則表示溫度為零下,送顯示"L"
mov e_bit,#89h
ret
looop: mov e_bit,#0c7h ;否則為0顯示"H"
ret
/****************************************************
顯示子程序
****************************************************/
display:
;mov dptr,#numtab ;指定查表啟始地址
mov r0,#2
dpl1: mov r1,#250 ;顯示1000次
dplop: mov a,a_bit ;取個位數(shù)
MOVC A,@A+DPTR ;查個位數(shù)的7段代碼
mov p0,a ;送出個位的7段代碼
clr p0.7
setb p2.2 ;開個位顯示
acall d1ms ;顯示1ms
clr p2.2
setb p0.7
mov a,b_bit ;取十位數(shù)
MOVC A,@A+DPTR ;查十位數(shù)的7段代碼
mov p0,a ;送出十位的7段代碼
setb p2.1 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.1
mov a,c_bit ;取個位數(shù)
MOVC A,@A+DPTR ;查個位數(shù)的7段代碼
mov p0,a ;送出個位的7段代碼
setb p2.4 ;開個位顯示
acall d1ms ;顯示1ms
clr p2.4
mov a,d_bit ;取十位數(shù)
MOVC A,@A+DPTR ;查十位數(shù)的7段代碼
mov p0,a ;送出十位的7段代碼
setb p2.3 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.3
mov p0,e_bit ;送出十位的7段代碼顯示"H"
setb p2.0 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.0
mov p0,#0c6h ;送出十位的7段代碼顯示"C"
setb p2.5 ;開十位顯示
acall d1ms ;顯示1ms
clr p2.5
djnz r1,dplop ;100次沒完循環(huán)
djnz r0,dpl1 ;2個100次沒完循環(huán)
ret
D1MS: MOV R7,#80
DJNZ R7,$
RET
DISTAB: DB 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h