51单片机c语言pid.docx

上传人:b****3 文档编号:2578628 上传时间:2022-11-02 格式:DOCX 页数:5 大小:16.14KB
下载 相关 举报
51单片机c语言pid.docx_第1页
第1页 / 共5页
51单片机c语言pid.docx_第2页
第2页 / 共5页
51单片机c语言pid.docx_第3页
第3页 / 共5页
51单片机c语言pid.docx_第4页
第4页 / 共5页
51单片机c语言pid.docx_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

51单片机c语言pid.docx

《51单片机c语言pid.docx》由会员分享,可在线阅读,更多相关《51单片机c语言pid.docx(5页珍藏版)》请在冰豆网上搜索。

51单片机c语言pid.docx

实现PID算法,由于是用整型数来做的,所以也不是很精确,但是对于很多的使用场合,这个精度也够了,

关于系数和采样电压全部是放大10倍处理的.所以精度不是很高.但是也不是那么低,大部分的场合都够了.实在觉得精度不够, 

可以再放大10倍或者100倍处理,但是要注意不超出整个数据类型的范围就可以了.本程序包括PID计算和输出两部分.

当偏差>10度全速加热,偏差在10度以内为PID计算输出. 具体的参考代码参见下面:

*/ 

//================================================================ 

//pid.H 

//OperationaboutPIDalgorithmprocedure 

//C51编译器 Keil7.08 

//================================================================ 

//Allrightsreserved. 

//================================================================ 

#include 

#include 

typedef unsigned char    uint8;    

typedef unsigned int    uint16;  

typedef unsigned longint  uint32; 

/**********函数声明************/ 

void  PIDOutput(); 

void  PIDOperation(); 

/*****************************/ 

typedefstructPIDValue 

uint32   Ek_Uint32[3];         //差值保存,给定和反馈的差值 

uint8   EkFlag_Uint8[3];       //符号,1则对应的为负数,0为对应的为正数   

uint8   KP_Uint8; 

uint8   KI_Uint8; 

uint8   KD_Uint8; 

uint16   Uk_Uint16;        //上一时刻的控制电压 

uint16   RK_Uint16;        //设定值 

uint16   CK_Uint16;       //实际值 

}PIDValueStr; 

PIDValueStr PID; 

uint8    out;        //加热输出 

uint8    count;       //输出时间单位计数器 

/********************************* 

PID=Uk+KP*[E(k)-E(k-1)]+KI*E(k)+KD*[E(k)-2E(k-1)+E(k-2)];(增量型PID算式) 

函数入口:

RK(设定值),CK(实际值),KP,KI,KD 

函数出口:

U(K) 

//PID运算函数 

********************************/ 

void  PIDOperation(void)  

uint32   Temp[3];                    //中间临时变量 

uint32   PostSum;                   //正数和 

uint32   NegSum;                   //负数和 

Temp[0]=0; 

Temp[1]=0; 

Temp[2]=0; 

PostSum=0; 

NegSum =0; 

if(PID.RK_Uint16>PID.RK_Uint16)          //设定值大于实际值否?

 

 if(PID.RK_Uint16-PID.RK_Uint16>10)      //偏差大于10否?

 

 { 

 PID.Uk_Uint16=100; 

 //偏差大于10为上限幅值输出(全速加热) 

 }           

 else 

Temp[0]=PID.RK_Uint16-PID.CK_Uint16;   //偏差<=10,计算E(k) 

PID.EkFlag_Uint8[1]=0;            //E(k)为正数 

 //数值移位 

PID.Ek_Uint32[2]=PID.Ek_Uint32[1]; 

PID.Ek_Uint32[1]=PID.Ek_Uint32[0]; 

PID.Ek_Uint32[0]=Temp[0]; 

/****************************************/ 

if(PID.Ek_Uint32[0]>PID.Ek_Uint32[1])              //E(k)>E(k-1)否?

 

Temp[0]=PID.Ek_Uint32[0]-PID.Ek_Uint32[1];     //E(k)>E(k-1) 

PID.EkFlag_Uint8[0]=0;                   //E(k)-E(k-1)为正数

else 

Temp[0]=PID.Ek_Uint32[0]-PID.Ek_Uint32[1];    //E(k)

 PID.EkFlag_Uint8[0]=1;                        //E(k)-E(k-1)为负数

}

/****************************************/ 

Temp[2]=PID.Ek_Uint32[1]*2;                      //2E(k-1) 

if((PID.Ek_Uint32[0]+PID.Ek_Uint32[2])>Temp[2])      //E(k-2)+E(k)>2E(k-1)否?

 

Temp[2]=(PID.Ek_Uint32[0]+PID.Ek_Uint32[2])-Temp[2];  //E(k-2)+E(k)>2E(k-1) 

PID.EkFlag_Uint8[2]=0;                     //E(k-2)+E(k)-2E(k-1)为正数 

else 

Temp[2]=Temp[2]-(PID.Ek_Uint32[0]+PID.Ek_Uint32[2]); //E(k-2)+E(k)<2E(k-1) 

PID.EkFlag_Uint8[2]=1;                   //E(k-2)+E(k)-2E(k-1)为负数

/****************************************/    

Temp[0]=(uint32)PID.KP_Uint8*Temp[0];            //KP*[E(k)-E(k-1)] 

Temp[1]=(uint32)PID.KI_Uint8*PID.Ek_Uint32[0];       //KI*E(k) 

Temp[2]=(uint32)PID.KD_Uint8*Temp[2];           //KD*[E(k-2)+E(k)-2E(k-1)] 

/*以下部分代码是讲所有的正数项叠加,负数项叠加*/   

/**********KP*[E(k)-E(k-1)]**********/ 

if(PID.EkFlag_Uint8[0]==0) 

PostSum+=Temp[0];                  //正数和 

else                        

NegSum+=Temp[0];                  //负数和 

/*********KI*E(k)****************/ 

if(PID.EkFlag_Uint8[1]==0)    

PostSum+=Temp[1];                //正数和 

else 

;                        //空操作,E(K)>0 

/****KD*[E(k-2)+E(k)-2E(k-1)]****/              

if(PID.EkFlag_Uint8[2]==0) 

PostSum+=Temp[2];               //正数和 

else 

NegSum+=Temp[2];              //负数和 

/***************U(K)***************/               

PostSum+=(uint32)PID.Uk_Uint16;   

 

if(PostSum>NegSum)            //是否控制量为正数 

Temp[0]=PostSum-NegSum; 

if(Temp[0]<100)            //小于上限幅值则为计算值输出 

PID.Uk_Uint16=(uint16)Temp[0]; 

else 

PID.Uk_Uint16=100;          //否则为上限幅值输出 

else                  //控制量输出为负数,则输出0(下限幅值输出) 

PID.Uk_Uint16=0; 

else 

PID.Uk_Uint16=0; 

/********************************* 

函数入口:

U(K) 

函数出口:

out(加热输出) 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 财务管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1