• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

温度和时钟自动切换显示!有兴趣的朋友进来看下!!!!!

本人学单片机差不多四个多月了,前几天买了一个B20的温度传感器,因对时序很严格,先在网上找了不少的源程序,没办法只有自己写了,下面的程序是我自己写的,给朋友们参考下.时钟和温度切换显示,改天拍个照片发上来给朋友们看看:



Counter  EQU 57H        ;计数器,显示程序通过它得知现正显示哪个数码管
     DISPBUF  EQU 58H        ;显示缓冲区从58H 开始
         SEC  EQU 56H        ;秒计数单元
         Min  EQU 55H        ;分计数单元
        Hour  EQU 54H        ;时计数单元
        Coun  EQU 53H        ;4ms 信号计数器,每计250 次为1s
ccccc   equ 51h
DQ bit  P1.6
;TEMPER_L EQU 29H  ;用于保存读出温度的低8位
;TEMPER_H EQU 28H  ;用于保存读出温度的高8位
FLAG1  EQU 38H   ;是否检测到DS18B20标志位
a_bit  equ 20h   ;数码管个位数存放内存位置
b_bit  equ 21h   ;数码管十位数存放内存位置
c_bit   equ 22h   ;数码管小数部份存放的位置
d_bit   equ 23h   ;数码管小数部份存放的位置
e_bit equ 24h   ;温度标志位显示暂存



         ORG  0000H
        AJMP  START
         ORG  000BH          ;定时器T0 的入口
        AJMP  DISP           ;中断入口
         ORG  30H
START:   MOV  SP,#5FH        ;设置堆栈
         MOV  P0,#0FFH
         MOV  P2,#0FFH       ;初始化,所显示器,LED 灭
  mov  dptr,#distab  ;段码送DPTR
         MOV  TMOD,#00010001B        ;定时器T0 工作于模式1(16 位定时/计数模式)
         MOV  TH0,#4ch
         MOV  TL0,#00h
        SETB  EA
SETB  TR0
        SETB  ET0
         MOV  Counter,#0     ;计数器初始化
         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  ;调用读温度子程序
lcall come
LCALL  DISPLAY   ;调用数码管显示子程序
LCALL  GET_TEMPER  ;调用读温度子程序
lcall come
LCALL  DISPLAY   ;调用数码管显示子程序
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 的中断响应程序
        PUSH  ACC            ;ACC 入栈
        PUSH  PSW            ;PSW 入栈
         MOV  TH0,#4ch
         MOV  TL0,#00h



         INC  COUN           ;4ms 计数器
         MOV  A,COUN
        CJNE  A,#20,DISPEXIT    ;不到1s,则转
         MOV  COUN,#0        ;计数器清零



         INC  SEC            ;到1s,秒计数单元加1
         MOV  A,SEC
        CJNE  A,#60,DISPEXIT    ;不到1min,转
         MOV  SEC,#0        ;秒计数器清零



         INC  MIN
         MOV  A,MIN
        CJNE  A,#60,DISPEXIT
         MOV  MIN,#0        ;分计数器清零



         INC  HOUR
         MOV  A,HOUR
        CJNE  A,#24,DISPEXIT
         MOV  HOUR,#0
DISPEXIT:
         POP  PSW
         POP  ACC
         RETI
;******************************************************
display1:
mov  a,DISPBUF   ;取十位数
MOVC  A,@A+DPTR   ;查十位数的7段代码
mov  p0,a    ;送出十位的7段代码
setb  p2.0    ;开十位显示
acall  d1ms    ;显示1ms
clr  p2.0



mov  a,DISPBUF+1   ;取个位数
MOVC  A,@A+DPTR   ;查个位数的7段代码
mov  p0,a    ;送出个位的7段代码
clr     p0.7
setb  p2.1    ;开个位显示
acall  d1ms    ;显示1ms
clr  p2.1
setb p0.7



mov  a,DISPBUF+2   ;取十位数
MOVC  A,@A+DPTR   ;查十位数的7段代码
mov  p0,a    ;送出十位的7段代码
setb  p2.2    ;开十位显示
acall  d1ms    ;显示1ms
clr  p2.2



mov  a,DISPBUF+3   ;取十位数
MOVC  A,@A+DPTR   ;查十位数的7段代码
mov  p0,a    ;送出十位的7段代码
clr p0.7
setb  p2.3    ;开十位显示
acall  d1ms    ;显示1ms
clr  p2.3
setb p0.7



mov  a,DISPBUF+4   ;取个位数
MOVC  A,@A+DPTR   ;查个位数的7段代码
mov  p0,a    ;送出个位的7段代码
setb  p2.4    ;开个位显示
acall  d1ms    ;显示1ms
clr  p2.4



