基于51单片机ds1302时钟、ds18b20的恒温器
广西河池学院
广西高校重点实验室培训基地
系统控制与信息处理重点实验室
本篇博客来自河池学院:OpenWRT无线路由组
写作时间:2020年8月12日22:00:00
首先要感谢学长学姐们在制作项目的时间里指导,期间遇到许多的问题,有的得到了解决,有的实在解决不了的只能另选方法,在问题中发现、学习和吸取教训才重要:
第一:做一个工程项目前,一定要设计和规划好项目,要明确达到什么功能,有目标的去做。
第二:一定要建好单独项目文件,不要混在一起,工程名尽量使用英文命名,中文命名有几率会使工程无法使用或出现故障。
第三:在使用多个模块时,要注意各个模块使用的引脚是否重复,例如:LED灯、蜂鸣器同时无法与12864液晶显示屏使用,可能是由于LED灯所使用的P2端口与12864的使能信号端、读/写选择端、数据/命令选择端冲突。
第四:使用模块时,要仔细辨认器件是否插入正确,若插反器件极易发烫、烧坏,损坏元器件。
第五:使用函数封装,程序简洁明了,使用简便。
项目:基于51单片机ds1302时钟、ds18b20的恒温器
所需模块:51单片机,STC15F2K60S2,DS1302时钟芯片,DS18B20温度传感器,LCD12864,矩阵按键,独立按键,蜂鸣器,LED
如图:
功能说明:
- 采用STC15F2K60S2芯片、DS1302时钟芯片、DS18B20温度传感器,LCD12864、独立按键,矩阵键盘。
- 开机进入第一界面,显示时间,作者。
- 第二界面显示实时温度,上下限,以及温度显示是否正常提示。
- 按下第三个独立按键则进入第三界面,显示时间,时间不会因为切换界面而从新开始,并可以后台提供温度报警。
运行流程:
①开机问候,时间显示在12864上,温度在上下限范围时仅亮三个led灯作为待机指示,当温度超出设定范围时则led全亮,蜂鸣器也开始响,开始声光报警。
②第一界面显示时间,可通过矩阵键盘调节年、月、日、时、分。(秒不必要调)按下第一个独立按键就跳到第二界面,采用DS18B20+12864显示温度和上下限值 。按下第三个独立按键跳回第一界面继续走时,即在第非时间显示界面时,时间在后台正常走。温度达到限值则触发流水灯闪亮与蜂鸣器鸣叫,同时在界面底部显示“温度超出范围”,温度在范围内则显示“温度稳定”。
③从新切回到时间界面时,温度仍然实时监测,只是在最后一行显示“温度超出范围”或“温度稳定”。
④时间,温度报警可以同时起作用。
效果展示:
(拍照太快,时间还没有显示)
(温度正常时)
(温度报警时)
(时间持续走)
供电方式:
USB直连或外接电池组。
用途:
家居日常
提高:
完成上述功能后,可以添加其他模块,如温湿度传感器,红外接收修改报警范围,以扩展恒温器用途与便捷性。
附:
/**************LCD12864上显示时钟、实时温度、报警温度上下限*************************
原创于河池学院OpenWRT无线路由组:小蔡
显示屏第一页为时钟,可用矩阵按键来控制年月日时分秒的值。
独立按键可以实现翻页功能,当由时钟页面跳到报警器页面时,时钟的值依旧跳动
第二页为温度报警器,可用独立按键调节温度上限,矩阵按键调节温度下限,
当温度高于上限值或者低于下限值时,显示屏出现“温度超出范围”,并拉响蜂鸣,LED灯闪烁以达到报警效果。
若温度正常,显示屏将显示“温度稳定”;
*********************************************************************************/
#include "DS18B20.H"
#include "LCD12864.H"
#include "DS1302.h"
#include <stdio.h>
uchar table1[]="当前温度 ";
uchar table2[]="上限值 度";
uchar table3[]="下限值 度";
uchar table4[]=" 温度超出范围 ";
uchar table5[]=" 温度稳定 ";
unsigned char Time_buf[8]={0x20,0x00,0x00,0x00,0x15,0x08,0x03,0x20};//年,秒,分,时,日,月,星期,年
sbit BUZZ = P1^1; //定义蜂鸣器引脚
sbit key1 = P3^2; //独立按键右一切换到温度显示界面
sbit key2 = P3^3; //上限加一
sbit key3 = P3^4; //左一切换到时间界面
sbit key4 = P3^5; //上限减一
/*================================================================================
按键调节时间
=================================================================================*/
void SetTime(void)
{
uint i;
switch(array()) //矩阵按键扫描
{
case 0: Time_buf[7] = Time_buf[7] + 0x01;break; //年+
case 1: Time_buf[5] = Time_buf[5] + 0x01;break; //月+
case 2: Time_buf[4] = Time_buf[4] + 0x01;break; //日+
case 8: Time_buf[3] = Time_buf[3] + 0x01;break; //时+
case 9: Time_buf[2] = Time_buf[2] + 0x01;break; //分+
case 4: Time_buf[7] = Time_buf[7] - 0x01;break; //年-
case 5: Time_buf[5] = Time_buf[5] - 0x01;break; //月-
case 6: Time_buf[4] = Time_buf[4] - 0x01;break; //日-
case 12:Time_buf[3] = Time_buf[3] - 0x01;break; //时-
case 13:Time_buf[2] = Time_buf[2] - 0x01;break; //分-
default:;
}
for( i = 0; i < 8;i++)
{
if( (Time_buf[i] & 0x0F) > 9)
{
Time_buf[i] = ((Time_buf[i]+0x10)&0xF0);
}
}
DS1302_Data_Input(DS1302_CONTROL_ADD,0x00); //关闭写保护
DS1302_Data_Input(DS1302_MIN_ADD,Time_buf[2]); //分
DS1302_Data_Input(DS1302_HR_ADD,Time_buf[3]); //时
DS1302_Data_Input(DS1302_DAY_ADD,Time_buf[4]); //日
DS1302_Data_Input(DS1302_MONTH_ADD,Time_buf[5]); //月
DS1302_Data_Input(DS1302_YEAR_ADD,Time_buf[7]); //年
DS1302_Data_Input(DS1302_CONTROL_ADD,0x80); //打开写保护
}
/*================================================================================
主函数
=================================================================================*/
void main()
{
unsigned char sec_buf = 0x00; //用来保存上一次的秒数
uint i,z;
int hight=27,low=25; //定义上限为27度,下限为20度。
uchar L, H;
init_12864(); //12864初始化
DS1302_Init(); //DS1302初始化
DS1302_Write_Time(); //初始化数据
print(4,0," 祝你生活愉快 ");
get: print(1,0," 年 月 日");
print(2,0," 时 分 秒");
print(3,0,"华人牌温度报警器");
/*----------------------------------------------------------------------------------
时间显示
----------------------------------------------------------------------------------*/
while(1)
{
DS1302_Read_Time();
SetTime(); //设定时间
if(Time_buf[1] != sec_buf) //当前时间与原来时间不同
{
sec_buf = Time_buf[1]; //把当前的秒数赋值给临时变量
display_int(1,0,ChangeTime(Time_buf[0]));
display_int(1,1,ChangeTime(Time_buf[7])); //年
display_int(1,3,ChangeTime(Time_buf[5])); //月
display_int(1,5,ChangeTime(Time_buf[4])); //日
display_int(2,1,ChangeTime(Time_buf[3])); //时
display_int(2,3,ChangeTime(Time_buf[2])); //分
display_int(2,5,ChangeTime(Time_buf[1])); //秒
}
if(key1 == 0)
{
init_12864();
break;//按下切换到温度显示界面
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
//作用: 将三行汉子固定显示,不刷新
display(1,0,&table1); //在第1行显示
display(2,0,&table2);
display(3,0,&table3);
/*----------------------------------------------------------------------------------
温度显示
----------------------------------------------------------------------------------*/
while(1)
{
Init_DS18B20(); //初始化DS18B20
Write_Byte(0xcc); //发送跳跃ROM指令
Write_Byte(0x44); //发送温度转换指令
Init_DS18B20(); //初始化DS18B20
Write_Byte(0xcc); //发送跳跃ROM指令
Write_Byte(0xbe); //读取DS18B20暂存器值
L = Read_Byte(); //读高速暂存器的byte0(低字节,二进制数)
H = Read_Byte(); //读高速暂存器的byte1(高字节,二进制数)
i = H; //低8位赋值给i
i <<= 8; // 低8位的数据整体左移8位
i |= L; // 高8位的数据填充低8位移走的空位,组成16位的二进制赋值给i
i = i * 0.0625 * 10 + 0.5; //读到的二进制数据转换温度的算法
LcdDisplay(i); //温度显示函数
LcdDisplay_hight(hight);
LcdDisplay_low(low);
if((i>=hight*10)|(i<=low*10)) //温度高于上限就报警
{
display(4,0,&table4);
for(z = 0;z<5;z++)
{
BUZZ = 0; //拉低蜂鸣器响
// P2=1;//会出错,啥原因暂不晓得....
Delay50ms();
BUZZ =~BUZZ;
// P2=~P2;//会出错,啥原因暂不晓得....
Delay50ms();
}
P2=1;
Delay50ms();
P2=~P2;
Delay50ms();
}
else
{
display(4,0,&table5);
}
//---------------------------------------------------------------------
//按键调上限
if(key2==0) //当key2按下一次时,上限温度加一,一直按一直加
{
hight++;
}
if(key4==0) //当key4按下一次时,上限温度减一,一直按一直减
{
hight--;
}
//-----------------------------------------------------------------------
//调下限
if(array()==11) //当key11按下一次时,下限温度加一,一直按一直加
{
low++;
}
if(array()==15) //当key15按下一次时,下限温度减一,一直按一直减
{
low--;
}
//--------------------------------------------------------------------
//跳回时间
if(key3 == 0)//按下切换到时间显示界面,但不初始化时间,接着开机时计算(后台走时)
{
init_12864 ();
goto get;
// break;
}
}
}
.........................
文章限制,需要请复制至网盘下载完整代码。