一个单片机爱好者将本网一个温度测量和电饭煲程序文件合成,不进入各种模式操作正常,进入后死机,文件如下。请指出那错并改正一下,不胜感激。
#include <reg52.h>
#include<intrins.h>
#define uint unsigned int
#define ulong unsigned long
#define uchar unsigned char //宏定义
sbit DQ = P3^7; //定义DS18B20总线I/O
#define LCD_DB P0 //定义LCD数据口
sbit LCD_RS=P2^1;
sbit LCD_RW=P1^5;
sbit LCD_E=P1^6;
void delay_n40us(uint n); //函数申明
uint ReadTemperature(void); //函数申明
void Delay_DS18B20(int num); //函数申明
void LCD_SramChar(uchar hang,uchar lie,char sign);
void LCD_WriteString(uchar hang,uchar lie,uchar *p);
//单片机电饭煲程序
//#include "includes.h"
uint temp;
uint count;
uint hour,minute,sec,oldsec=0;
uint hour1=0,minute1=0,sec1=0; //时,分,秒
sbit green = P1^0; //工作指示灯
sbit red = P1^1; //停止指示灯
sbit Cook = P1^7; //速煮米饭
sbit Soup = P1^4; //精煮米饭
sbit congee = P2^3; //煮粥
sbit Stewed = P2^0; //煲汤
sbit KeepHeat = P3^3; //保温
sbit menu = P3^2; //时间预约
sbit add = P3^4; //加
sbit dec = P3^5; //减
sbit Beep = P1^2; //蜂鸣器
sbit AddTemp = P1^3; //加热
uint ModeFlag;
unsigned char mode;
void KeepTemp(void);
//********延时函数***************
void delay_n40us(uint n)
{ uint i;
uchar j;
for(i=n;i>0;i--)
for(j=0;j<2;j++); //在这个延时循环函数中我只做了2次循环,
}
//**********写入LCD指令**********写入命令****************
void LCD_write_command(uchar dat)
{
LCD_RS=0; //指令
LCD_RW=0; //写入
LCD_DB=dat;
LCD_E=1; //允许
delay_n40us(1);//实践证明,LCD1602 上,用for 循环1 次就能完成普通写指令。
LCD_E=0; //产生下降沿
}
//*******************************
//********再写数据函数*****向1602中写入数据********
void LCD_write_data(uchar dat)
{
LCD_RS=1; //数据
LCD_RW=0; //写入
LCD_DB=dat;
LCD_E=1; //允许
delay_n40us(1);
LCD_E=0; //产生下降沿
}
//************8LCD初始化**************
void LCD_init(void) //LCD_Initial();
{
LCD_write_command(0x01); //清除屏幕显示----------------
delay_n40us(100);//实践证明,LCD1602上,用for 循环200 次就能可靠完成清屏指令。
LCD_write_command(0x38); //设置8位格式,2行,5x7
LCD_write_command(0x06); //设定输入方式,增量不移位--------------
LCD_write_command(0x0c); //整体显示,关光标,不闪烁
LCD_E=0; //产生下降沿
}
/********************************************************************
* 名称 : L1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,
调用该函数如下 L1602_char(1,5,'b')
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void LCD_SramChar(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
// enable(a);
LCD_write_command(a);
// write(sign);
LCD_write_data(sign);
}
/********************************************************************
* 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位开始的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,
调用该函数如下 L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void LCD_WriteString(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
LCD_write_command(a);
// enable(a);
while(1)
{
if(*p == '\0') break;
// write(*p);
LCD_write_data(*p);
p++;
}
}
//************15us延时子程序
void Delay_DS18B20(int num)
{
while(num--) ;
}
//***********初始化DS18B20
void Init_DS18B20(void)
{
bit q;
//DQ = 1; //把总线拿高
//Delay_DS18B20(1); //15us
DQ = 0; //给复位脉冲
Delay_DS18B20(80); //750us
DQ = 1; //把总线拿高 等待
Delay_DS18B20(8); //120us
q = DQ; //读取18b20初始化信号
Delay_DS18B20(30); //等待450us确保初始化成功
DQ = 1; //把总线拿高 释放总线
}
//***********从1820读一个字节
uchar ReadOneChar(void)
{
unsigned char i=0;
uchar dat=0;
for (i=8;i>0;i--)
{
bit x;
dat>>=1; // 右移一位
DQ = 0; // 给复位脉冲信号
DQ = 1; // 拉高电平确实读给脉冲信号
x=DQ; // 读总线输出一位数据
if(x)
dat|=0x80; // 高电平保存数据
Delay_DS18B20(5); //等待75us
}
return (dat); //返回读出的十进制数据
}
//*********向1820写一个字节
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0; //给复位脉冲信号
DQ = dat&0x01; //写入一位数据
Delay_DS18B20(5); //等待75微妙确保数据写入
DQ = 1; //释放总线为高电平
dat>>=1;
}
}
//读取温度
uint ReadTemperature(void)
{
uchar a=0;
uint t=0;
Init_DS18B20();
Delay_DS18B20(50);
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0x44); //启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
a=ReadOneChar(); //读低8位
t=ReadOneChar(); //读高8位
t <<= 8; //高8位左移
t|=a; //高8位左移与低8位相或得到温度值
t=t*0.0625*10+0.5; //接近真实温度
//Delay_DS18B20(60);
return(t);
}
//延时子程序
/*void Delay(int num)
{
while( --num ); //此函数没有调用
}
*/
//显示温度子程序
/*void Disp_Temperature(void) //显示温度
{
uint h;
int feng,ge,shi,bai;
LCD_init(); //LCD初始化
LCD_write_command(0x80);//第一行写入数据
LCD_write_data('T'); //写T 连续写地址自动+1
delay_n40us(15000); //延迟
LCD_write_data('e');
delay_n40us(15000);
LCD_write_data('m');
delay_n40us(15000);
LCD_write_data('p');
delay_n40us(15000);
LCD_write_data(':');
delay_n40us(15000);
h= ReadTemperature();
if(h<=0x07d0) //判断温度为正
{
h*=0.625;
bai=h/1000;
feng=h%10;
ge=h/10%10;
shi=h/100;
LCD_write_command(0x80+5); //从第一行第六个开始显示
LCD_write_data(0x30+bai);
delay_n40us(15000);
LCD_write_command(0x80+6);
LCD_write_data(0x30+shi);
delay_n40us(15000);
LCD_write_data(0x30+ge);
delay_n40us(15000);
LCD_write_data('.');
delay_n40us(15000);
LCD_write_data(0x30+feng);
delay_n40us(15000);
}
else //温度为负时
{
h=h-1; //减1取反
h=(~h);
h*=0.625;
feng=h%10;
ge=h/10%10;
shi=h/100;
LCD_write_command(0x80+5);
LCD_write_data('-');
delay_n40us(15000);
LCD_write_data(0x30+shi);
delay_n40us(15000);
LCD_write_data(0x30+ge);
delay_n40us(150000);
LCD_write_data('.');
delay_n40us(1500);
LCD_write_data(0x30+feng);
delay_n40us(15000);
}
//*************显示C*************
LCD_write_command(0x80+10); //共11位
LCD_write_data('C');
delay_n40us(15000);
} */
//主函数
/*void main(void)
{
Init_DS18B20();
while(1)
{
Disp_Temperature();
}
}
*/
/*******************************************
****** 延时程序 ******
*******************************************/
void delay_ms(unsigned char ms) // 延时毫秒@12M,ms最大值255
{
unsigned char i;
while(ms--)
for(i = 0; i < 5; i++);
}
void delay00(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*******************************************
****** 设置工作模式 ******
*******************************************/
void SetMode()
{
if(Cook == 0) //速煮米饭
{
delay_ms(5);
while(!Cook);
sec = 0;
minute = 0;
count = 0;
ModeFlag = 1;
}
else if(Soup == 0) //精煮米饭
{
delay_ms(5);
while(!Soup);
sec = 0;
minute = 0;
count = 0;
ModeFlag = 2;
}
else if(KeepHeat == 0) //保温
{
delay_ms(5);
while(!KeepHeat);
sec = 0;
minute = 0;
count = 0;
ModeFlag = 5;
}
else if(congee == 0) //煮粥
{
delay_ms(5);
while(!congee);
sec = 0;
minute = 0;
count = 0;
ModeFlag = 3;
}
else if(Stewed == 0) //煲汤
{
delay_ms(5);
while(!Stewed);
sec = 0;
minute = 0;
count = 0;
ModeFlag = 4;
}
}
/*******************************************
****** 速煮米饭部分 ******
*******************************************/
void CookRice(void) //速煮米饭
{
LCD_WriteString(1,1,"Cook Rice"); //指定位置开始写入字符串
//delay00(800);
AddTemp = 0; //开始加热
green = 1;
red= 0;
Cook= 0;
if(temp >= 300) //超过50度
{
TR0 = 1;
if(sec!=oldsec)
{
oldsec=sec;
LCD_SramChar(1,11,(3 - minute)%100/10+0x30); //4分钟
LCD_SramChar(1,12,(3 - minute)%10+0x30);
LCD_SramChar(1,13,':'); //指定位置写入字符
LCD_SramChar(1,14,(59 - sec)%100/10+0x30);
LCD_SramChar(1,15,(59 - sec)%10+0x30);
}
}
else
TR0 = 0;
if((1- minute) == 0 && (59 - sec) == 0)
{
TR0 = 0; //这里要和上面的函数相同来控制工作时间
AddTemp = 1;
green = 0;
red = 1;
Cook = 1;
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
ModeFlag=5; //保温
}
}
/*******************************************
****** 精煮米饭部分 ******
*******************************************/
void CookCong(void)
{
LCD_WriteString(1,1,"Cook Cong");
//delay00(800);
AddTemp = ~AddTemp; //开始加热
green = 1;
red = 0;
//Soup = 0;
if(temp >= 500) //超过50度
{
TR0 = 1;
if(sec!=oldsec)
{
oldsec=sec;
LCD_SramChar(1,12,(6 - minute)%100/10+0x30); //7分钟
LCD_SramChar(1,13,(6 - minute)%10+0x30);
LCD_SramChar(1,14,':');
LCD_SramChar(1,15,(59 - sec)%100/10+0x30);
LCD_SramChar(1,16,(59 - sec)%10+0x30);
}
}
else
TR0 = 0; //&&(逻辑与)运算符&&会先评估第一个值,如果为假则不评估第二个值
if((1 - minute) == 0 && (59 - sec) == 0)
{
TR0 = 0;
AddTemp = 1;
green = 0;
red =1;
//Soup = 1;
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
ModeFlag=5;
}
}
/*******************************************
****** 煮粥部分 *******
*******************************************/
void CookSoup(void) //煮粥
{
LCD_WriteString(1,1,"Cook Soup");
delay00(200);
AddTemp = ~AddTemp; //开始加热
//congee = 0;
green = 1;
red = 0;
if(temp >= 450) //超过45度
{
TR0 = 1;
if(sec!=oldsec)
{
oldsec=sec;
LCD_SramChar(1,12,(3 - minute)%100/10+0x30); //工作4 分钟
LCD_SramChar(1,13,(3 - minute)%10+0x30);
LCD_SramChar(1,14,':');
LCD_SramChar(1,15,(59 - sec)%100/10+0x30);
LCD_SramChar(1,16,(59 - sec)%10+0x30);
}
}
else
TR0 = 0;
if((1 - minute) == 0 && (59 - sec) == 0)
{
TR0 = 0;
AddTemp = 1;
green = 0;
red = 1;
//congee = 1;
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
//KeepTemp();
ModeFlag=5;
}
}
/*******************************************
****** 煲汤部分 ******
*******************************************/
void Stewedsoup(void) //煲汤
{
LCD_WriteString(1,1,"Stew soup");
AddTemp = ~AddTemp; //开始加热
delay00(800);
green = 1;
red = 0;
//Stewed = 0; //时间不相等才执行
if(temp >= 400) //超过40度
{
TR0 = 1;
if(sec!=oldsec)
{
oldsec=sec;
LCD_SramChar(1,12,(5 - minute)%100/10+0x30); //6分钟
LCD_SramChar(1,13,(5 - minute)%10+0x30);
LCD_SramChar(1,14,':');
LCD_SramChar(1,15,(59 - sec)%100/10+0x30);
LCD_SramChar(1,16,(59 - sec)%10+0x30);
}
}
else
TR0 = 0;
if((1 - minute) == 0 && (59 - sec) == 0)
{
TR0 = 0;
AddTemp = 1;
green = 0;
red = 1;
//Stewed = 1;
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
Beep = 0;delay00(200);Beep = 1;delay00(200);
ModeFlag=5;
}
}
/*******************************************
****** 保温部分 *******
*******************************************/
void KeepTemp(void)
{
LCD_WriteString(1,1,"Keep Temp"); //9个字符位
AddTemp = 0; //开始加热
green = 1;
red= 0;
if(temp >= 300) //超过60度 测温放大了10倍
{
AddTemp = 1; //停止加热
green = 0;
red=1;
}
else if(temp <= 200) //开始加热 30度
{
AddTemp = 0;
green = 1;
red=0;
}
}
/*******************************************
****** 按键部分 ******
*******************************************/
void key_scan()
{
unsigned char s1num=0; //修改后在下面行
if(menu==0)
{
delay00(50);
if(menu==0)
{
while(!menu);
s1num++;
// command(0x01);
LCD_write_command(0x01); //清除屏幕显示
TR0 = 0; hour=0;minute=0;sec=0;
while(1)
{
if(menu==0)
{
delay00(50);
if(menu==0)
{
while(!menu);
s1num++;
}
}
if(s1num==1)
{
LCD_WriteString(2,1,"Set Mode:");
LCD_SramChar(2,10,mode/10+0x30);
LCD_SramChar(2,11,mode%10+0x30);
if(add==0)
{
delay00(30);
if(add==0)
{ while(!add);
mode ++;
if(mode >= 5)
mode = 0;
LCD_SramChar(2,10,mode/10+0x30);
LCD_SramChar(2,11,mode%10+0x30);
}
}
if(dec==0)
{
delay00(30);
if(dec==0)
{ while(!dec);
if(mode == 0)
mode = 5;
mode --;
LCD_SramChar(2,10,mode/10+0x30);
LCD_SramChar(2,11,mode%10+0x30);
}
}
}
if(s1num==2)
{
LCD_WriteString(2,0,"Set hour:");
LCD_SramChar(2,10,hour1/10+0x30);
LCD_SramChar(2,11,hour1%10+0x30);
if(add==0)
{
delay00(30);
if(add==0)
{ while(!add);
hour1 ++;
if(hour1 == 12)
hour1 = 0;
LCD_SramChar(2,10,hour1/10+0x30);
LCD_SramChar(2,11,hour1%10+0x30);
}
}
if(dec==0)
{
delay00(30);
if(dec==0)
{ while(!dec);
if(hour1 == 0)
hour1 = 12;
hour1 --;
LCD_SramChar(2,10,hour1/10+0x30);
LCD_SramChar(2,11,hour1%10+0x30);
}
}
}
if(s1num==3)
{
LCD_WriteString(2,0,"Set minute:");
LCD_SramChar(2,12,minute1/10+0x30);
LCD_SramChar(2,13,minute1%10+0x30);
if(add==0)
{
delay00(30);
if(add==0)
{ while(!add);
minute1 ++;
if(minute1 == 60)
minute1 = 0;
LCD_SramChar(2,12,minute1/10+0x30);
LCD_SramChar(2,13,minute1%10+0x30);
}
}
if(dec==0)
{
delay00(30);
if(dec==0)
{ while(!dec);
if(minute1 == 0)
minute1 = 60;
minute1 --;
LCD_SramChar(2,12,minute1/10+0x30);
LCD_SramChar(2,13,minute1%10+0x30);
}
}
}
if(s1num == 4)
{
s1num=0; //s1num清零//
// command(0x01); //清屏
LCD_write_command(0x01); //清除屏幕显示
delay_n40us(1);
ModeFlag = 6;
AddTemp = 1;
TR0 = 1;
break;
}
}
}
}
}
/*******************************************
****** 显示预约剩余时间部分 ******
*******************************************/
void SetTime(void)
{
LCD_SramChar(1,1,(hour1 - hour)%100/10+0x30);//hour1 是设定的时间,hour是正常走的时间
LCD_SramChar(1,2,(hour1 - hour)%10+0x30);
LCD_SramChar(1,3,':');
if((minute1-minute)>0)
{
LCD_SramChar(1,4,(minute1 - 1 - minute)%100/10+0x30);
LCD_SramChar(1,5,(minute1 - 1 - minute)%10+0x30);
}
else
{
LCD_SramChar(1,4,'0');
LCD_SramChar(1,5,'0');
}
LCD_SramChar(1,6,':');
if(((hour1 - hour)>0)||((minute1-minute)>0))
{
LCD_SramChar(1,7,(59 - sec)%100/10+0x30);
LCD_SramChar(1,8,(59 - sec)%10+0x30);
}
else
{
LCD_SramChar(1,7,'0');
LCD_SramChar(1,8,'0'); //以上是本函数倒计时显示,归0后显选择的模式
}
LCD_WriteString(1,10," "); //每种模式的工作时长填充到这里,不到0显剩余时间
if((minute1 - 1 - minute) == 0 && (59 - sec) == 0 &&(hour1 - hour) == 0)
{
TR0 = 0;Beep = 0;delay00(200);Beep = 1;
ModeFlag = mode;
hour=0;minute=0;sec=0;
}
}
/*******************************************
****** 主函数 ******
*******************************************/
void main()
{
EA = 1;
TMOD = 0X01;
ET0 = 1;
TH0 = 0X3C;
TL0 = 0XB0;
Beep = 1;
AddTemp = 1;
// LCD_Initial(); //LCD_init 上面的
LCD_init();
Init_DS18B20();
delay_ms(100);
temp = ReadTemperature(); //uint ReadTemperature() 上面的
//delay_ms(100); //在ASCII码表中,0x30是十六进制表示法,对应于十进制的48,它代表的字符是数字"0"。
while(1)
{
temp = ReadTemperature(); //读取温度
//Disp_Temperature();
LCD_WriteString(2,1,"NowTemp="); //修改后开机显示在下面行
LCD_SramChar(2,9,temp%10000/1000+0x30);
LCD_SramChar(2,10,temp%1000/100+0x30);
LCD_SramChar(2,11,temp%100/10+0x30);
LCD_SramChar(2,12,'.');
LCD_SramChar(2,13,temp%10+0x30);
LCD_SramChar(2,14,'C'); //不能写0行0列的,本工程函数
SetMode();
key_scan(); //以上这些项目预约倒计时归0后才显示出来
switch(ModeFlag) //模式选择
{
case 1: CookRice();break;
case 2: CookCong();break;
case 3: CookSoup();break;
case 4: Stewedsoup();break;
case 5: KeepTemp();break;
case 6: SetTime();break;
}
}
}
/*******************************************
****** 定时器定时部分 ******
*******************************************/
void t0() interrupt 1
{
TH0 = 0X3C;
TL0 = 0XB0;
count ++;
if(count >= 20)
{
count = 0;
sec ++;
if(sec == 60)
{
sec = 0;
minute ++;
if(minute == 60)
hour ++;
}
}
}
|