附 录
源程序:
#include
#define KP 1.6 //比例系数 #define KI 0.5 //积分系数 #define KD 0 //微分系数
#define max 200 //返回的最大值,是PWM的周期值 #define min 0 //返回的最小值,为0 #define deadline 0x08//速度PID设置死区范围 #define setspeed 80 //速度设定值
typedef struct PID //定义数法核心数据 {
int vi_Ref;//速度PID,速度设定值 int vi_FeedBack; //速度PID,速度反馈值
long PreError;//速度PID,前一次,速度误差setspeed-speed long PreDerror;//速度PID,前一次,速度误差之差 uint v_Kp; //速度PID,Ka = Kp
uint v_Ki; //速度PID,Kb = Kp * ( T / Ti ) uint v_Kd; //速度PID,kc = Kp * ( Td / T ) long PreU;//电机控制输出值 }PID;
static PID sPID; //PID控制结构
static PID*sptr=&sPID;
uchar code loops[] = {0x7f,0xbf,0xdf,0xef};//定义显示位控制驱动码
uchar code table[]={0x14,0xd7,0x4c,0x45,0x87,0x25,0x24,0x57,0x04,0x05}; // 共阳极0,1,2,3,4,5,6,7,8,9
void PIDInit(void) {
sptr->vi_Ref=setspeed;//速度设定值 sptr->vi_FeedBack=bb; //速度反馈值
sptr->PreError = 0 ; //前一次,速度误差,setspeed-speed sptr->PreDerror = 0 ; //前一次,速度误差之差,d_error-PreDerror; sptr->v_Kp = KP; sptr->v_Ki = KI; sptr->v_Kd = KD;
sptr->PreU = 0; //电机控制输出值 }PID;
uint speed_pid(int v); void DisplayFresh(); void delay(uint z); void init(); uchar i,a,b,c,d; main() { init(); while(1) { en=1;
delay(sptr->PreU ); en=0;
delay(200-sptr->PreU ); DisplayFresh(); } }
void delay(uint z) { uint x,y;
for(x=z;x>0;x--) for(y=11;y>0;y--); }
void init()//初始化 {
TMOD=0x51;
TH0=(65536-20000)/256; TL0=(65536-20000)%6; IT1=1;//外部中断1触发类型选择 IT0=1;//外部中断0触发类型选择
TR1=0;//T1的运行控制位,清0时停止T1 TR0=1;//T0的运行控制位,置1时启动T0 EA=1; //开总中断
ET0=1;//定时计数器0中断允许 zhen=1; fan=0;
sptr->PreU=30;//设置初始占空比 }
void timer0() interrupt 1 {
TH0=(65536-20000)/256;//赋初值20ms TL0=(65536-20000)%6; i++;
//延时子程序,延时0.1ms
if(i%==0) // 判断是否时间到了0.5S {
//T1不允许中断
TR1=0;
bb=TH1*256+TL1; //计算脉冲数 TR1=1; bb/=2; 个脉冲
speed_pid(bb); //速度PI计算 }
if(a%==0) {
void ClacSpeed(); } } //PID
uint speed_pid(int v) {
signed long error,d_error,dd_error; // sptr->vi_FeedBack=v;
error = (signed long)(sptr->vi_Ref - sptr->vi_FeedBack); // 偏差计算 d_error = error - sptr->PreError; dd_error = d_error - sptr->PreDerror; sptr->PreError = error; //存储当前偏差 sptr->PreDerror = d_error; //储存当前误差之差
sptr->PreU += (signed long)( sptr -> v_Kp * d_error +sptr -> v_Ki * error +sptr->v_Kd*dd_error);//速度PID计算
if( sptr->PreU >=max )//速度PID,防止调节最高溢出 sptr->PreU = max; else
// 0.25S刷新一次数码管缓存器内的值
//计算转过的圈数,除以2即为转过的圈数,叶片转一圈得到2
if( sptr->PreU <= min ) //速度PID,防止调节最低溢出 sptr->PreU = min; else
return ( sptr->PreU ); // 返回预调节占空比 }
void DisplayFresh() {
P2 =loops[0] ;
P0 = table[a];
delay(50); P2 =loops[1] ; P0 = table[b];
delay(50);
P2 =loops[2] ; P0 = table[c]; delay(50); P2 =loops[3] ;
P0 = table[d]; }
void ClacSpeed() { }
delay(50);
a = (bb/1000); b = (bb/100); c = (bb/10); d = bb;
电路图: