|
主控芯片采用STM32F103RCT6,用18b20作為溫度傳感器,可以通過(guò)串口發(fā)送命令和當(dāng)前溫度等信息。PI調(diào)節(jié),使用PWM控制固態(tài)繼電器繼而控制加熱器通斷。
/******************************************
/********* 無(wú)線遙控溫度控制
/********* MCU:STC89C52
* ******* 溫度傳感器:18b20
* 控制方法:PID控制
* 串口命令格式'\0x04'+命令+'\0x05'
*****************************************/
#include <reg51.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200L //晶振頻率
#define BAUD 9600 //串口波特率
#define PWMPERIOD 100 //周期,*5ms
#define OPEN 1
#define CLOSE 0
sbit pwm_out=P1^2; //pwm輸出口
sbit dq = P0^1; //18b20數(shù)據(jù)接口
sbit die=P1^0;
uchar tx[10]; //溫度結(jié)果儲(chǔ)存,0、1為整數(shù)位,其余小數(shù)
uchar temp_now;
//float temp_now_dec;
float temp_set;
uchar cmd;
uchar time_length;
uchar duty_ratio;
//float duty;
float kp,ki,kd; //pid參數(shù)
float e_k,e_k_1,e_k_2; //偏差,此刻,上一刻,上上一刻
uchar cmd_flag; //狀態(tài)標(biāo)志量,與接收命令有關(guān)
uchar run; //運(yùn)行狀態(tài),為1則啟動(dòng)溫控
//微秒級(jí)延時(shí)
void DelayUs(int num)
{
while(num--) ;
}
//毫秒級(jí)延時(shí)
void DelayMs(uint di) //延時(shí)
{
uint da,db;
for(da=0;da<di;da++)
for(db=0;db<100;db++);
}
//發(fā)送
void Print(uchar str)
{
//TR0=0;
SBUF=str;
while(!TI);
TI=0;
//TR0=1;
}
//PID計(jì)算程序
void CalculatePID()
{
char u_add;
e_k_2=e_k_1;
e_k_1=e_k;
e_k=temp_set-temp_now;
//u_add=(kp+ki+kd)*e_k-(kp+2*kd)*e_k_1+kd*e_k_2;
u_add=kp*e_k-kp*e_k_1;
// duty=duty-u_add;
// if(duty>1)
// {
// duty=1;
// }else if(duty<0)
// {
// duty=0;
// }
// duty_ratio=PWMPERIOD*duty;
duty_ratio=u_add+duty_ratio;
if(duty_ratio>=PWMPERIOD)
{
duty_ratio=PWMPERIOD;
}
Print('D');
Print(duty_ratio/100+48);
Print(duty_ratio%100/10+48);
Print(duty_ratio%10+48);
Print('\n');
}
//ds18b20初始化程序
//返回值:1初始化成功,0失敗
uchar Init_DS18B20(void)
{
uchar x=0;
dq = 1; //dq復(fù)位
DelayUs(8); //稍做延時(shí)
dq = 0; //單片機(jī)將dq拉低
DelayUs(80); //精確延時(shí) 大于 480us
dq = 1; //拉高總線
DelayUs(14);
x=dq; //稍做延時(shí)后 如果x=0則初始化成功 x=1則初始化失敗
if(x)
{
x=0;
}else
{
x=1;
}
DelayUs(20);
return x;
}
//串口初始化程序
void Init_Uart()
{
SCON = 0x52; //8bit無(wú)奇偶校驗(yàn)
TMOD = 0x20; //Timer1設(shè)為8bit自動(dòng)重裝模式
TCON=0x00;
PCON=0X00;
TH1 = TL1 = -(FOSC/12/32/BAUD); //定時(shí)器初值
TR1 = 1; //Timer1使能
RI=0;
TI=0;
ES = 1; //串口中斷使能
EA = 1; //總中斷使能
}
//定時(shí)器初始化程序
void InitTimer() //5毫秒
{
//AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式
TMOD &= 0x01; //設(shè)置定時(shí)器模式
TL0 = 0x00; //設(shè)置定時(shí)初值
TH0 = 0xEE; //設(shè)置定時(shí)初值
TF0 = 0; //清除TF0標(biāo)志
TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
ET0 = 1;
}
//從DS18B20讀取一節(jié)數(shù)據(jù)
//返回值:讀到的數(shù)據(jù)
uchar ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
dq = 0; // 給脈沖信號(hào)
dat>>=1;
dq = 1; // 給脈沖信號(hào)
if(dq)
dat|=0x80;
DelayUs(4);
}
return(dat);
}
//對(duì)18b20寫一個(gè)字節(jié)
//參數(shù):數(shù)據(jù)
void WriteOneChar(unsigned char dat)
{
uchar i=0;
for (i=8; i>0; i--)
{
dq = 0;
dq = dat&0x01;
DelayUs(2);
dq = 1;
dat>>=1;
}
}
//讀取溫度
void ReadTemperature(void)
{
uchar a=0;
uchar b=0;
uchar Data_L=0;
uchar num=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳過(guò)讀序號(hào)列號(hào)的操作
WriteOneChar(0x44); // 啟動(dòng)溫度轉(zhuǎn)換
Init_DS18B20();
WriteOneChar(0xCC); //跳過(guò)讀序號(hào)列號(hào)的操作
WriteOneChar(0xBE); //讀取溫度寄存器
a=ReadOneChar(); //讀低8位
b=ReadOneChar(); //讀高8位
tx[0] = (a/16+b*16)/10; //整數(shù)部分
tx[1] = (a/16+b*16)%10;
Data_L=a&0X0F;
for(num=3;num<7;num++) //小數(shù)部分
{
Data_L=Data_L*10;
tx[num]=Data_L/16;
Data_L=Data_L%16;
}
temp_now=(uchar)(tx[0*10+tx[1]);
//temp_now_dec=tx[0]*10+tx[1]+tx[3]*0.1+tx[4]*0.01;
}
//處理命令
void DealCMD()
{
if(cmd_flag==3)
{
switch (cmd)
{
case 'U':
//up命令,溫度設(shè)定值上升
if(temp_set<50)
{
temp_set++;
}else
{
temp_set=50;
}
cmd_flag=0;
break;
case 'D':
//down命令,溫度設(shè)定值下降
if(temp_set>20)
{
temp_set--;
}else
{
temp_set=20;
}
cmd_flag=0;
break;
case 'C':
//close命令,關(guān)閉加熱
run=0;
//P1=0XF0;
cmd_flag=0;
break;
case 'O':
//open命令,開(kāi)啟加熱
run=1;
//P1=0X10;
cmd_flag=0;
break;
default:
cmd_flag=0;
break;
}
}
}
//串口中斷函數(shù)
void Get()interrupt 4
{
uchar dat;
//P1=0X0C;
if(RI)//接收到數(shù)據(jù)
{
die=0;
RI=0;
dat=SBUF;
switch (cmd_flag) //根據(jù)當(dāng)前狀態(tài)采取不同措施
{
case 0:
//未接收到命令頭狀態(tài)
if(dat=='$')
//收到命令頭
{
cmd_flag=1;
}
break;
case 1:
//收到命令頭狀態(tài)
cmd=dat;
cmd_flag=2;
break;
case 2:
//準(zhǔn)備收結(jié)束位
if(dat=='/')
{
cmd_flag=3;
}else
{
cmd_flag=0;
}
break;
default:
//無(wú)效狀態(tài)
cmd_flag=0;
break;
}
}
}
//定時(shí)中斷函數(shù)
void Time()interrupt 1
{
time_length++;
if(time_length>=PWMPERIOD)
{
ReadTemperature();
if(run)
{
pwm_out=OPEN;
time_length=0;
CalculatePID();
}
}else if (time_length>=duty_ratio)
{
pwm_out=CLOSE;
}
}
//主函數(shù)
int main()
{
IP=0x10;
InitTimer();
Init_Uart();
Init_DS18B20();
time_length=0;
duty_ratio=0;
e_k=0;
e_k_1=0;
e_k_2=0;
// duty=0;
temp_set=30;
time_length=0;
kp=1;
ki=0;
kd=0;
run=1;
while(1)
{
DealCMD();
if(run)//判斷是否需要啟動(dòng)了加熱
{
die=!die; //指示燈閃爍
TR0=1;
Print('>'); //運(yùn)行狀態(tài)
}else
{
die=0; //指示燈常亮
//TR0=0;
pwm_out=0;
Print('|'); //暫停狀態(tài)
}
//輸出當(dāng)前溫度
Print('N');
// Print('=');
// Print(temp_now/10+48);
// Print(temp_now%10+48);
// Print('.');
// Print((int)(temp_now_dec*10)+48);
// Print((int)(temp_now_dec*100)%10+48);
Print(tx[0+'0');
Print(tx[1+'0');
Print('.');
Print(tx[3+'0');
Print(tx[4+'0');
Print(',');
//Print('\n');
//輸出設(shè)定溫度
Print('S');
// Print('=');
Print((int)temp_set/10+48);
Print((int)temp_set%10+48);
Print('\r');
Print('\n');
DelayMs(200);
}
return 0;
}
|
-
-
USER.7z
2019-7-21 19:01 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
84.56 KB, 下載次數(shù): 60, 下載積分: 黑幣 -5
|