单片机仿真实现 PID算法实现
2011年 2月 21日晚
下面给出单片机实现 PID算法的 protues仿真程序和仿真效果图,
希望对广大的 PID算法爱好者有所帮助。不要觉得 PID算法很难,
其 实 很 简 单 , 而 且 很 实 用 哦 !
//单片机实现 PID算法控制实验
//2011年 1月 21日
#include"reg51.h"
#include
#define uchar unsigned char
#define uint unsigned int
#define tiaocan() (P00==0)
#define qiwangzhi() (P01==0)
#define tiao_P() (P02==0)
#define tiao_I() (P03==0)
#define tiao_D() (P04==0)
#define LE0_1() (P05=1)
#define LE0_0() (P05=0)
#define LE1_1() (P06=1)
#define LE1_0() (P06=0)
#define OE0_0() (P07=0)
#define OE0_1() (P07=1)
#define OE1_0() (P10=0)
#define OE1_1() (P10=1)
sbit P00=P0^0;
sbit P01=P0^1;
sbit P02=P0^2;
sbit P03=P0^3;
sbit P04=P0^4;
sbit P05=P0^5;
sbit P06=P0^6;
sbit P07=P0^7;
sbit P10=P1^0;
uint PIDResult;
uchar
display_code[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0
X7D,0X07,0X7F,0X6F,0X77,0X7C,0X39,0X5E,0X79,0
X71};
uchar times=108; //假设为实测值
uchar times1;
//定义 PID结构体 "->"指向结构体成员运算符,"."结
构体成员运算符也叫分量运算符。
struct PID //"struct"结构体关键字。。。 “PID”结构体名
{ //下面是成员列
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
unsigned int SetPoint; // 设定目标值
unsigned int Proportion; // 比例常数
unsigned int Integral; // 积分常数
unsigned int Derivative; // 微分常数
unsigned int LastError; // 上一次偏差
unsigned int PrevError; // 当前偏差
unsigned int SumError; // 偏差累积
}spid;
/*PID结构体变量*/
//struct PID spid; // PID Control Structure
/*调用 string.h头文件函数*/
void PIDInit (struct PID *pp/*定义一个指向结构体变
量的指针*/)
{/*memset()给第一个参数赋第二个参数的ASCII的值
并分配第三个参数大小的空间*/
memset(pp,0,sizeof(struct PID));//PID 各参数存储空
间赋初值 0
}
/*=======================================
=========================
PID计算部分:比例常数*偏差+积分常数*偏差累积量
+微分常数*偏差变化量
========================================
==========================*/
unsigned int PIDCalc( struct PID *pp, unsigned int
NextPoint/*接收传过来的实测值*/ )
{ // pp->"?" 相当于(*pp)."?" -> 用于指向结构体
成员
unsigned int dError,Error;//定义偏差变化量寄存器,
偏差寄存器;
Error = pp->SetPoint - NextPoint; //期望值 -测量侧
(反馈值)=偏差
pp->SumError += Error; //每次偏差的累加=累积偏
差=积分 //提高系统误差度
pp->PrevError = Error; //记录当前偏差
dError = pp->PrevError - pp->LastError; //偏差变化
量=当前偏差-前一次偏差=微分 //反应偏差变化趋势
pp->LastError = Error; /*记录当前偏差用于下次比
较*/
/*比例项、积分项、微分项*/
return (pp->Proportion*Error +
pp->Integral*pp->SumError+ pp->Derivative*dError);
}
void delay(void)
{ uchar i;
for(i=250;i>0;i--);
}
void display()
{ LE1_0(); //禁止锁存器输入,输出
LE0_0();
OE1_1();
OE0_1();
P3=0xff;
P2=display_code[times%10];
OE0_0(); //打开下一行显示;
LE0_1();
P3=0xfe;
delay();
P3=0xff;
P2=display_code[times/10%10];
P3=0xfD;
delay();
P3=0xff;
P2=display_code[times/100];
P3=0xfB;
delay();
P3=0xff;
P2=display_code[times1%10];
P3=0xdf;
delay();
P3=0xff;
P2=display_code[times1/10%10];
P3=0xbf;
delay();
P3=0xff;
P2=display_code[times1/100];
P3=0x7f;
delay();
OE0_1(); //关闭下一排数码管显示
LE0_0();
OE1_0(); //打开上一排数码管显示
LE1_1();
P3=0xff;
P2=display_code[spid.SetPoint%10];
P3=0xfe;
delay();
P3=0xff;
P2=display_code[spid.SetPoint/10%10];
P3=0xfD;
delay();
P3=0xff;
P2=display_code[spid.SetPoint/100];
P3=0xfB;
delay();
P3=0xff;
P2=display_code[spid.Derivative]; //显示微分常数
P3=0xf7;
delay();
P3=0xff;
P2=display_code[spid.Integral]; //显示积分常数
P3=0xdf;
delay();
P3=0xff;
P2=display_code[spid.Proportion]; //显示比列常数
P3=0x7f;
delay();
}
void delay10ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
void main()
{
/*PID初始化*/
PIDInit (&spid);//把结构体变量的起始地址传给指
针变量
//下面应用结构体变量中的成员并赋值
spid.SetPoint = 180;/*控制目的*/
spid.Proportion =6;/*比例常数*/
spid.Integral = 3;/*积分常数*/
spid.Derivative =4;/*微分常数*/
while(1)
{display();
/*PID输出与控制目标对比,调节到稳定状态*/
if(times1!=spid.SetPoint) //如果实测值不等于期
望值,则调用 pid算法
{PIDResult=PIDCalc(&spid,times1/* 实 测 值
*/);
times1=PIDResult; //把通过 PID算法过后
的值送输出
}
if(tiaocan()) //模拟输出发生变化
{delay10ms();
if(tiaocan())
{if(++times>200)
times=0;
times1=times;
while(tiaocan())
display();
}
}
else if(qiwangzhi()) //模拟期望值发生变化
{delay10ms();
if(qiwangzhi())
{if(++spid.SetPoint>240)
spid.SetPoint=180;
while(qiwangzhi())
display();
}
}
else if(tiao_P()) //模拟 P发生变化
{delay10ms();
if(tiao_P())
{if(++spid.Proportion>9)
spid.Proportion=0;
while(tiao_P())
display();
}
}
else if(tiao_I()) //模拟 I发生变化
{delay10ms();
if(tiao_I())
{if(++spid.Integral>9)
spid.Integral=0;
while(tiao_I())
display();
}
}
else if(tiao_D()) //模拟 D发生变化
{delay10ms();
if(tiao_D())
{if(++spid.Derivative>9)
spid.Derivative=0;
while(tiao_D())
display();
}
}
}
}