51单片机温度PID算法(C程序)

发布者:RadiantGlow最新更新时间:2018-10-05 来源: eefocus关键字:51单片机  温度PID算法 手机看文章 扫描二维码
随时随地手机看文章

#include "reg51.h"


#include "intrins.h"


#include "math.h"


#include "string.h"


struct PID 



unsigned int SetPoint; // 设定目标 Desired Value 


unsigned int Proportion; // 比例常数 Proportional Const 


unsigned int Integral; // 积分常数 Integral Const 


unsigned int Derivative; // 微分常数 Derivative Const 


unsigned int LastError; // Error[-1] 


unsigned int PrevError; // Error[-2] 


unsigned int SumError; // Sums of Errors 


}; 


struct PID spid; // PID Control Structure 


unsigned int rout; // PID Response (Output) 


unsigned int rin; // PID Feedback (Input) 


sbit data1=P1^0; 


sbit clk=P1^1; 


sbit plus=P2^0; 


sbit subs=P2^1; 


sbit stop=P2^2; 


sbit output=P3^4; 


sbit DQ=P3^3; 


unsigned char flag,flag_1=0; 


unsigned char high_time,low_time,count=0;//占空比调节参数 


unsigned char set_temper=25; 


unsigned char temper; 


unsigned char i; 


unsigned char j=0; 


unsigned int s; 

 

void delay(unsigned char time) 



unsigned char m,n; 


for(n=0;n


for(m=0;m<2;m++){} 


 


void write_bit(unsigned char bitval) 



EA=0; 


DQ=0;  


if(bitval==1) 



_nop_(); 


DQ=1;  



delay(5);  


DQ=1;  


_nop_(); 


_nop_(); 


EA=1; 


 


void write_byte(unsigned char val) 



unsigned char i; 


unsigned char temp; 


EA=0; 


TR0=0; 


for(i=0;i<8;i++)  



temp=val>>i;  


temp=temp&1; 


write_bit(temp);  



delay(7);  


// TR0=1; 


EA=1; 


 


unsigned char read_bit() 



unsigned char i,value_bit; 


EA=0; 


DQ=0;  


_nop_(); 


_nop_(); 


DQ=1;  


for(i=0;i<2;i++){} 


value_bit=DQ; 


EA=1; 


return(value_bit); 


 


unsigned char read_byte() 



unsigned char i,value=0; 


EA=0; 


for(i=0;i<8;i++) 



if(read_bit())  


value|=0x01<


delay(4);  



EA=1; 


return(value); 


 

unsigned char reset() 



unsigned char presence; 


EA=0; 


DQ=0;  


delay(30);  


DQ=1;  


delay(3); 


presence=DQ;  


delay(28);  


EA=1; 


return(presence);  


 

void get_temper() 



unsigned char i,j; 


do 



i=reset();  


} while(i!=0);  


i=0xcc;  


write_byte(i); 


i=0x44;  


write_byte(i); 


delay(180);  


do 



i=reset();  


} while(i!=0); 


i=0xcc;  


write_byte(i); 


i=0xbe;  


write_byte(i); 


j=read_byte(); 


i=read_byte(); 


i=(i<<4)&0x7f; 


s=(unsigned int)(j&0x0f); //得到小数部分 


s=(s*100)/16; 


j=j>>4; 


temper=i|j;  


 


void PIDInit (struct PID *pp) 



memset ( pp,0,sizeof(struct PID)); //全部初始化为0 


 


unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) 



unsigned 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 compare_temper() 



unsigned char i; 


if(set_temper>temper) //是否设置的温度大于实际温度 



if(set_temper-temper>1) //设置的温度比实际的温度是否是大于1度 



high_time=100; //如果是,则全速加热 


low_time=0; 



else //如果是在1度范围内,则运行PID计算 



for(i=0;i<10;i++) 



get_temper(); //获取温度 


rin = s; // Read Input 


rout = PIDCalc ( &spid,rin ); // Perform PID Interation 



if (high_time<=100) 


high_time=(unsigned char)(rout/800); 


else 


high_time=100; 


low_time= (100-high_time); 




else if(set_temper<=temper) 



if(temper-set_temper>0) 



high_time=0; 


low_time=100; 



else 



for(i=0;i<10;i++) 



get_temper(); 


rin = s; // Read Input 


rout = PIDCalc ( &spid,rin ); // Perform PID Interation 



if (high_time<100) 


high_time=(unsigned char)(rout/10000); 


else 


high_time=0; 


low_time= (100-high_time); 




// else 


// {} 


 


void serve_T0() interrupt 1 using 1 



if(++count<=(high_time)) 


output=1; 


else if(count<=100) 



output=0; 



else 


count=0; 


TH0=0x2f; 


TL0=0xe0; 


 


void serve_sio() interrupt 4 using 2 


 




void disp_1(unsigned char disp_num1[6]) 



unsigned char n,a,m; 


for(n=0;n<6;n++) 



// k=disp_num1[n]; 


for(a=0;a<8;a++) 



clk=0; 


