|
主控芯片采用STM32F103RCT6,用18b20作為溫度傳感器,可以通過串口發送命令和當前溫度等信息。PI調節,使用PWM控制固態繼電器繼而控制加熱器通斷。
/******************************************
/********* 無線遙控溫度控制
/********* 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數據接口
sbit die=P1^0;
uchar tx[10]; //溫度結果儲存,0、1為整數位,其余小數
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參數
float e_k,e_k_1,e_k_2; //偏差,此刻,上一刻,上上一刻
uchar cmd_flag; //狀態標志量,與接收命令有關
uchar run; //運行狀態,為1則啟動溫控
//微秒級延時
void DelayUs(int num)
{
while(num--) ;
}
//毫秒級延時
void DelayMs(uint di) //延時
{
uint da,db;
for(da=0;da<di;da++)
for(db=0;db<100;db++);
}
//發送
void Print(uchar str)
{
//TR0=0;
SBUF=str;
while(!TI);
TI=0;
//TR0=1;
}
//PID計算程序
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復位
DelayUs(8); //稍做延時
dq = 0; //單片機將dq拉低
DelayUs(80); //精確延時 大于 480us
dq = 1; //拉高總線
DelayUs(14);
x=dq; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
if(x)
{
x=0;
}else
{
x=1;
}
DelayUs(20);
return x;
}
//串口初始化程序
void Init_Uart()
{
SCON = 0x52; //8bit無奇偶校驗
TMOD = 0x20; //Timer1設為8bit自動重裝模式
TCON=0x00;
PCON=0X00;
TH1 = TL1 = -(FOSC/12/32/BAUD); //定時器初值
TR1 = 1; //Timer1使能
RI=0;
TI=0;
ES = 1; //串口中斷使能
EA = 1; //總中斷使能
}
//定時器初始化程序
void InitTimer() //5毫秒
{
//AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0x01; //設置定時器模式
TL0 = 0x00; //設置定時初值
TH0 = 0xEE; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0 = 1;
}
//從DS18B20讀取一節數據
//返回值:讀到的數據
uchar ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
dq = 0; // 給脈沖信號
dat>>=1;
dq = 1; // 給脈沖信號
if(dq)
dat|=0x80;
DelayUs(4);
}
return(dat);
}
//對18b20寫一個字節
//參數:數據
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); // 跳過讀序號列號的操作
WriteOneChar(0x44); // 啟動溫度轉換
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器
a=ReadOneChar(); //讀低8位
b=ReadOneChar(); //讀高8位
tx[0] = (a/16+b*16)/10; //整數部分
tx[1] = (a/16+b*16)%10;
Data_L=a&0X0F;
for(num=3;num<7;num++) //小數部分
{
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命令,溫度設定值上升
if(temp_set<50)
{
temp_set++;
}else
{
temp_set=50;
}
cmd_flag=0;
break;
case 'D':
//down命令,溫度設定值下降
if(temp_set>20)
{
temp_set--;
}else
{
temp_set=20;
}
cmd_flag=0;
break;
case 'C':
//close命令,關閉加熱
run=0;
//P1=0XF0;
cmd_flag=0;
break;
case 'O':
//open命令,開啟加熱
run=1;
//P1=0X10;
cmd_flag=0;
break;
default:
cmd_flag=0;
break;
}
}
}
//串口中斷函數
void Get()interrupt 4
{
uchar dat;
//P1=0X0C;
if(RI)//接收到數據
{
die=0;
RI=0;
dat=SBUF;
switch (cmd_flag) //根據當前狀態采取不同措施
{
case 0:
//未接收到命令頭狀態
if(dat=='$')
//收到命令頭
{
cmd_flag=1;
}
break;
case 1:
//收到命令頭狀態
cmd=dat;
cmd_flag=2;
break;
case 2:
//準備收結束位
if(dat=='/')
{
cmd_flag=3;
}else
{
cmd_flag=0;
}
break;
default:
//無效狀態
cmd_flag=0;
break;
}
}
}
//定時中斷函數
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;
}
}
//主函數
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)//判斷是否需要啟動了加熱
{
die=!die; //指示燈閃爍
TR0=1;
Print('>'); //運行狀態
}else
{
die=0; //指示燈常亮
//TR0=0;
pwm_out=0;
Print('|'); //暫停狀態
}
//輸出當前溫度
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');
//輸出設定溫度
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 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
84.56 KB, 下載次數: 60, 下載積分: 黑幣 -5
|