ad da实现pid闭环控制 pid的一个经典应用 对学习pid算法很有用
源代码在线查看: pid程序.c
/***********************************************************************
文件名:PID程序.C
功能: 用PID算法闭环控制BANGK3区DAC0832的输出电压,通过设置年想要的输出
电压,它通过ADC0804将O832的输出电压读回单片机进行PID自动调节,
并经过短时间将DAC0832的输出电压升到设置的电压
/此程序用的是位置式调节/
作者:测控五组 ¤春暖花★开
日期:2007/4/16/17:16
版本:V1.0
***********************************************************************/
#include
#include
#include
#include
#include
sbit ADC_INT = P3^2;
code unsigned char Tab[10] ={0x0c0,0x0f9,0x0a4,0x0b0,0x99,0x92,0x82,0x0f8,0x80,0x90};
typedef struct
{
double SetPoint; /* 设定目标 Desired Value */
double Proportion; /* 比例常数 Proportional Const */
double Integral; /* 积分常数 Integral Const */
double Derivative; /* 微分常数 Derivative Const */
double LastError; /* 前一项误差 */
double PrevError; /* 前第二项误差 */
double SumError; /* 总误差 */
} PID;
unsigned char sensor () ; /* 传感器返回信号数据 **/
void actuator(unsigned char rDelta); /* 执行机构函数 */
void Delay(unsigned char t);
void display(unsigned char rIn);
/****************************************************************************
PID计算部分
****************************************************************************/
double PIDCalc( PID *pp, double NextPoint )
{
double dError,Error;
Error = pp->SetPoint - NextPoint; /* 计算当前偏差 */
pp->SumError += Error; /* 积分《总偏差》*/
dError = pp->LastError - pp->PrevError; /* 当前微分 */
pp->PrevError = pp->LastError;
pp->LastError = Error; /* 三个误差值移位 */
return(NextPoint+pp->Proportion * Error + pp->Integral * pp->SumError + pp->Derivative * dError ); /*《返回总的误差值》*/
}
/*******************************************************************************
主函数部分
********************************************************************************/
void main(void)
{
PID sPID; /* 定义PID结构体变量 */
double rOut; /* PID 响应输出 */
unsigned char rIn; /* PID 反馈 (Input) */
double x;
sPID.Proportion = 0.74; /* 设置 PID 比例系数 */
sPID.Integral = 0.70; /* 设置PID积分系数 */
sPID.Derivative = 0.0; /* 设置PID微分系数 */
sPID.SetPoint = 2.0; /* 设置 PID 输出值 */
for (;;)
{
unsigned char sumout;
/* PID进入循环检测状态中 */
unsigned char i;
rIn = sensor (); /* 读传感器输出 */
for(i=0;i display(rIn);
x = 5.0 * (double)rIn / 256.0;
rOut = PIDCalc ( &sPID,x ); /* 计算PID 输出 */
sumout=rOut*256/5;
actuator ( sumout ); /* 将要反馈的数据输出 */
}
}
/*******************************************************************************
程序名称:8位并行D/A芯片DAC0832
*********************************************************************************/
void actuator(unsigned char rDelta)
{
XBYTE[0xA000] = rDelta;
Delay(10);
}
/*******************************************************************************
函数:Delay()
功能:延时0.01s~2.56s
参数:t>0时,延时(t*0.01)s
t=0时,延时2.56s
说明:定时10ms的定时器初值=65536-0.01/(1/(f/12)),其中f为晶振频率
*******************************************************************************/
void Delay(unsigned char t)
{
TMOD &= 0xF0;
TMOD |= 0x01;
EA=1;
EX0=1;
do
{
TH0 = 0xee; /* 设置定时器初值(定时5ms)*/
TL0 = 0x00;
TR0 = 1; /* 启动定时器 */
while ( !TF0 ); /* 等待定时器溢出 */
TR0 = 0; /* 停止定时器 */
TF0 = 0; /* 清除溢出标志 */
} while ( --t != 0 ); /* 循环t次 */
}
unsigned char sensor (void)
{
unsigned char v;
Delay(30);
XBYTE[0xB000] = 0xFF; /* 启动A/D转换 */
Delay(1);
while ( ADC_INT ); /* 等待A/D转换完毕 */
v = XBYTE[0xB000]; /* 读取A/D转换结果 */
return (v);
}
void display(unsigned char rIn)
{
float num;
int N;
num=5.0*rIn/256;
N=(int)(num*1000.0);
XBYTE[0x8000]=0x08;
XBYTE[0x9000]=Tab[N/1000]&0x7f;
Delay(1);
XBYTE[0x8000]=0x04;
XBYTE[0x9000]=Tab[N%1000/100];
Delay(1);
XBYTE[0x8000]=0x02;
XBYTE[0x9000]=Tab[N%100/10];
Delay(1);
XBYTE[0x8000]=0x01;
XBYTE[0x9000]=Tab[N%10];
Delay(1);}