m=(disp_num1[n]&1); 


disp_num1[n]=disp_num1[n]>>1; 


if(m==1) 


data1=1; 


else 


data1=0; 


_nop_(); 


clk=1; 


_nop_(); 




 

void display() 


unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; 


unsigned char disp_num[6]; 


unsigned int k,k1; 


k=high_time; 


k=k00; 


k1=k/100; 


if(k1==0) 


disp_num[0]=0; 


else 


disp_num[0]=0x60; 


k=k0; 


disp_num[1]=number[k/10]; 


disp_num[2]=number[k]; 


k=temper; 


k=k0; 


disp_num[3]=number[k/10]; 


disp_num[4]=number[k]+1; 


disp_num[5]=number[s/10]; 


disp_1(disp_num); 


 

void main() 



unsigned char z; 


unsigned char a,b,flag_2=1,count1=0; 


unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2}; 


TMOD=0x21; 


TH0=0x2f; 


TL0=0x40; 


SCON=0x50; 


PCON=0x00; 


TH1=0xfd; 


TL1=0xfd; 


PS=1; 


EA=1; 


EX1=0; 


ET0=1; 


ES=1; 


TR0=1; 


TR1=1; 


high_time=50; 


low_time=50; 


PIDInit ( &spid ); // Initialize Structure 


spid.Proportion = 10; // Set PID Coefficients 比例常数 Proportional Const 


spid.Integral = 8; //积分常数 Integral Const 


spid.Derivative =6; //微分常数 Derivative Const 


spid.SetPoint = 100; // Set PID Setpoint 设定目标 Desired Value 


while(1) 




if(plus==0) 



EA=0; 


for(a=0;a<5;a++) 


for(b=0;b<102;b++){} 


if(plus==0) 



set_temper++; 


flag=0; 




else if(subs==0) 



for(a=0;a<5;a++) 


for(b=0;a<102;b++){} 


if(subs==0) 



set_temper--; 


flag=0; 




else if(stop==0) 



for(a=0;a<5;a++) 


for(b=0;b<102;b++){} 


if(stop==0) 



flag=0; 


break; 



EA=1; 



get_temper(); 


b=temper; 


if(flag_2==1) 


a=b; 


if((abs(a-b))>5) 


temper=a; 


else 


temper=b; 


a=temper; 


flag_2=0; 


if(++count1>30) 



display(); 


count1=0; 



compare_temper(); 



TR0=0; 


z=1; 


while(1) 



EA=0; 


if(stop==0) 



for(a=0;a<5;a++) 


for(b=0;b<102;b++){} 


if(stop==0) 


disp_1(phil); 


// break; 



EA=1; 



}


关键字:51单片机  温度PID算法 引用地址:51单片机温度PID算法(C程序)

上一篇:12864液晶显示原理(C程序)
下一篇:单片机万年历DS1302时钟芯片的应用

推荐阅读最新更新时间:2024-03-16 16:14