mov  a,DISPBUF+5   ;取十位数
MOVC  A,@A+DPTR   ;查十位数的7段代码
mov  p0,a    ;送出十位的7段代码
setb  p2.5    ;开十位显示
acall  d1ms    ;显示1ms
clr  p2.5
ret
/*************************************************
这是DS18B20复位初始化子程序
****************************************************/
INIT_1820:
SETB  DQ
NOP
CLR  DQ
;主机发出延时537微秒的复位低脉冲
MOV  R1,#3
TSR1: MOV  R0,#107
DJNZ  R0,$
DJNZ  R1,TSR1
SETB  DQ   ;然后拉高数据线
NOP
NOP
NOP
MOV  R0,#25H
TSR2:
JNB  DQ,TSR3   ;等待DS18B20回应
DJNZ  R0,TSR2
LJMP  TSR4    ; 延时
TSR3:
SETB  FLAG1    ; 置标志位,表示DS1820存在
;CLR  P1.7   ;检查到DS18B20就点亮P1.7LED
LJMP  TSR5
TSR4:
CLR  FLAG1    ; 清标志位,表示DS1820不存在
;CLR  P1.1
LJMP  TSR7



TSR5:
MOV  R0,#117
TSR6:
DJNZ  R0,TSR6   ; 时序要求延时一段时间
TSR7:
SETB  DQ
RET
/***************************************************************
读出转换后的温度值
****************************************************/
GET_TEMPER:
SETB  DQ
LCALL  INIT_1820  ;先复位DS18B20
JB  FLAG1,TSS2
;CLR  P1.2
RET     ; 判断DS1820是否存在?若DS18B20不存在则返回
TSS2:
;CLR  P1.3   ;DS18B20已经被检测到!!!!!!!!!!!!!!!!!!
MOV  A,#0CCH   ; 跳过ROM匹配
LCALL  WRITE_1820
MOV  A,#44H    ; 发出温度转换命令
LCALL  WRITE_1820




LCALL  DISPLAY   ;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒



LCALL  INIT_1820  ;准备读温度前先复位



MOV  A,#0CCH   ; 跳过ROM匹配
LCALL  WRITE_1820



MOV  A,#0BEH   ; 发出读温度命令
LCALL  WRITE_1820

LCALL  READ_18200  ; 将读出的温度数据保存到35H/36H
;CLR  P1.4
RET
/**********************************************************
写DS18B20的子程序(有具体的时序要求)
****************************************************/
WRITE_1820:
MOV  R2,#8   ;一共8位数据
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中读出两个字节的温度数据
****************************************************/
READ_18200:
MOV  R4,#2    ; 将温度高位和低位从DS18B20中读出
MOV  R1,#29H   ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00:
MOV  R2,#8   ;数据一共有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   ;低字节送入A
mov 37h,29h   ;送37进行小数部份的运算
swap a   ;高低交换
anl a,#0fh   ;与出温度低四位
mov 31h,a   ;先存32H
;与出温度的低四位
mov a,28h   ;高字节送入A
mov 36h,28h   ;送36进行温度标志位的运算
swap a   ;交换高低
anl a,#0f0h   ;与出温度高四位
add a,35h   ;高低相加
mov 29h,a
;与出温度的高四位,并合起来放在29h
mov  a,29H   ;将29H中的十六进制数转换成10进制
mov  b,#10    ;10进制/10=10进制
div  ab
mov  b_bit,a   ;十位在a
mov  a_bit,b   ;个位在b
;把整数部份转成十进制,并除10分成个位和十位
mov a,37h   ;低字节送入A
anl a,#0fh   ;与出低四位小数
mov b,#6
mul ab   ;*6取整数,分辩率为0.06
mov 28h,a



mov  a,28H   ;将28H中的十六进制数转换成10进制
mov  b,#10    ;10进制/10=10进制
div  ab
mov  d_bit,a   ;十位在a
mov  c_bit,b   ;个位在b
;在低温度字节里与出小数部份,并*6,分成显示.1和.01
;*************************************************************
;下面部份为把高字节的温度标志位加以区别,为1则显示"L"为0则显示"H"
mov a,31h   ;高字节送A
rr a
rr a
rr a   ;右移三位,
anl a,#01h   ;与出温度正负标志位
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   ;取个位数
MOVC  A,@A+DPTR   ;查个位数的7段代码
mov  p0,a    ;送出个位的7段代码
clr p0.7
setb  p2.2    ;开个位显示
acall  d1ms    ;显示1ms
clr  p2.2
setb p0.7



mov  a,b_bit   ;取十位数
MOVC  A,@A+DPTR   ;查十位数的7段代码
mov  p0,a    ;送出十位的7段代码
setb  p2.1    ;开十位显示
acall  d1ms    ;显示1ms
clr  p2.1



mov  a,c_bit   ;取个位数
MOVC  A,@A+DPTR   ;查个位数的7段代码
mov  p0,a    ;送出个位的7段代码
setb  p2.4    ;开个位显示
acall  d1ms    ;显示1ms
clr  p2.4



mov  a,d_bit   ;取十位数
MOVC  A,@A+DPTR   ;查十位数的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次没完循环
djnz  r0,dpl1   ;2个100次没完循环
ret
D1MS:  MOV  R7,#80
DJNZ  R7,$
RET
DISTAB:  DB  0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h
全部回复(2)
正序查看
倒序查看
少帅
LV.5
2
2006-07-13 11:37
能把你做的东西看看吗
?
0
回复
bailsfi
LV.4
3
2006-07-25 11:59
@少帅
能把你做的东西看看吗?
行,改天我照个片上来
0
回复