智能手表
项目说明硬件设计温度传感器计算温度读取温度
定时器中断工作方式定时器配置
硬件实物连接软件设计temp.htemp.cmain.c
实验现象与总结
项目说明
用普中51和keil uVision4实现智能手表,功能包括:显示秒表、时间、日期、星期、设置闹钟,读取温度,指示灯亮等。综合的实验主要有独立按键、指示灯亮、温度传感器、定时器、动态数码管显示、蜂鸣器实验,其中本篇博文重要讲解定时器和温度传感器实验,其他结合的实验比较简单,自行查阅资料即可明白。
硬件设计
温度传感器
这个项目我用的是精度较高的外部 DS18B20 数字温度传感器,由于此传感器是单总线接口,所以需要使用 51 单片机的一个 IO 口模拟单总线时序与 DS18B20 通信,将检测的环境温度读取出来。 DS18B20 外观实物如下图所示:
**注意:**如果把传感器插反,那么电源将短路,传感器就会发烫,很容易损坏,所以一定要注意传感器方向,通常在开发板上都会标出传感器的凸起出,所以只需要把传感器凸起的方向对着开发板凸起方向插入即可。
DS18B20 数字温度传感器内部的一些高速暂存存储器自行查阅资料,这里就跳过了,直接理解它是怎么计算温度值的吧。
计算温度
如果测得的温度大于 0,前5 位为‘ 0’,只要将测到的数值乘以 0.0625(默认精度是 12 位)即可得到实际温度;如果温度小于 0,这 5 位为‘ 1’,测到的数值需要取反加 1 再乘以 0.0625 即可得到实际温度。比如我们要计算+85 度,数据输出十六进制是 0X0550,因为高字节的高 5位为 0,表明检测的温度是正温度,0X0550 对应的十进制为 1360,将这个值乘以 12 位精度 0.0625,所以可以得到+85 度。
读取温度
知道了怎么计算温度,接下来我们就来看看如何读取温度数据,由于DS18B20 是单总线器件,所有的单总线器件都要求采用严格的信号时序,以保证 数据的完整性。DS18B20 时序包括如下几种:初始化时序、写(0 和 1)时序、读(0 和 1)时序。 DS18B20 发送所有的命令和数据都是字节的低位在前。 这里主要有这几个信号的时序:(1) 初始化时序、(2)写时序、(3)读时序。时序的详细介绍自行查阅,其实根据字面意思大致也可以猜到是什么意思的。 DS18B20 的典型温度读取过程为:复位→发 SKIP ROM 命令(0XCC)→发开始转换命令(0X44)→延时→复位→发送 SKIP ROM 命令(0XCC)→发读存储器命令(0XBE)→连续读出两个字节数据(即温度)→结束。
定时器中断
学习定时器前需要明白: ①51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之 为定时器/计数器。 ②定时器/计数器和单片机的 CPU 是相互独立的。定时器/计数器工作的过程是自动完成的,不需要 CPU 的参与。 ③51 单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信 号对寄存器中的数据加 1。 有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加 1 的 工作可以交给定时器/计数器处理。CPU 转而处理一些复杂的事情,同时可以实现精确定时作用。
STC89C5X 单片机内有两个可编程的定时/计数器 T0、T1 和一个特殊功能定时器 T2。
工作方式
这里着重讲解定时器常用的工作方式: 计数位数是 16 位,由 TL0 作为低 8 位,TH0 作为高 8 位,组成了16 位加 1 计数器。 计数初值与计数个数的关系为:X=2(16)-N。
定时器配置
这里以定时器 0 为例介绍配置定时器工作方式 1、设定 1ms 初值,开启定时器计数功能以及总中断,如下:
void Timer0Init()
{
TMOD
|=0X01;
TH0
=0XFC;
TL0
=0X18;
ET0
=1;
EA
=1;
TR0
=1;
}
定时器赋初值百度上会教你怎么赋值的,对于定时器 1 的使用方法是一样的,只是将上述的 0 变为 1 即可。
硬件实物连接
由于这个线连接的有点绕,所以直接口述还好些吧。 上面就是用到的GPIO口,LSA、LSB、LSC指的就是74HC138模块,k1到k8就是独立按键模块,led到led4指的是LED交通灯模块,beep指蜂鸣器模块,DS18B20我连接的是P3^7接口,动态数码管我连接的是P0口(在普中51单片机上是J22连接到J6,就是上图中的8排杜邦线)。
软件设计
上述DS18B20温度传感器的代码实现如下:
temp.h
#ifndef _TEMP_H_
#define _TEMP_H_
#include <reg52.h>
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
sbit DSPORT
=P3
^7;
void Delay1ms(uint
);
uchar
Ds18b20Init();
void Ds18b20WriteByte(uchar com
);
uchar
Ds18b20ReadByte();
void Ds18b20ChangTemp();
void Ds18b20ReadTempCom();
int Ds18b20ReadTemp();
#endif
temp.c
#include "temp.h"
void Delay1ms(uint y
)
{
uint x
;
for(;y
>0;y
--)
{
for(x
=110;x
>0;x
--);
}
}
uchar
Ds18b20Init()
{
uchar i
;
DSPORT
= 0;
i
= 70;
while(i
--);
DSPORT
= 1;
i
= 0;
while(DSPORT
)
{
Delay1ms(1);
i
++;
if(i
>5)
{
return 0;
}
}
return 1;
}
void Ds18b20WriteByte(uchar dat
)
{
uint i
, j
;
for(j
=0; j
<8; j
++)
{
DSPORT
= 0;
i
++;
DSPORT
= dat
& 0x01;
i
=6;
while(i
--);
DSPORT
= 1;
dat
>>= 1;
}
}
uchar
Ds18b20ReadByte()
{
uchar byte
, bi
;
uint i
, j
;
for(j
=8; j
>0; j
--)
{
DSPORT
= 0;
i
++;
DSPORT
= 1;
i
++;
i
++;
bi
= DSPORT
;
byte
= (byte
>> 1) | (bi
<< 7);
i
= 4;
while(i
--);
}
return byte
;
}
void Ds18b20ChangTemp()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0x44);
}
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0xbe);
}
int Ds18b20ReadTemp()
{
int temp
= 0;
uchar tmh
, tml
;
Ds18b20ChangTemp();
Ds18b20ReadTempCom();
tml
= Ds18b20ReadByte();
tmh
= Ds18b20ReadByte();
temp
= tmh
;
temp
<<= 8;
temp
|= tml
;
return temp
;
}
最后在主函数一并实现定时器中断实验:
main.c
#include "reg52.h"
#include "temp.h"
typedef unsigned int u16
;
typedef unsigned char u8
;
sbit LSA
=P2
^2;
sbit LSB
=P2
^3;
sbit LSC
=P2
^4;
sbit k1
=P3
^1;
sbit k2
=P3
^2;
sbit k3
=P3
^3;
sbit k4
=P3
^4;
sbit k5
=P3
^5;
sbit k6
=P3
^6;
sbit k7
=P3
^0;
sbit led
=P2
^0;
sbit led1
=P2
^1;
sbit led2
=P2
^5;
sbit led3
=P2
^6;
sbit beep
=P2
^7;
sbit k8
=P1
^0;
sbit led4
=P1
^1;
u8 code smgduan
[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u16 hour
=15,minute
=32,second
=30;
u16 year
=2020,month
=6,day
=30,week
=2;
u8 ssec
,sec
,min
;
u8 DisplayData
[8];
u8 DisplayData1
[8];
u8 DisplayData2
[8];
u8 DisplayData3
[8];
u8 DisplayData4
[8];
void delay(u16 i
)
{
while(i
--);
}
void keypros()
{
if(k1
==0)
{
delay(1000);
if(k1
==0)
{
led1
=1;
led
=1;
led3
=1;
led4
=1;
led
=~led
;
}
while(!k1
);
}
if(k2
==0)
{
delay(1000);
if(k2
==0)
{
led
=1;
led2
=1;
led3
=1;
led4
=1;
led1
=~led1
;
}
while(!k2
);
}
if(k3
==0)
{
delay(1000);
if(k3
==0)
{
led
=1;
led1
=1;
led3
=1;
led4
=1;
led2
=~led2
;
}
while(!k3
);
}
if(k4
==0)
{
delay(1000);
if(k4
==0)
{
led
=1;
led1
=1;
led2
=1;
led4
=1;
led3
=~led3
;
}
while(!k4
);
}
if(k8
==0)
{
delay(1000);
if(k8
==0)
{
led
=1;
led1
=1;
led2
=1;
led3
=1;
led4
=~led4
;
}
while(!k8
);
}
}
void datapros1(int temp
)
{
float tp
;
if(temp
< 0)
{
DisplayData
[0] = 0x40;
temp
=temp
-1;
temp
=~temp
;
tp
=temp
;
temp
=tp
*0.0625*100+0.5;
}
else
{
DisplayData
[0] = 0x00;
tp
=temp
;
temp
=tp
*0.0625*100+0.5;
}
DisplayData1
[1] = smgduan
[temp
/ 10000];
DisplayData1
[2] = smgduan
[temp
% 10000 / 1000];
DisplayData1
[3] = smgduan
[temp
% 1000 / 100] | 0x80;
DisplayData1
[4] = smgduan
[temp
% 100 / 10];
DisplayData1
[5] = smgduan
[temp
% 10];
}
void Timer0Init()
{
TMOD
|=0X01;
TH0
=0Xd8;
TL0
=0Xf0;
ET0
=1;
EA
=1;
TR0
=1;
}
void DigDisplay1()
{
u8 i
;
for(i
=0;i
<6;i
++)
{
switch(i
)
{
case(0): LSA
=0;LSB
=0;LSC
=0; break;
case(1): LSA
=1;LSB
=0;LSC
=0; break;
case(2): LSA
=0;LSB
=1;LSC
=0; break;
case(3): LSA
=1;LSB
=1;LSC
=0; break;
case(4): LSA
=0;LSB
=0;LSC
=1; break;
case(5): LSA
=1;LSB
=0;LSC
=1; break;
}
P0
=DisplayData1
[i
];
delay(100);
P0
=0x00;
}
}
void DigDisplay2()
{
u8 i
;
for(i
=0;i
<8;i
++)
{
switch(i
)
{
case(0):
LSA
=0;LSB
=0;LSC
=0; break;
case(1):
LSA
=1;LSB
=0;LSC
=0; break;
case(2):
LSA
=0;LSB
=1;LSC
=0; break;
case(3):
LSA
=1;LSB
=1;LSC
=0; break;
case(4):
LSA
=0;LSB
=0;LSC
=1; break;
case(5):
LSA
=1;LSB
=0;LSC
=1; break;
case(6):
LSA
=0;LSB
=1;LSC
=1; break;
case(7):
LSA
=1;LSB
=1;LSC
=1; break;
}
P0
=DisplayData2
[i
];
delay(100);
P0
=0x00;
}
}
void datapros2()
{
DisplayData2
[0]=smgduan
[hour
/10];
DisplayData2
[1]=smgduan
[hour
%10];
DisplayData2
[2]=0x40;
DisplayData2
[3]=smgduan
[minute
/10];
DisplayData2
[4]=smgduan
[minute
%10];
DisplayData2
[5]=0x40;
DisplayData2
[6]=smgduan
[second
/10];
DisplayData2
[7]=smgduan
[second
%10];
}
void datapros4()
{
DisplayData4
[0]=0x00;
DisplayData4
[1]=0x00;
DisplayData4
[2]=0x00;
DisplayData4
[3]=0x00;
DisplayData4
[4]=0x00;
DisplayData4
[5]=0x00;
DisplayData4
[6]=0x00;
DisplayData4
[7]=smgduan
[week
%10];
}
void DigDisplay4()
{
u8 i
;
for(i
=0;i
<8;i
++)
{
switch(i
)
{
case(0):
LSA
=0;LSB
=0;LSC
=0; break;
case(1):
LSA
=1;LSB
=0;LSC
=0; break;
case(2):
LSA
=0;LSB
=1;LSC
=0; break;
case(3):
LSA
=1;LSB
=1;LSC
=0; break;
case(4):
LSA
=0;LSB
=0;LSC
=1; break;
case(5):
LSA
=1;LSB
=0;LSC
=1; break;
case(6):
LSA
=0;LSB
=1;LSC
=1; break;
case(7):
LSA
=1;LSB
=1;LSC
=1; break;
}
P0
=DisplayData4
[i
];
delay(100);
P0
=0x00;
}
}
void DigDisplay3()
{
u8 i
;
for(i
=0;i
<8;i
++)
{
switch(i
)
{
case(0):
LSA
=0;LSB
=0;LSC
=0; break;
case(1):
LSA
=1;LSB
=0;LSC
=0; break;
case(2):
LSA
=0;LSB
=1;LSC
=0; break;
case(3):
LSA
=1;LSB
=1;LSC
=0; break;
case(4):
LSA
=0;LSB
=0;LSC
=1; break;
case(5):
LSA
=1;LSB
=0;LSC
=1; break;
case(6):
LSA
=0;LSB
=1;LSC
=1; break;
case(7):
LSA
=1;LSB
=1;LSC
=1; break;
}
P0
=DisplayData3
[i
];
delay(100);
P0
=0x00;
}
}
void datapros3()
{
DisplayData3
[0]=smgduan
[year
/1000];
DisplayData3
[1]=smgduan
[year
/100%10];
DisplayData3
[2]=smgduan
[year
/10%10];
DisplayData3
[3]=smgduan
[year
%10];
DisplayData3
[4]=smgduan
[month
/10];
DisplayData3
[5]=smgduan
[month
%10];
DisplayData3
[6]=smgduan
[day
/10];
DisplayData3
[7]=smgduan
[day
%10];
}
void DigDisplay()
{
u8 i
;
for(i
=0;i
<8;i
++)
{
switch(i
)
{
case(0):
LSA
=0;LSB
=0;LSC
=0; break;
case(1):
LSA
=1;LSB
=0;LSC
=0; break;
case(2):
LSA
=0;LSB
=1;LSC
=0; break;
case(3):
LSA
=1;LSB
=1;LSC
=0; break;
case(4):
LSA
=0;LSB
=0;LSC
=1; break;
case(5):
LSA
=1;LSB
=0;LSC
=1; break;
case(6):
LSA
=0;LSB
=1;LSC
=1; break;
case(7):
LSA
=1;LSB
=1;LSC
=1; break;
}
P0
=DisplayData
[i
];
delay(100);
P0
=0x00;
}
}
void datapros()
{
DisplayData
[0]=smgduan
[min
/10];
DisplayData
[1]=smgduan
[min
%10];
DisplayData
[2]=0x40;
DisplayData
[3]=smgduan
[sec
/10];
DisplayData
[4]=smgduan
[sec
%10];
DisplayData
[5]=0x40;
DisplayData
[6]=smgduan
[ssec
/10];
DisplayData
[7]=smgduan
[ssec
%10];
}
void main()
{
led
=1;
led1
=1;
led2
=1;
led3
=1;
led4
=1;
Timer0Init();
while(1)
{
keypros();
while(hour
==16 && minute
==50)
{
beep
=~beep
;
delay(100);
if(led2
==0)
{
datapros2();
DigDisplay2();
}
}
if(led
==0)
{
datapros();
DigDisplay();
}
if(led1
==0)
{
datapros1(Ds18b20ReadTemp());
DigDisplay1();
}
if(led2
==0)
{
datapros2();
DigDisplay2();
}
if(led3
==0)
{
datapros3();
DigDisplay3();
}
if(led4
==0)
{
datapros4();
DigDisplay4();
}
}
}
void Timer0() interrupt
1
{
if(k5
==0 && led2
==0)
{
delay(1000);
if(k5
==0)
{
hour
++;
if(hour
==24)
{
hour
=0;
week
++;
day
++;
}
}
while(!k5
);
}
if(k6
==0 && led2
==0)
{
delay(1000);
if(k6
==0)
{
minute
++;
if(minute
==60)
{
minute
=0;
hour
++;
}
}
while(!k6
);
}
if(k7
==0 && led2
==0)
{
delay(1000);
if(k7
==0)
{
second
++;
if(second
==60)
{
second
=0;
minute
++;
}
}
while(!k7
);
}
if(k5
==0 && led3
==0)
{
delay(1000);
if(k5
==0)
{
year
++;
if(year
==10000)
{
year
=0;
}
}
while(!k5
);
}
if(k6
==0 && led3
==0)
{
delay(1000);
if(k6
==0)
{
month
++;
if(month
==13)
{
month
=1;
year
++;
}
}
while(!k6
);
}
if(k7
==0 && led3
==0)
{
delay(1000);
if(k7
==0)
{
day
++;
week
++;
if(week
==8)
{
week
=1;
}
if(month
==1 || month
==3 || month
==5 || month
==7 || month
==8 || month
==10)
{
if(day
==32)
{
day
=1;
month
++;
}
}
if(month
==4 || month
==6 || month
==9 || month
==11)
{
if(day
==31)
{
day
=1;
month
++;
}
}
if(month
==2)
{
if(year
%4==0 && year
%100!=0 &&day
==30)
{
day
=1;
month
++;
}
if(year
%400==0 && day
==30)
{
day
=1;
month
++;
}
if(year
%4!=0 && day
==29)
{
day
=1;
month
++;
}
if(year
%4==0 && year
%100==0 && year
%400!=0 && day
==29)
{
day
=1;
month
++;
}
}
}
while(!k7
);
}
TH0
=0Xd8;
TL0
=0Xf0;
ssec
++;
if(ssec
>=100)
{
ssec
=0;
sec
++;
second
++;
if(second
==60)
{
second
=0;
minute
++;
if(minute
==60)
{
minute
=0;
hour
++;
if(hour
==24)
{
hour
=0;
day
++;
}
if(month
==1 || month
==3 || month
==5 || month
==7 || month
==8 || month
==10)
{
if(day
==32)
{
day
=1;
month
++;
}
}
if(month
==4 || month
==6 || month
==9 || month
==11)
{
if(day
==31)
{
day
=1;
month
++;
}
}
if(month
==2)
{
if(year
%4==0 && year
%100!=0 &&day
==30)
{
day
=1;
month
++;
}
if(year
%400==0 && day
==30)
{
day
=1;
month
++;
}
if(year
%4!=0 && day
==29)
{
day
=1;
month
++;
}
if(year
%4==0 && year
%100==0 && year
%400!=0 && day
==29)
{
day
=1;
month
++;
}
}
if(month
==12)
{
month
=1;
year
++;
if(year
==10000)
{
year
=0;
}
}
}
}
if(sec
>=60)
{
sec
=0;
min
++;
if(min
>=60)
{
min
=0;
}
}
}
}
结合主函数main.c和temp.h和temp.c函数在keil4里面运行即可产生hex文件,接下来烧录单片机即可。
实验现象与总结
烧录单片机后,单片机运行:
51单片机实现智能手表
大致实现就这样,觉得本篇博文不错的,也可以给博客点个赞、关注哟!后面也一起学习吧。