51单片机常见的7种时钟电路介绍
在MCS-51单片机片内有一个高增益的反相放大器,反相放大器的输入端为XTAL1,输出端为XTAL2,由该放大器构成的振荡电路和时钟电路一起构成了单片机的时钟方式。根据硬件电路的不同,单片机的时钟连接方式可分为内部时钟方式和外部时钟方式,如下图所示。 时钟电路:(a)内部方式时钟电路,(b)外接时钟电路 在内部方式时钟电路中,必须在XTAL1和XTAL2引脚两端跨接石英晶体振荡器和两个微调电容构成振荡电路,通常C1和C2一般取30pF,晶振的频率取值在1.2MHz~12MHz之间。对于外接时钟电路,要求XTAL1接地,XTAL2脚接外部时钟,对于外部时钟信号并无特殊要求,只要保证一定的脉冲宽度,时钟频率低于12MHz
[单片机]
<font color='red'>51单片机</font>常见的7种时钟电路介绍
51单片机程序执行流程详细分析
单片机是没有上操作系统的东西,在keil中编写的代码都是裸机代码,深入编写裸机代码有助于了解硬件的特性。 若不是硬件特性已定的情况之下的其它流程都是代码作祟。忽然想到来探探51单片机的执行流程。这个念头起源于最初见到每个51程序里面的主函数里面最终都挂一个while(1);语句。为何要加一句while死循环让程序停留在main函数中呢。将while(1);语句去掉有什么影响么? 写一个很简单的程序试一下。 执行以上程序,由P1端口控制的流水灯闪了一下。程序最终进入while(1);里纠缠去了,这个到好解释。 现将while(1);语句屏蔽掉。我还以为程序不能被正确执行了呢,因为退出了main主函数,就像Render需要
[单片机]
<font color='red'>51单片机</font>程序执行流程详细分析
51单片机制作简易电风扇定时控制器
自己的床头风扇的机械定时器坏掉了,准备51单片机给设计了一个.程序在实验板初步调试通过,等待元件寄到就可以做板子了,只是有点浪费单片机的资源。 一,设计思路: 开始通过手动键给单片机供电。直到电源指示灯LED4亮.单片机运行,继电器2工作给单片机供电。通过按键设置继电器2的工作时间,实现系统的自动断电,通过设置继电器1的工作时间,实现风扇的间歇转动,实现节能。 1. 显示部分:通过按键,在风扇转动时间,暂停时间,和系统关闭剩余时间切换显示。数码显示两位,为“分”走时,其中系统关闭剩余时间为“小时”走时,LED为红,黄,蓝,分别点亮对应的风扇转动,暂停,和系统关闭剩余时间的状态。 2. 按键部分: lK1为时间调整移位键,按
[单片机]
<font color='red'>51单片机</font>制作简易电风扇定时控制器
基于51单片机温度报警器
本数字温度报警器是基于51单片机及温度传感器DS18B20来设计的,温度测量范围0到99.9摄氏度,精度为0.1摄氏度,可见测量温度的范围广,精度高的特点。可设置上下限报警温度,默认上限报警温度为38℃、默认下限报警温度为5℃(通过程序可以更改默认上下限值)。报警值可设置范围:最低上限报警值等于当前下限报警值,最高下限报警值等于当前上限报警值。将下限报警值调为0时为关闭下限报警功能。 程序 /*****定时器0中断服务程序*****/ void timer0(void) interrupt 1 { TH0=0x3c; TL0=0xb0; x++; } /*****外部中断0服务程序*****/ void int0(void)
[单片机]
基于<font color='red'>51单片机</font>的<font color='red'>温度</font>报警器
51单片机引脚的详细资料介绍
AT89C2051是精简版的51单片机,精简掉了P0口和P2口,只有20引脚,但其内部集成了一个很实用的模拟比较器,特别适合开发精简的51应用系统,毕竟很多时候我们开发简单的产品时用不了全部32个I/O口,用AT89C2051更合适,芯片体积更小,而且AT89C2051的工作电压最低为2.7V,因此可以用来开发两节5号电池供电的便携式产品。 本文以ATMEL公司生产的51系列家族的AT89S51和AT89C2051两种单片机来讲解,两种单片机是目前最常用的单片机,其中AT89S51为标准51单片机,当然其功能比早期的51单片机更强大,支持ISP在系统编程技术,内置硬件看门狗。。。 一、AT89S51单片机引脚介绍 AT89
[单片机]
<font color='red'>51单片机</font>引脚的详细资料介绍
关于51单片机不能正常起振的原因
如何确定晶振正常起振? 1、判断方法很多,用示波器看波形是最直接的,用数字万用表的电压档测电压也行,因晶振波形的占空比为50%,所以测得的平均电压为1/2Vcc左右,对于51单片机,在使用外置程序存储器的时候还可以测PSEN引脚或P0口引脚的电压或波形,只有晶振电路正常工作,那些引脚才会有信号输出,但现在很少采用片外扩展存储器,所以测晶体两端的电压或波形即可,只是晶振电路设计不良时,测试设备的引入有可能导致停振。 2、晶体两端的电压差不是平均电压差,虽然事实上因外电路的影响,晶体两端的电压可能会有差别,但这不是判断晶振是否起振的依据,也不是晶振电路正常工作的条件。至于一高一低没有工作是指一端为Vcc或接近Vcc,另一端为0
[单片机]
关于<font color='red'>51单片机</font>不能正常起振的原因
51单片机通过esp8266和温度传感器将温度显示到手机上
需要的硬件:51单片机,ESP8266(wifi模块),DS18b20(温度传感器) 需要的软件: 手机要下载一个网络调试助手,浏览器就有。 部分代码: #include reg52.h #include intrins.h #define uint unsigned int #define uchar unsigned char sbit DQ=P2^4; sbit k1=P1^0; sbit fmq=P1^4; char receiveTable = ; char aa = ; uint temp,shi,ge,a,i,flag; void delay(uint i) //5us { do
[单片机]
<font color='red'>51单片机</font>通过esp8266和<font color='red'>温度</font>传感器将<font color='red'>温度</font>显示到手机上
采用二维模糊控制器和C8051单片机实现室内自然采光系统的设计
1、 引言 从远古的篝火、油灯到蜡烛、白炽灯,再到今天千家万户的荧光灯,人类已经基本适应了人工光源的室内照明环境。但是由于千万年来的环境影响,自然光仍然是人类最习惯、感觉最舒适的光源,自然采光一直受到建筑师和照明设计师的高度重视。当今社会建筑的节能环保需求更对自然采光照明提出了进一步的要求。《建筑采光设计标准》 中的国家技术经济政策指出: 建筑设计要充分利用天然光,创造良好的光环境。 对室内照明自然采光的研究具有重要的意义: (1) 资料表明,照明用电占整个商业建筑能耗的25 - 40% ,而自然采光在特定的情况下可以节省52% 的照明用电,大大节约了能源。 (2) 相关研究表明,人在自然光条件下工作,可以增加满意度和提高工作
[单片机]
采用二维模糊控制器和C80<font color='red'>51单片机</font>实现室内自然采光系统的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved