一個單片機愛好者將本網一個溫度測量和電飯煲程序文件合成,不進入各種模式操作正常,進入后死機,文件如下。請指出那錯并改正一下,不勝感激。
#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 ++;
}
}
}
|