迅维网
标题:
一个读温度不闪的18B20数码管温度计
[打印本页]
作者:
バ幸福De右岸
时间:
2016-7-24 07:59
标题:
一个读温度不闪的18B20数码管温度计
初学单片机,学着做一个18B20温度计,开始在网上找了这么多这方面的程序来学习,但是发现一个共同的问题,就是在18B20读取温度的时候数码管都会闪一下,经过研究发现原来是18B20读取温度需要的时间是毫秒级的,而数码管显示是实时扫描的,所以会造成显示中断。经过几天的折腾后,把显示程序改进了一下,达到了预期效果,现在已经看不到一点闪了,现把程序分享出来,跟同学们交流交流。
先上几张实物:
登录/注册后看高清大图
登录/注册后看高清大图
登录/注册后看高清大图
登录/注册后看高清大图
贴上程序
main.c
/*
程序:18B20数码管显示
MCU:STC89C52RC
晶振:11.0592MHz
*/
#include<reg52.h>
#include "delay.h"
#include "ds18b20.h"
#define uchar unsigned char
#define uint unsigned int
#define duan P2
#define wei P3
sbit dp=P2^7; //小数点
int temp; //温度缓存
//*******************************显示函数*****************************
void Display()
{
uchar code table[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共阳码表0~9、负号、不显,共12位
uchar code wf[5]={0xff,0xfe,0xfd,0xfb,0xf7};//位选表(只用到后4位)
uchar data df[5]; //用来存取温度各位数的值(只用到1-4)
uchar i;
uint j;
j=temp;
if(temp<0)j=-temp; //如果是负数转换成正数
for(i=4;i>0;i--) //循环次数等于温度值的位数
{
df
=j%10; //取出各位数的值
j/=10;
}
if(temp<0)df[1]=10; //如果温度是负数,千位显示负号
if(df[1]==0)df[1]=11; //如果千位是0不显示空
for(i=4;i>0;i--) //循环次数等于数码管的位数
{
delaynms(15); //先延时,跳出循环后马上读取温度,避免读温度时数码管闪
duan=0xff; //先关段显
duan=table[df
]; //送出段码
if(i==3)dp=0; //显示小数点
wei=wf
; //送出位码
}
}
//*********************************主函数*********************************
void main()
{
reset(); //18b20初始化
while(1)
{
Display(); //显示温度
temp=get_temp(); //读取温度
}
}
复制代码
18b20.c
#include <reg52.h>
#include <intrins.h>
#include "ds18b20.h"
#include "delay.h"
//**************************初始化函数************************
void reset()
{
uchar x=0;
DQ = 1;
delayus(1);
DQ = 0;
delayus(50); //延时600us
DQ = 1;
delayus(6); //延时80us
x=DQ;
delayus(45); //延时420us
}
//**************************写字节函数************************
void write_byte(uchar wByte)
{
uchar i;
for(i=8; i>0; i--)
{
DQ = 0;
_nop_();
_nop_();
_nop_();
_nop_();
DQ = wByte & 0x01;
delayus(6);
DQ = 1;
wByte >>= 1;
}
delayus(1);
}
//***********************读字节函数************************
uchar read_byte(void)
{
uchar i,rByte;
for(i=8; i>0; i--)
{
DQ = 0;
_nop_();
rByte >>= 1;
DQ = 1;
_nop_();
_nop_();
_nop_();
_nop_();
if(DQ)
rByte |= 0x80;
delayus(6);
}
return rByte;
}
//************************读取温度函数************************
uint get_temp(void)
{
uchar a=0;
uchar b=0;
int t=0; //温度
uint tt=0;
reset(); //复位
write_byte(0xcc); //忽略ROM
write_byte(0x44); //发送温度转化命令
reset(); //再次复位
write_byte(0xcc); //忽略ROM
write_byte(0xbe);
a= read_byte(); //读温度低字节
b= read_byte(); //读温度高字节
tt=(b<<8)|a; //合并
if(b>200)tt=~tt+1; //如果是负温度取反,加一
t=tt*0.625; //转换成十进制
if(b>200)t=~t; //如果是负温度转换成负数
return(t); //返回温度值
}
复制代码
18b20.h
#ifndef _DS18B20_H_
#define _DS18B20_H_
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P0^7;
void reset(void);//复位
void write_byte(uchar wByte);//写字节
uchar read_byte(void);//读字节
uint get_temp(void);//读温度
#endif
复制代码
delay.c
#include "delay.h"
//**************************10us延时函数************************
void delayus(uint us)
{
while(us--);
}
//**************************nms延时函数************************
void delaynms(uint n)
{
uint a;
uchar b;
for(a=n;a>0;a--)
for(b=110;b>0;b--);
}
复制代码
delay.h
#ifndef _DELAY_H_
#define _DELAY_H_
#define uchar unsigned char
#define uint unsigned int
void delayus(uint us);//延时10微秒
void delaynms(uint n);//延时若干毫秒
#endif
作者:
李续超
时间:
2016-7-24 12:37
楼主总是在牛A与牛C之间徘徊
欢迎光临 迅维网 (https://www.chinafix.com/)
Powered by Discuz! X3.4