设计背景
当我们要查看室内外温度时,在我们身边的智能设备只有手机天气可以查看,而天气查看的当地气温是根据卫星测量的出的温度区间,而我们并不能具体到自己身边的温度。我们无法得知令我们感到寒冷的天气到底有多少度,也无法得知令我们感到舒适的温度到底是多少度,所以我萌生了做一个实时温度极,具有体积小、测量准、能够揣兜里不占地方,最好是能够采用充电式。
器件选择
- 采用DS18B20温度传感器,采用单总线协议与单片机通信,精度可达0.0625度,误差±0.1度,测量范围-55度-125度;
- 单片机采用了宏晶科技STC8G1K08单片机,其具有18个可用IO口,十分适合驱动四段八位数码,且高速稳定。
- 显示部分使用了四段八位的共阴极数码管,可以说是我的库存,简单来说便宜,且数字的显示风格很装逼。
- 为达到设备便携的目的,使用了TP4054锂电池充电管理IC,其可调的最大充电电流600ma能够再很短的时间内将小容量电池充满,非常适合便携式设备充电。
原理图设计
![](https://cdn.jsdelivr.net/npm/typecho_joe_theme@4.3.5/assets/img/lazyload.jpg)
PCB设计
![](https://cdn.jsdelivr.net/npm/typecho_joe_theme@4.3.5/assets/img/lazyload.jpg)
3D仿真
实物图
程序代码
#include <STC8G.H>
#include "temp.h"
#define u8 unsigned char
#define u16 unsigned int
u16 temp,temp2;
u8 num1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//正常不带小数点
u8 num2[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1};//正常带小数点
u8 flag=0,num=0,dig=0;
void Delay500ms() //@11.0592MHz
{
unsigned char data i, j, k;
i = 29;
j = 14;
k = 54;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer0_Init(void) //200微秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x5C; //设置定时初始值
TH0 = 0xF7; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
void Init()
{
P1M0=0;
P1M1=0;
P3M0=0;
P3M1=0;
P5M0=0;
P5M1=0;
EA=1;
ET0=1;
}
void main()
{
Init();
Timer0_Init();
Delay500ms();
while(1)
{
Delay500ms();
temp2 = Ds18b20ReadTemp();
if(temp/256 > 7)//判断温度是否为负值
{
flag=1;
temp2 = ~temp2;
temp2+=1;
}
else
flag=0;
if(temp2 <= 0x0fff)
temp = (int)temp2*0.625;//换算温度值放大十倍
TR0=1;
}
}
void timer0()interrupt 1
{
num++;
if(num==5)
{
num=0;
if(flag==0)//正负判断
{
switch(dig)
{
case 0:dig=1;
P1=0X00; //消影
P3 = 0XEF;//P34
if(temp/1000)
P1=num1[temp/1000];
else
P1=0X00;
break;
case 1:dig=2;
P1=0X00; //消影
P3 = 0XDF;//P35
if(temp/100)
P1=num1[(temp%1000)/100];
else
P1=0X00;
break;
case 2:dig=3;
P1=0X00; //消影
P3 = 0XBF;//P36
P1=num2[(temp%100)/10];//加小数点
break;
case 3:dig=0;
P1=0X00; //消影
P3 = 0X7F;//P36
P1=num1[temp%10];
break;
}
}
else
{
switch(dig)
{
case 0:dig=1;
P1=0X00; //消影
P3 = 0XEF;//P34
P1=0x40;
break;
case 1:dig=2;
P1=0X00; //消影
P3 = 0XDF;//P35
if(temp/100)
P1=num1[(temp%1000)/100];
else
P1=0X00;
break;
case 2:dig=3;
P1=0X00; //消影
P3 = 0XBF;//P36
P1=num2[(temp%100)/10];//加小数点
break;
case 3:dig=0;
P1=0X00; //消影
P3 = 0X7F;//P37
P1=num1[temp%10];
break;
}
}
}
}
#ifndef _temp_H_
#define _temp_H_
#include <STC8g.H>
#include <intrins.H>
#define u8 unsigned char
#define u16 unsigned int
sbit DQ = P5^5;
void Delay5us(u8 j);
void Ds18b20Init();
void Ds18b20WriteByte(unsigned char com);
unsigned char Ds18b20ReadByte();
void Ds18b20ChangTemp();
void Ds18b20ReadTempCom();
unsigned int Ds18b20ReadTemp();
#endif
#include "temp.h"
void Delay5us(u8 j) //@11.0592MHz
{
unsigned char data i;
for(;j>0;j--)
{
_nop_();
i = 16;
while (--i);
}
}
void Delay2us() //@11.0592MHz
{
unsigned char data i;
_nop_();
i = 5;
while (--i);
}
void Ds18b20Init() //复位应答脉冲
{
DQ=0;
Delay5us(100);
DQ=1;
Delay5us(12);
}
void Ds18b20WriteByte(unsigned char dat)
{
unsigned int j;
for(j=0;j<8;j++)
{
DQ=0;
Delay5us(2);
if(dat&0x01)
DQ=1;
Delay5us(12);
DQ=1;
Delay5us(2);
dat>>=1;
}
}
unsigned char Ds18b20ReadByte()
{
unsigned char byte,j;
for(j=8;j>0;j--)
{
byte>>=1;
DQ=0;
Delay2us();
DQ=1;
Delay2us();
if(DQ)
byte |= 0x80;
Delay5us(12);
}
return byte;
}
void Ds18b20ChangTemp()
{
Ds18b20Init();
while(DQ==0);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0x44);
}
void Ds18b20ReadTempCom()
{
Ds18b20Init();
while(DQ==0);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0xbe);
// Ds18b20Init();
}
unsigned int Ds18b20ReadTemp()
{
unsigned char temp=0;
unsigned char tmh,tml;
unsigned char num1,num2,num3,num4;
unsigned int tem;
tem =0;
Ds18b20ChangTemp();
Ds18b20ReadTempCom();
tml=Ds18b20ReadByte();
tmh=Ds18b20ReadByte();
num1=Ds18b20ReadByte();
num2=Ds18b20ReadByte();
num3=Ds18b20ReadByte();
num4=Ds18b20ReadByte();
tem+=tmh;
tem<<=8;
tem+=tml;
// if(tmh>7)
// {
// tem = ~tem;
// tem = tem+1;
// }
// tem = (int)tem*0.625;
// tem += num3;
return tem;
}