|
#include <at89x51.h>
#include <absacc.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <DS18B20.h>
#include "LCD1602.h" ////液晶顯示頭文件
#define uchar unsigned char
#define uint unsigned int
sbit Key1=P1^0;
sbit Key2=P1^1;
sbit Up =P1^2;
sbit Down=P1^3;
uchar t[2],*pt; //這是用來存放溫度值的,測溫程序通過這個數(shù)組與主函數(shù)通信
uchar TempBuffer1[9]={0x2b,0x31,0x32,0x32,0x2e,0x30,0x30,0x43,'\0'};
//顯示實時的溫度,上電時顯示+125.00C
uchar TempBuffer0[17]={0x54,0x48,0x3a,0x2b,0x31,0x32,0x35,0x20,
0x54,0x4c,0x3a,0x2b,0x31,0x32,0x34,0x43,'\0'};
//顯示溫度上下限,上電時顯示TH:+125 TL:+124C
uchar code dotcode[4]={0,25,50,75};
uchar set;//溫度初始值
uchar count,high_time=0; //調(diào)節(jié)占空比的參數(shù)
uint rout;// PID輸出
/查表法*******
將表值分離出的十位和個位送到十分位和百分位********************/
struct PID
{
uint SetPoint; // 設(shè)定目標 Desired Value
uint Proportion; // 比例常數(shù) Proportional Const
uint Integral; // 積分常數(shù) Integral Const
uint Derivative; // 微分常數(shù) Derivative Const
signed int LastError; // 錯誤Error[-1]
signed int PrevError; // 錯誤Error[-2]
signed int SumError; // Sums of Errors
};
struct PID spid; // PID控制結(jié)構(gòu)體
void init_pid()
//PID初始化
{
high_time=50;
spid.Proportion = 23; // Set PID Coefficients
spid.Integral = 2;
spid.Derivative =6;
spid.SetPoint = set; // Set PID Setpoint
}
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
//PID算法
{
signed int dError,Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 積分
dError = pp->LastError - pp->PrevError; // 當前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error+ pp->Integral * pp->SumError + pp->Derivative * dError);
}
void duty_cycle(uint t)
// 占空比
{
uchar s;
t=t/10;
s=set;
if(s>t)
{
if(s-t>2)
high_time=100;
else
{
rout = PIDCalc ( &spid,t ); // Perform PID Interation
if(high_time<=100)
high_time=(uchar)(rout/600);
else
high_time=100;
}
}
else
high_time=0;
}
void covert0( unsigned char TH, unsigned char TL) //將溫度上下限轉(zhuǎn)換為LCD顯示的數(shù)據(jù)
{
if(TH>0x7F) //判斷正負,如果為負溫,將其轉(zhuǎn)化為其絕對值
{
TempBuffer0[3]=0x2d; //0x2d為"-"的ASCII碼
TH=~TH;
TH++;
}
else TempBuffer0[3]=0x2b; //0x2B為"+"的ASCII碼
if(TL>0x7f)
{
TempBuffer0[11]=0x2d; //0x2d為"-"的ASCII碼
TL=~TL+1;
}
else
TempBuffer0[11]=0x2b; //0x2B為"+"的ASCII碼
TempBuffer0[4]=TH/100+0x30; //分離出TH的百十個位
if( TempBuffer0[4]==0x30)
TempBuffer0[4]=0xfe; //百位數(shù)消隱
TempBuffer0[5]=(TH%100)/10+0x30; //分離出十位
TempBuffer0[6]=(TH%100)%10+0x30; //分離出個位
TempBuffer0[12]=TL/100+0x30; //分離出TL的百十個位
if( TempBuffer0[12]==0x30)
TempBuffer0[12]=0xfe; //百位數(shù)消隱
TempBuffer0[13]=(TL%100)/10+0x30; //分離出十位
TempBuffer0[14]=(TL%100)%10+0x30; //分離出個位
}
void covert1(void) //將溫度轉(zhuǎn)換為LCD顯示的數(shù)據(jù)
{
unsigned char x=0x00,y=0x00;
t[0]=*pt;
pt++;
t[1]=*pt;
if(t[1]>0x07) //判斷正負溫度
{
TempBuffer1[0]=0x2d; //0x2d為"-"的ASCII碼
t[1]=~t[1]; /*下面幾句把負數(shù)的補碼*/
t[0]=~t[0]; /* 換算成絕對值*********/
x=t[0]+1; /***********************/
t[0]=x; /***********************/
if(x>255) /**********************/
t[1]++; /*********************/
}
else
TempBuffer1[0]=0x2b; //0xfe為變"+"的ASCII碼
t[1]<<=4; //將高字節(jié)左移4位
t[1]=t[1]&0x70; //取出高字節(jié)的3個有效數(shù)字位
x=t[0]; //將t[0]暫存到X,因為取小數(shù)部分還要用到它
x>>=4; //右移4位
x=x&0x0f; //和前面兩句就是取出t[0]的高四位
t[1]=t[1]|x; //將高低字節(jié)的有效值的整數(shù)部分拼成一個字節(jié)
TempBuffer1[1]=t[1]/100+0x30; //+0x30 為變 0~9 ASCII碼
if( TempBuffer1[1]==0x30)
TempBuffer1[1]=0xfe; //百位數(shù)消隱
TempBuffer1[2]=(t[1]%100)/10+0x30; //分離出十位
TempBuffer1[3]=(t[1]%100)%10+0x30; //分離出個位
t[0]=t[0]&0x0c; //取有效的兩位小數(shù)
t[0]>>=2; //左移兩位,以便查表
x=t[0];
y=dotcode[x]; //查表換算成實際的小數(shù)
TempBuffer1[5]=y/10+0x30; //分離出十分位
TempBuffer1[6]=y%10+0x30; //分離出百分位
}
void delay(unsigned int i)
{
while(i--);
}
void t0_int(void) interrupt 1 //PWM波輸出
{
if(++count<=(high_time))
Relay=0;
else if(count<=100)
Relay=1;
else
count=0;
TH0=0X20;
TL0=0X00;
}
main()
{
unsigned char TH=50,TL=10,temp=0; //下一步擴展時可能通過這兩個變量,調(diào)節(jié)上下限
//測溫函數(shù)返回這個數(shù)組的頭地址
TMOD=0X01;
TH0=0X20;
TL0=0X00;
EA=1;
ET0=1;
TR0=1;
set=60;//目標溫度
Beep=0;Relay=0;
init_pid();
while(1)
{
if(Up==0)
{
while(!Up);
TH++;
}
if(Down==0)
{
while(!Down);
TL--;
}
pt=ReadTemperature(TH,TL,0x3f); //上限溫度-22,下限-24,分辨率10位,也就是0.25C
//讀取溫度,溫度值存放在一個兩個字節(jié)的數(shù)組
if((t[1]>TH)|(t[1]<TL))
{
Beep=1;
// Relay=1;
}
else
{
Beep=0;
// Relay=0;
}
delay(10000);
covert1();
covert0(TH,TL);
LCD_Initial(); //第一個參數(shù)列號,第二個為行號,為0表示第一行
//為1表示第二行,第三個參數(shù)為顯示數(shù)據(jù)的首地址
LCD_Print(0,0,TempBuffer0);
LCD_Print(0,1,TempBuffer1);
}
}
|
-
仿真圖
-
-
測試1.rar
2018-5-30 19:53 上傳
點擊文件名下載附件
98.41 KB, 下載次數(shù): 25
|