测温打铃是在单片机的基础上实现的一种温度报警装置。它可以通过自己设定报警温度,当温度传感器的温度达到报警温度发出报警声。(本项目添加生日快乐的报警音乐)有想法的可以自己动手实践,做一个真正的单片机实体项目。
电路图首先要了解需要哪些元件,我在本项目中添加了微调电容、外部晶振、温度传感器、LCD显示屏、排阻、三极管、蜂鸣器、AT89C52。下面是具体电路图。
代码注释很清晰,具体代码如下:
#include //头文件
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^0; //数据传输线接单片机的相应的引脚
sbit beepIO=P3^1; //接PNP型三极管
sbit RS = P3^2;//液晶接口,rs0命令,1数据;外部中断0
sbit RW = P3^3;//外部中断1
sbit E = P3^4;//液晶使能端E,控制信号输入端,下降沿使能
sbit k3 = P3^5;//k3开关,播放音量
sbit k2 = P3^6;//k2开关,温度上限减
sbit k1 = P3^7;//k1开关,温度上限加
float Temp;//温度
uint Temp_H = 60;//温度上限
unsigned char tempL=0; //设全局变量//用于温度进制转化
unsigned char tempH=0;
uchar bz1;//k3按下
uchar m,n;
uchar code T[49][2]={{0,0},//各个音调的初始值
{0xF8,0x8B},{0xF8,0xF2},{0xF9,0x5B},{0xF9,0xB7},{0xFA,0x14},{0xFA,0x66},{0xFA,0xB9},{0xFB,0x03},{0xFB,0x4A},{0xFB,0x8F},{0xFB,0xCF},{0xFC,0x0B},
{0xFC,0x43},{0xFC,0x78},{0xFC,0xAB},{0xFC,0xDB},{0xFD,0x08},{0xFD,0x33},{0xFD,0x5B},{0xFD,0x81},{0xFD,0xA5},{0xFD,0xC7},{0xFD,0xE7},{0xFE,0x05},
{0xFE,0x21},{0xFE,0x3C},{0xFE,0x55},{0xFE,0x6D},{0xFE,0x84},{0xFE,0x99},{0xFE,0xAD},{0xFE,0xC0},{0xFE,0x02},{0xFE,0xE3},{0xFE,0xF3},{0xFF,0x02},
{0xFF,0x10},{0xFF,0x1D},{0xFF,0x2A},{0xFF,0x36},{0xFF,0x42},{0xFF,0x4C},{0xFF,0x56},{0xFF,0x60},{0xFF,0x69},{0xFF,0x71},{0xFF,0x79},{0xFF,0x81}
};
uchar code music[][2]={{0,4},
{17,6},{17,2},{19,8},{17,8},{22,8},{21,16},
{17,6},{17,2},{19,8},{17,8},{24,8},{22,16},{17,6},{17,2},{29,8},{26,8},{22,8},{21,8},{19,8},{27,6},{27,2},{26,8},{22,8},{24,8},{22,16},
{0xFF,0xFF}};
/***********************************************************延时函数**********************************************************/
void delayms(uint x)
{
uchar i;
while(x--)for(i = 0; i < 120; i++);
}
void delay(unsigned char i)
{
for(i;i>0;i--);
}
/***********************************************************************液晶显示*******************************************/
//写指令
void Write_Order(uchar x)
{
delayms(1);
RS = 0;//低电平选择指令寄存器
RW = 0;//低电平写数据
P0 = x;//P0端口设为x
E = 1;//使能端高电平(下降沿,赋给传感器)
_nop_();//指令延时1us,延时一个机器周期
E = 0;//使能端低电平
/*让EN引脚从低电平到高电平变化,然后EN引脚再从高电平到低电平出现下降沿,
检测到下降沿后,就会读取D0~D7的数据*/
RW = 1;//高电平进行读操作
}
//写数据
void Write_Data(uchar x)
{
delayms(1);
RS = 1;//高电平选择数据寄存器
RW = 0;//低电平写数据
P0 = x;//P0端口设为x
E = 1;//使能端高电平
_nop_();//指令延时1us,延时一个机器周期
E = 0;//使能端低电平
RW = 1;//高电平进行读操作
}
//初始化LCD(液晶显示器)
void Init_1602(void)
{
Write_Order(0x38);//显示设置:8位数据接口,2行,16×2显示,5×7点阵
Write_Order(0x08);//显示关闭
Write_Order(0x01);//清屏(包含数据指针清零,所有显示清零)
Write_Order(0x06);//输入方式:光标右移,屏幕不动
Write_Order(0x0c);//整体显示,有光标,不闪烁
}
//显示一个字节
void Write_Byte(uchar x,uchar y,uchar dod)
{
if(x)
y |= 0x40;//逻辑"或"1000000(0x40),X=X|0x40, 即将X的第6位赋值为1。
y |= 0x80;//10000000(0x80),即将X的第7位,也就是最高位赋值为1。
Write_Order(y);//写y指令
Write_Data(dod);//写数据
}
//显示一个字符串
void Write_String(uchar x,uchar y,uchar *p)
{
uchar i = 0;
if(x == 0)y|=0x80;//将X的第7位,也就是最高位赋值为1。
if(x == 1)y|=0xc0;
if(x == 2)y|=0x94;
if(x == 3)y|=0xd4;
Write_Order(y);//写字符串指令y
while(p[i] != 0)
{
Write_Data(p[i++]);//写字符串数据p[i++]
}
}
//LCD显示字符
void Display(void)
{
uchar Buff[20];
sprintf(Buff,"Temp:%3.1f H%d ",Temp,Temp_H);//显示测试温度和报警上限温度
Write_String(0,0,Buff);//LCD显示字符串
}
/*************************************************************温度检测******************************************************/
//*******************************************************初始化程序 **********************************************************//
void Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
delay(8); //稍延时
DQ=0; //发送复位脉冲
delay(80); //延时(>480us)
DQ=1; //拉高数据线
delay(5); //等待(15~60us)
x=DQ; //用X的值来判断初始化有没有成功,18B20存在的话X=0,否则X=1
delay(20);
}
//**********读一个字节************//
ReadOneChar(void) //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
{
unsigned char i=0; //每个读周期最短的持续时间为60us,各个读周期之间必须有1us以上的高电平恢复期
unsigned char dat=0;
for (i=8;i>0;i--) //一个字节有8位
{
DQ=1; //DQ先置高
delay(1);
DQ=0;//发送复位脉冲
dat>>=1;
DQ=1; //拉高数据线
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
//*********************** **写一个字节**************************//
void WriteOneChar(unsigned char dat)
{
unsigned char i=0; //数据线从高电平拉至低电平,产生写起始信号。15us之内将所需写的位送到数据线上,
for(i=8;i>0;i--) //在15~60us之间对数据线进行采样,如果是高电平就写1,低写0发生。
{
DQ=0; //在开始另一个写周期前必须有1us以上的高电平恢复期。
DQ=dat&0x01;
delay(5);
DQ=1; //继续至高电平
dat>>=1;
}
delay(4);
}
//读温度值(低位放tempL;高位放tempH;)
void ReadTemperature(void)
{
int TempINT;
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0x44); //启动温度转换
delay(125); //转换需要一点时间,延时
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL=ReadOneChar(); //读出温度的低位LSB
tempH=ReadOneChar(); //读出温度的高位MSB
TempINT = tempH<<8|tempL;
Temp = TempINT*0.0625;
}
void CL(void)
{
ReadTemperature();//读温度值
}
/*********************************************************按键扫描********************************************************/
void keyscand()
{
if(k1==0)//k1开关按下,温度上限加
{
delayms(100);//延时
if(k1==0)//k1依然处于低电平状态
{
Temp_H++;//温度上限加1
bz1=0;
EA=0;
}
}
if(Temp_H==100)//如果温度上限等于100
{
Temp_H=50; //超过元件最大温度,至为50
}
if(k2==0)//k2开关按下,温度上限减
{
delayms(100);
if(k2==0)//k2依然处于低电平状态
{
Temp_H--;//温度上限减1
bz1=0;
EA=0;
}
}
if(Temp_H==0)//k3开关,播放音量
{
Temp_H=50;
}
}
/**********************************************BAOJING************************************************************/
void bj()//报警
{
if(Temp>Temp_H)//温度大于温度上限
{
beepIO=0;//蜂鸣器鸣叫
delayms(200);//超过上限报警
}
if(Temp<Temp_H)//温度小于温度上限
{
beepIO=1;//蜂鸣器关闭
}
}
//k3按键(播放音调)
void k3scand()
{
if(k3==0)//如果k3被按下
{
delayms(100);//延时
if(k3==0)
{
bz1++;
}
}
if(bz1==2)
{
bz1=0;
}//k3按下标志取值01
}
/********************************************************主函数***********************************************************/
//中断T0
void T0_int() interrupt 1
{
beepIO=!beepIO;
TH0=T[m][0];
TL0=T[m][1];
}
//主函数
void main()
{
uchar i=0;
TMOD=0x01; //开启定时器0,0x10时使用定时器,0x11时启动两个
EA=1;//开放所有中断
ET0=1; //允许T0中断
Init_1602();//初始化LCD(液晶显示器)
while(1)
{
k3scand();//k3按键
if(bz1==0)//k3未按下
{
EA=0;//关闭所有中断
CL();//读温度值
Display();//LCD显示温度
delayms(50);//延时
keyscand();//按键扫描
bj();//报警
}
if(bz1==1)//k3按下
{
EA=1;//开放所有中断
m=music[i][0];
n=music[i][1];
if(m==0x00)
{
TR0=0;//关闭定时器计数器0
delayms(n*100);
i++;
}
else if(m==0xFF)
{
TR0=0;//关闭定时器计数器0
delayms(30*100);
i=0;
}
else if(m==music[i+1][0])
{ TR0=1;//打开定时器计数器0
delayms(n*100);
TR0=0;
delayms(100);
i++;
}
else
{
TR0=1;//开放定时器计数器0
delayms(n*100);
i++;
}
}
}
}
链接: https://pan.baidu.com/s/1CFJgNWwhgXQfjJPz5pfX_w
提取码:64kl