本人做基于单片机的温度自动检测与控制系统,刚焊完硬件,但温度保持27.9℃保持不变,接上报警模块,蜂鸣器不停的响,调整温度上下限值后,仍然在不停的报警,是怎么回事?我是买的最小系统,其上面的晶振是11.0592KHZ,仿真是用12KHZ。
#include<intrins.h>
#include "1602.h"
#define uint unsigned int
#define uchar unsigned char
void delay_uint(uint q)
{
while(q--);
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_1602com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_1602data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_1602string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_1602com(0x80+add);
else
write_1602com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_1602data(*p);
p++;
}
}
/***********************lcd1602上显示特定的字符************************/
void write_1602zifu(uchar hang,uchar add,uchar date)
{
if(hang==1)
write_1602com(0x80+add);
else
write_1602com(0x80+0x40+add);
write_1602data(date);
}
/***********************lcd1602初始化设置************************/
void init_1602()
{
write_1602com(0x38);
write_1602com(0x0c);
write_1602com(0x06);
delay_uint(1000);
write_1602string(1,0,"Hello Everyboby");
write_1602string(2,1," Temp:");
}
#include <reg52.h> //调用单片机头文件
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
#include <intrins.h>
#include "eeprom52.h"
#include "1602.h"
#include "1302.h"
sbit dq = P3^6; //18b20 IO口的定义
sbit beep = P3^7; //蜂鸣器IO口定义
uint temperature ;
bit flag_300ms ;
bit key_500ms ;
uchar code table_num[]="0123456789abcdefg";
uchar menu_1; //菜单设计的变量
uint t_high =300,t_low = 100;
uchar tflag; //温度正负号标志位
uchar timeflag=1; //时间显示标志位
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<110;j++);
}
/******************把数据保存到单片机内部eepom中******************/
void write_eeprom() //保存数据
{
SectorErase(0x2000);
byte_write(0x2000, t_high%256);
byte_write(0x2001, t_high/256);
byte_write(0x2002, t_low%256);
byte_write(0x2003, t_low/256);
byte_write(0x2055, a_a);
}
/******************把数据从单片机内部eepom中读出来*****************/
void read_eeprom() //读出保存数据
{
t_high=byte_read(0x2001);
t_high<<=8;
t_high|=byte_read(0x2000);
t_low=byte_read(0x2003);
t_low<<=8;
t_low|=byte_read(0x2002);
a_a=byte_read(0x2055);
}
///**************开机自检eeprom初始化*****************/
void init_eeprom() ////开始初始化保存的数据
{
read_eeprom(); //读出保存数据
if(a_a !=1) //新的单片机初始单片机内问EEPROM
{
t_high=300;
t_low =100;
a_a =1;
write_eeprom(); //保存数据
}
}
/***********************lcd1602上显示两位十进制数************************/
void write_sfm3_18B20(uchar hang,uchar add,uint date)
{
if(hang==1)
write_1602com(0x80+add);
else
write_1602com(0x80+0x40+add);
write_1602data(0x30+date/100%10);
write_1602data(0x30+date/10%10);
write_1602data('.');
write_1602data(0x30+date%10);
}
/***********************18b20初始化函数*****************************/
void init_18b20()
{
bit q;
dq=1; //把总线拿高
delay_uint(1); //15us
dq=0; //给复位脉冲
delay_uint(80); //750us
dq=1; //把总线拿高 等待
delay_uint(10); //110us
q=dq; //读取18b20初始化信号
delay_uint(20); //200us
dq=1; //把总线拿高 释放总线
}
/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{ //写数据是低位开始
dq=0; //把总线拿低写时间隙开始
dq=dat&0x01; //向18b20总线写数据了
delay_uint(5); // 60us
dq=1; //释放总线
dat>>=1;
}
}
/*************读取18b20内的数据***************/
uchar read_18b20()
{
uchar i,value;
for(i=0;i<8;i++)
{
dq=0; //把总线拿低读时间隙开始
value>>=1; //读数据是低位开始
dq =1; //释放总线
if(dq==1) //开始读写数据
value|=0x80;
delay_uint(5); //60us 读一个时间隙最少要保持60us的时间
}
return value; //返回数据
}
/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
uint value;
uchar low; //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
init_18b20(); //初始化18b20
write_18b20(0xcc); //跳过64位ROM
write_18b20(0x44); //启动一次温度转换命令
delay_uint(75); //500us
init_18b20(); //初始化18b20
EA=0;
write_18b20(0xcc); //跳过64位ROM
write_18b20(0xbe); //发出读取暂存器命令
EA=1;
low=read_18b20(); //读温度低字节
value=read_18b20(); //读温度高字节
value<<=8; //把温度的高位左移8位
value|=low; //把读出的温度低位放到value的低八位中
value*=0.625; //转换到温度值 小数
if(value<0x0fff)
tflag=0;
else
{
value=~value+1;
tflag=1;
}
return value; //返回读出的温度 带小数
}
/*************定时器0初始化程序***************/
void time_init()
{
EA=1; //开总中断
TMOD=0X01; //定时器0、定时器1工作方式1
ET0=1; //开定时器0中断
TR0=1; //允许定时器0定时
}
/********************独立按键程序*****************/
uchar key_can; //按键值
void key() //独立按键程序
{
static uchar key_new;
key_can=20; //按键值还原
P1|=0xf0;
if(key_500ms==1) //连加
{
key_500ms=0;
key_new=1;
}
if((P1&0xf0)!=0xf0) //按键按下
{
delay_1ms(1); //按键消抖动
if(((P1&0xf0)!=0xf0) && (key_new==1))
{
key_new=0; //确认是按键按下
switch(P1&0xf0)
{
case 0xd0: key_can=3;break; //得到k1键值
case 0xb0: key_can=2;break; //得到K2键值
case 0x70: key_can=1;break; //得到k3键值
}
}
}
else
{
if(key_new==0)
{
key_new=1;
write_eeprom(); //保存数据
}
}
}
/****************按键显示函数***************/
void key_with()
{
if(key_can==1) //设置键
{
menu_1++;
if(menu_1>=5)
{
menu_1=0;
}
if(menu_1==0)
{
write_1602com(0x01);//清显示
timeflag=1;
init_1602();
}
}
if(menu_1==1)
{
write_1602com(0x01);//清显示
write_1602com(0x0c);
write_1602string(1,0,"20 - - ");
write_1602string(2,0," : : ");
timeflag=0;
timesetting();
}
if(menu_1==2)
{
write_1602com(0x01);//清显示
timeflag=1;
write_1602string(1,0,"Htemp: Ltemp:");
write_sfm3_18B20(2,1,t_high);
write_1602zifu(2,5,0xdf); //显示度
write_1602zifu(2,6,0x43);
write_sfm3_18B20(2,9,t_low);
write_1602zifu(2,13,0xdf); //显示度
write_1602zifu(2,14,0x43);
}
if(menu_1==3) //设置高温报警
{
if(key_can==2)
{
t_high+=10;
if(t_high>500)
t_high=500;
}
if(key_can==3)
{
t_high-=10; //温度减1
if(t_high<=t_low)
t_high=t_low+1;
}
write_sfm3_18B20(2,1,t_high); //显示高温报警温度
write_1602com(0x80+0x40+1); //将光标移动到秒个位
write_1602com(0x0f); //显示光标并且闪烁
write_eeprom(); //保存数据
}
if(menu_1==4) //设置低温报警
{
if(key_can==2)
{
t_low+=10; //温度加1
if(t_low>=t_high)
t_low=t_high-1;
}
if(key_can==3)
{
t_low-=10;
if(t_low<=10)
{
t_low=10;
}
}
write_sfm3_18B20(2,9,t_low);
write_1602com(0x80+0x40+0x09); //将光标移动到秒个位
write_1602com(0x0f); //显示光标并且闪烁
write_eeprom(); //保存数据
}
}
/********************菜单对应的处理函数***********************/
void menu_display()
{
if((menu_1==3)) //对光标不处理,要不然光标不会显示在正确的位置
{
write_1602com(0x80+0x40+0x01); //将光标移动到
write_1602com(0x0f); //显示光标并且闪烁
}else if((menu_1==4))
{
write_1602com(0x80+0x40+0x09); //将光标移动到
write_1602com(0x0f); //显示光标并且闪烁
}
}
/****************报警函数***************/
void clock_h_l()
{
static uchar value;
if((temperature<=t_low)||(temperature>=t_high))
{
value ++; //消除实际距离在设定距离左右变化时的干扰
if(value >=2)
{
beep =~beep; //蜂鸣器报警
}
}
else
{
beep=1;
}
}
/****************主函数***************/
void main()
{
beep=0; //开机叫一声
delay_1ms(150);
init_1602(); //1602初始化
temperature=read_temp(); //先读出温度的值
time_init(); //初始化定时器
init_eeprom(); //开机自检eeprom初始化
if(menu_1==4)
{
write_sfm3_18B20(1,2,t_high);
write_sfm3_18B20(1,10,t_low);
}
temperature=read_temp(); //先读出温度的值
write_sfm3_18B20(2,9,temperature);
while(1)
{
if(timeflag==0)
{
ds1302_init() ;
read1302();
}
if(menu_1==1)
{
timesetting();
}
if(flag_300ms==1) //300ms 处理一次温度程序
{
flag_300ms=0;
if(menu_1<2)
{
temperature=read_temp(); //先读出温度的值
if(tflag==1)
write_1602zifu(2,8,0x2d);
else
write_1602zifu(2,8,0x20);
write_sfm3_18B20(2,9,temperature);
write_1602zifu(2,13,0xdf); //显示度
write_1602zifu(2,14,0x43);
}
menu_display(); //不同级的菜单对应显示1602对应显示不同
}
key(); //按键程序
if(key_can<10)
{
key_with(); //设置报警温度
}
}
}
/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{
static uchar value;
TH0=0x3c;
TL0=0xb0; // 50ms
value++;
if(value%6==0)
{
flag_300ms=1; //300ms
value=0;
}
} |
|