#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
/********************LCD、键盘的引脚和变量定义***************************/
sbit lcden=P2^7;//LCD 使能引脚
sbit lcdrs=P2^5;//LCD 的 RS 脚
sbit lcdrw=P2^6;//LCD 的 RW 脚
sbit ledred=P1^6;
sbit ledgreen=P1^7;
sbit key0=P2^0;//加一
sbit key1=P2^1;//减一
sbit key2=P2^2;//加十
sbit key3=P2^3;//减十
//存放设定温度显示值
uchar set[4]={0};
uchar code str1[]="now temp:
uchar code str2[]="set temp:
uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
uchar n,num;
C";
C";
/********************PID 结构体、参数定义***************************/
struct PID
{
unsigned int SetPoint; // 设定目标
unsigned int Proportion; // 比例常数
unsigned int Integral; // 积分常数
unsigned int Derivative; // 微分常数
unsigned int LastError; // 本次偏差
unsigned int PrevError; // 上次偏差
unsigned int SumError; // 偏差和
};
struct PID spid; // PID
uint rin; // 反馈输入,rin 为传感器传回来的真实温度值,作为实参传给 PID 计算函数,rin =
tvalue/10;
uint rout; // 响应输出,存放 PID 计算结果,用于下一步 high_time 设置使用,rout = PIDCalc
( &spid,rin ); high_time=(unsigned char)(rout/800);
int set_temper=30;//初始设定温度变量定义
/********************PWM 输出引脚定义、占空比参数定义***************************/
sbit output=P1^0;//PWM 输出口
uchar high_time,low_time,count=0;//占空比调节参数
/********************DS18B20 引脚定义和参数定义***************************/
sbit DQ=P3^2;//ds18b20 与单片机连接口
int temper,temp; // 温 度 变 量 定 义 temper 为 真 实 温 度 , 用 于 温 度 比 较 函 数 时 使 用
if(set_temper>temper);temp 为扩大十倍的温度,temp 为 uint get_temper()的返回值
//float
f_temp;//转换后的温度
uint tvalue;// 用 于 计 算 DS18B20 先 后 传 回 来 的 低 八 位 和 高 八 位 的 温 度 值 的 和 ,
tvalue=b;tvalue<<=8;tvalue=tvalue|a; 最 后 温 度 值 扩 大 10 倍 , 精 确 到 1 位 小 数
tvalue=tvalue*(0.625);
uchar tflag;//温度正负标志
/*************************LCD 程序****************************/
void delay(i)//延时函数
{
uint j;
for(i;i>0;i--)
for(j=110;j>0;j--);
}
void wr_com(uchar ml)//写命令
{
lcdrs=0;//RS=0 写指令,RS=1 写数据
P0=ml;
delay(5);
lcden=1;//使能信号,1 时读信息,1>0(下降沿)执行指令
delay(5);
lcden=0;//使能信号,1 时读信息,1>0(下降沿)执行指令
}
void wr_data(uchar shuju)//写数据
{
lcdrs=1;//RS=0 写指令,RS=1 写数据
//lcden=1;
P0=shuju;
delay(5);
lcden=1;//使能信号,1 时读信息,1>0(下降沿)执行指令
delay(5);
lcden=0;//使能信号,1 时读信息,1>0(下降沿)执行指令
}
void LCD_init()
{
//按照时序操作的初始化
lcdrw=0;//0 时向 LCD 写指令或数据,1 时从 LCD 读取信息
wr_com(0x38);//显示模式设置,设置为 16*2 显示,5*7 点阵,八位数据口
wr_com(0x0c);//开显示,但不开光标,光标不闪
wr_com(0x06);//显示光标移动设置
wr_com(0x01);// 清屏
wr_com(0x80);
for(num=0;num<16;num++)
// 数据指针初始化
{
}
wr_data(str1[num]);//now temp 显示"now temp:
C"
wr_com(0x80+0x40); //地址初始化
for(num=0;num<16;num++)
{
}
}
wr_data(str2[num]);//set temp 显示"set temp:
C"
/*************************DS1820 程序****************************/
void delay_18B20(unsigned int i)//延时 1 微秒
{
while(i--);
}
void ds1820rst(void)/*ds1820 复位*/
{
//DQ 复位
unsigned char x=0;
DQ = 1;
delay_18B20(4); //延时
DQ = 0;
TR0=0;
delay_18B20(100); //精确延时大于
TR0=1;
DQ = 1;
delay_18B20(40);
//DQ 拉低
//拉高
}
uchar ds1820rd(void)/*读数据*/
{
uchar i=0;
uchar dat = 0;
TR0=0;
for (i=8;i>0;i--)
{
DQ = 0; //给脉冲信号
dat>>=1; //先传的是低位值,所以需要右移
DQ = 1; //给脉冲信号
if(DQ)//如果 DQ 返回来的是 1,则让 dat 加数字 1,也就是 dat=dat|0x80
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata)/*写数据*/
{
unsigned char i=0;
TR0=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
uint get_temper()//获取温度
{
uchar a,b;
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd();
b=ds1820rd();
//低八位
//高八位
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
TR0=1;
if(tvalue<0x0fff)
else {tvalue=~tvalue+1;tflag=1;}//温度为负数,取补码
tvalue=tvalue*(0.625);//温度值扩大 10 倍,精确到 1 位小数
temp=tvalue;//温度值扩大 10 倍,精确到 1 位小数
return temp;
tflag=0;//温度为正数
}
void dis_temp(int t)//显示温度
{
uchar d0,d1,d2,d3;
//t=26;
if(tflag==0)
{
LCD 显示需要让得出的数的高位加上 0011 即 0x30
d0=t/1000+0x30;//百位
d1=t%1000/100+0x30;//十位
d2=t%100/10+0x30;//个位
d3=t%10+0x30;//小数一位
if(d0==0x30)//若温度没有超过一百度,则不显示百位
{
wr_com(0x80+9);
wr_data(d1); //显示十位
wr_com(0x80+10);
wr_data(d2); //显示个位
wr_com(0x80+11);
wr_data(0x2e); //显示小数点
wr_com(0x80+12);
wr_data(d3); //显示第一位小数
}
else
{
//显示百位
//显示十位
wr_com(0x80+9);
wr_data(d0);
wr_com(0x80+10);
wr_data(d1);
wr_com(0x80+11);
wr_data(d2);
wr_com(0x80+12);
wr_data(' ');
//显示个位
}
} //正温度显示
else
{
wr_com(0x80+9);
wr_data('-');
wr_com(0x80+10);
wr_data(d1);
wr_com(0x80+11);
wr_data(d2);
wr_com(0x80+12);
wr_data(' ');
//wr_com(0x80+12);
//wr_data(d3);
}//负温度显示
wr_com(0x80+14);
wr_data(0xdf); //显示摄氏温度的那个小圆圈。
temper=t/10; //get_temper()得到的 temp 传给参数 t,而其值为真实温度值的十倍 用
于温度比较时使用 if(set_temper>temper)
}
/*************************键盘程序****************************/
void keyscan()//键盘扫描
{
if(key0==0)
{
delay(1); //消抖
if(key0==0)
{
while(!key0); //若按键没松开则不执行下面的程序
delay(1);//消抖
while(!key0);
set_temper++;//设置温度加一
spid.SetPoint =set_temper;
}
set[0]=set_temper/10; //获得设置温度显示值
set[1]=set_temper%10;
set[2]=spid.SetPoint/10;
set[3]=spid.SetPoint%10;
wr_com(0x80+0x40+9);
wr_data(table[set[0]]);
delay(1);
wr_com(0x80+0x40+10);
wr_data(table[set[1]]);
delay(1);
//wr_com(0x80+0x40+11);
//wr_data(0x2e);
//wr_com(0x80+0x40+14);
//wr_data(0xdf);
delay(1);
wr_com(0x80+0x40+12);
wr_data(table[set[2]]);
delay(1);
wr_com(0x80+0x40+13);
wr_data(table[set[3]]);
delay(1);
//显示设置温度
//显示设置温度
}
if(key1==0)
{
delay(3);//延时去抖
if(key1==0)
{
while(!key1);
delay(3);
while(!key1);
set_temper--;//温度减
if(set_temper==0)
{set_temper=0;}
spid.SetPoint =set_temper;
}
set[0]=set_temper/10; //获得设置温度显示值
set[1]=set_temper%10;
set[2]=spid.SetPoint/10;
set[3]=spid.SetPoint%10;
//显示设置温度值
wr_com(0x80+0x40+9);
wr_data(table[set[0]]);
delay(1);
wr_com(0x80+0x40+10);
wr_data(table[set[1]]);
delay(1);
//wr_com(0x80+0x40+11);
//wr_data(0x2e);