|
|
51单片机温度PID控制程序1602显示
以下是部分代码
- /******************************************************************
- Main.C file
- 作者:颜强
- 建立日期: 2011.12.23
- 版本:V1.0
- Copyright(C) bg8wj
- /*******************************************************************/
- #include "ioconfig.h"
- #include "includes.h"
- #include "datacomm.h"
- /************************************************
- PID函数
- *************************************************/
- void PIDInit (struct PID *pp)
- {
- memset ( pp,0,sizeof(struct PID));
- }
- /************************************************
- 增量控制PID函数体
- 51单片机最不擅长浮点数计算,转换成int型计算
- *************************************************/
- unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
- {
- unsigned int dError,Error,pError;
- //增量法计算公式:
- //Pdt=Kp*[E(t)-E(t-1)]+Ki*E(t)+Kd*[E(t)-2*E(t-1)+E(t-2)]
- Error = set_temper - NextPoint; // 偏差E(t)
- pError=Error-pp->LastError; //E(t)-E(t-1)
- dError=Error-2*pp->LastError+pp->PrevError; //E(t)-2*E(t-1)+E(t-2)
- pp->PrevError = pp->LastError;
- pp->LastError = Error;
- return (
- pp->Proportion * pError //比例
- + pp->Integral *Error //积分项
- + pp->Derivative * dError // 微分项
- );
- }
- /************************************************
- PID函数初始化
- *************************************************/
- void PIDBEGIN()
- {
- PIDInit(&spid); // Initialize Structure
- spid.Proportion = 10; // Set PID Coefficients
- spid.Integral = 5;
- spid.Derivative =4;
- }
- /************************************************
- 实时温度读取函数
- 从DS18b20中读取实时温度
- 返回值放大10倍便于PID计算
- *************************************************/
- int ReadTemperature(void)
- {
- unsigned char TPL=0;
- unsigned char TPH=0;
- unsigned int temperture=0;
- //EA = 0;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
- TPL=ReadOneChar(); //读温度低字节
- TPH=ReadOneChar(); //读温度高字节
- //启动下一次温度转换
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳过读序号列号的操作
- WriteOneChar(0x44); // 启动温度转换
- //temperture=(TPH*256+TPL)*0.0625 //真实温度值 范围(+125,-55)
- if(TPH&0xfc)
- {
- tp_flag=1; //负温度标记
- temperture=((TPH<<8)|TPL);
- temperture=((~temperture)+1);
- temperture*=0.625+0.5;
- }
- else
- {
- tp_flag=0;
- //temperture=((TPH<<8)|TPL)*0.0625 //温度输出值范围(125.00,-55.00)
- temperture=((TPH<<8)|TPL)*0.625+0.5;//温度值放大10倍 范围(+1250.00,-550.00)
- } // +0.5四舍五入 精度只到小数后一位
- return(temperture);
- }
- /************************************************
- lcd1602显示函数
- *************************************************/
- void xianshi(void)
- {
- LCD_Write_String(0,0,"NOW TMP:");
- LCD_Write_String(0,1,"SET TMP:");
- }
- /************************************************
- lcd1602显示实时温度
- *************************************************/
- void view(unsigned int tmp)
- {
- LCD_Write_Char(15,0,'C');
- LCD_Write_Char(14,0,0xdf);//摄氏温度符号
- LCD_Write_Char(13,0,zhi[tmp%10]);//小数点后第1位
- LCD_Write_Char(12,0,'.');
- LCD_Write_Char(11,0,zhi[tmp%100/10]);// 个位
- LCD_Write_Char(10,0,zhi[tmp/100]); //十位
- if(0==tmp/1000)LCD_Write_Char(9,0,' ');//百位 如果为零显示空格
- else
- LCD_Write_Char(9,0,zhi[tmp/1000]);
- if(1==tp_flag)LCD_Write_Char(8,0,'-');//正负温度符号显示 负温度显示- 0上显示空格
- else
- LCD_Write_Char(8,0,' ');
- }
- /***********************************************************
- PID温度控制做动函数
- ***********************************************************/
- void compare_temper() //PID温度控制输出函数
- {
- unsigned char i;
-
- if(set_temper>temper)
- {
- if(set_temper-temper>50)//如果控制目标温度温与实时温度差大于5度,(放大10倍)是50
- {
-
- PWM0_set(10); //PWM 输出高电平占空比最大。即全速加温
- PWM1_set(10);
- }
- else
- {
- for(i=0;i<10;i++) //5度范围内PID增量控制,10次周期 即PID积分式中T=10
- {
- rin=ReadTemperature();//PID输入实时温度采样值
- rout = PIDCalc ( &spid,rin ); // PID增量输出
- }//PID增量输出范围(0-255)配合pwm取值范围
- send_string_com("pid out:"); //串口输出监视数据
- send_char_com(rin); //实时温度值
- send_char_com(rout);//PID增量输出值
- send_char_com(0x0d);//输出回车,换行间隔控制字符
- send_char_com(0x0a);//
-
- if(rout>=240)rout=240; //保障PWM输入值10-240 防止pwm出现失调。stc单片机特性。
- if(rout<=20)rout=20;
-
- PWM0_set(255-rout);
- PWM1_set(255-rout);
-
- }
- }
- else if(set_temper<=temper) //目标温度小于实时温度pwm输出低电平最高占空比,关闭加热。
- {
- PWM0_set(250);
- PWM1_set(250);
- }
- }
- /************************************************
- 系统初始化函数
- *************************************************/
- void Sys_Init()
- {
- PWM_init();
- PIDBEGIN();
- LCD_Init();
- Init_DS18B20();
- LCD_Clear();
- InitUart1();
- }
- /*************************************************
- 主函数
- **************************************************/
- void main(void)
- {
- Sys_Init(); //系统初始化
- xianshi(); //显示字符
- PWM0_set(250); //初始化PWM两路输出最高低电平占空比,不要加热
- PWM1_set(250);
- delay500ms(); //延时稍等芯片初始化
- while(1)
- {
- EA=0;
- k=KeyPro(); //键盘扫描
- if(k!=0xff)
- {
- if(k==15){i=0;shu[0]=0;shu[1]=0;shu[2]=0;shu[3]=0;}
- else{shu[i]=k;i++;if(i>3)i=0;}//键值15对应清除设定温度显示及数组为0
- }
- if(k==14)//键值14键 置入设定温度并确定 输入格式xxx+确定键 第一位是百度 为0需要输入0
- {
- EA=1;
- set_temper=1000*(shu[0])+100*shu[1]+10*shu[2];
- compare_temper(); //启动PID温度控制作动函数
- }
- LCD_Write_Char(15,1,'C'); //显示设定温度值百位为0时 显示空格 但是输入必须输入0
- LCD_Write_Char(14,1,0xdf); //温标符号
- LCD_Write_Char(13,1,zhi[0]);
- LCD_Write_Char(12,1,'.');
- LCD_Write_Char(11,1,zhi[shu[2]]);
- LCD_Write_Char(10,1,zhi[shu[1]]);
-
- if(shu[0]==0)LCD_Write_Char(9,1,' ');
- else LCD_Write_Char(9,1,zhi[shu[0]]);
-
- if(counter-- == 0) //温度联系读5次
- {
- temper=ReadTemperature();
- counter =5;
- }
- view(temper); //温度显示;
- if(!set_temper==0)compare_temper();//只有设置目标温度后才启动PID温控作动函数
- }
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|