使用蓝桥杯单片机实现温度和时钟界面的无缝切换
1基本功能描述
1)通过DS18B20温度传感器,采集环境温度数据,保留小数点后2位有效数字。
2)读取DS1302时钟芯片的时、分、秒数据。
3)通过数码管显示时间和温度数据,显示界面可以通过按键来回切换。
初始化状态说明
1)关闭蜂鸣器、继电器。
2)数码管处于时间界面。
3)实时时钟的初始化时间是00:00:00
显示界面状态
1)时间界面指示灯L2点亮,其余指示灯熄灭。
2)温度界面指示灯L3点亮,其余指示灯熄灭。
按键功能
1)按键S4定义为“切换”按键,用于切换显示时间和温度界面。
2)按键S5定义为“时”按键,每次按下,时加1。
3)按键S6定义为“分”按键,每次按下,分加1。
4)按键S7定义为“秒”按键,每次按下,秒值清零。
报警条件
- 当时间22:00:00,继电器吸合,指示灯L1点亮, 3秒后,继电器自动断开,指示灯L1熄灭。
- 当温度高于24度时,开启蜂鸣器发出响声,继电器吸合;温度低于24度时自动关闭蜂鸣器继电器。
代码如下
onewire.c
#include "onewire.h"
#include <STC15F2K60S2.H>
sbit DQ = P1^4;
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
t=t*12;
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//
float temperature()
{
int low,hight;
float wundu;
init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//开始温度转换
init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);//读取温度
low=Read_DS18B20();//接收低8位
hight=Read_DS18B20();//接收高8位
wundu=(hight<<8|low)*0.0625;//转换成10进制
return wundu ;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
float temperature();
#endif
ds1302函数c
#include "ds1302.h"
#include <STC15F2K60S2.H>
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
unsigned char DecToBCD(unsigned char j)//将10进制转换成BCD
{
j=(j/10*16)+(j%10);
return j;
}
void ds1302_sy(unsigned char h,unsigned char min ,unsigned char s)
{
Write_Ds1302_Byte( 0x8e,0x00 );//打开写保护
Write_Ds1302_Byte( 0x80,DecToBCD(s) );
Write_Ds1302_Byte( 0x82,DecToBCD(min));
Write_Ds1302_Byte( 0x84,DecToBCD(h));
Write_Ds1302_Byte( 0x8e, 0x80 );//关闭写保护
}
h
#ifndef __DS1302_H
#define __DS1302_H
#include <intrins.h>
unsigned char Read_Ds1302_Byte( unsigned char address );
void ds1302_sy(unsigned char h,unsigned char min ,unsigned char s);
#endif
主体函数
#include <STC15F2K60S2.H>
#include "ds1302.h"
#include "onewire.h"
unsigned char BCDToDec(unsigned char i)//BCD转换成10进程值
{
i=(i/16*10)+(i%16);
return i;
}
void Device(unsigned char p2,unsigned char p0)//配置锁存器
{
P0=p0;
P2=p2;
P2=0;
}
void system()//初始化
{
Device(0x80,0xff);
Device(0xa0,0);
}
int ms;
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0x18; //设置定时初始值
T2H = 0xFC; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
EA =1;
IE2 |= 0x04;
}
//这个为阴极数码管显示表0~9 10 为. 11为—— 12为C
unsigned char smg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x80,0x40,0x39};
void smg_csh(unsigned n,unsigned m)//配置数码管显示
{
int a;
a= 0x01<<n;
Device(0xc0,0);
Device(0xe0,~smg[m]);//显示内容
Device(0xc0,a);//显示的位置为n+1
}
char h,min,s;
void ds1302_dq()//读取时间
{
s = BCDToDec(Read_Ds1302_Byte(0x81));
min = BCDToDec(Read_Ds1302_Byte( 0x83 ));
h = BCDToDec(Read_Ds1302_Byte( 0x85));
}
void ds1302_show()//显示时间
{
smg_csh(0,h/10);
smg_csh(1,h%10);
smg_csh(2,11);
smg_csh(3,min/10);
smg_csh(4,min%10);
smg_csh(5,11);
smg_csh(6,s/10);
smg_csh(7,s%10);
}
unsigned long du;
void ds18b20()//读取温度
{
if(ms>=10)
{
ms=0;
du=(unsigned long)(temperature()*10000); //()强制类型转换
}
}
void ds18b20_show()//显示温度
{
smg_csh(0,12);
smg_csh(4,du/100000);
smg_csh(5,du/10000%10);
smg_csh(5,10);
smg_csh(6,du/1000%10);
smg_csh(7,du/100%10);
}
void Delay() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
int i=0;
void key()
{//按键按下s=0
if(P30==0){Delay();if(P30==0){s=0;ds1302_sy(h,min,s);while(P32==0){}}}
if(P32==0)//按下S5
{//消抖 判断下一个 按下一次加一 限制范围 存入该数据 让数码管闪说明在调整
Delay();if(P32==0){h++;if(h>23){h=0;}ds1302_sy(h,min,s);while(P32==0){}}//控制小时加
}
if(P31==0)//按下s6
{//消抖 判断下一个 按下一次加一 限制范围 存入该数据 让数码管闪说明在调整
Delay();if(P31==0){min++;if(min>59){min=0;}ds1302_sy(h,min,s);while(P31==0){}}//控制分钟加
}
if(P33==0)//变量值改变
{Delay();if(P33==0){i++;i=i%2;while(P33==0){}}}
}
void main()
{
Timer2Init();
system();
ds1302_sy(00,00,00);
while(1)
{
key();
ds1302_dq();
if(i==0)//该条件为时间显示条件
{
ds1302_show();Device(0x80,~0x02);Device(0xa0,0);
//报警的功能
if((h==22)&&(s==0)&&(min==0))
{Device(0xa0,0x10);Device(0x80,~0x01);}
if((h==22)&&(s==3)&&(min==0))
{Device(0xa0,0);Device(0x80,0xff);}
}
}
}
void t2() interrupt 12 //中断入口
{
ms++;
ds18b20();
if(i==1)//温度显示的条件
{
ds18b20_show();
Device(0x80,~0x04);
Device(0xa0,0);
//报警功能
if(du>240000)
{Device(0xa0,0x50);}
if(du<240000)
{Device(0xa0,0);}
}
}
有什么不足的地方请指教