单片机直流电机转速控制(数码管显示独立按键控制正反转停止开始PID算法)
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单片机直流电机转速控制(数码管显示独立按键控制正反转停止开始PID算法)相关的知识,希望对你有一定的参考价值。
单片机直流电机转速控制(数码管显示、独立按键控制正反转、停止、开始、PID算法)
-
proteus仿真演示
-
程序源码
#include<reg52.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define THC0 0xf9
#define TLC0 0x0f //2ms
unsigned char code Duan[]={0x3F, 0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//共阴极数码管,0-9段码表
unsigned char Data_Buffer[8]={0,0,0,0,0,0,0,0}; // 显示缓冲
uchar i=0;
sbit AddSpeed=P1^1;//加速按键
sbit SubSpeed=P1^2;//减速按键
sbit TurnForward=P1^3;//正向旋转
sbit TurnBackward=P1^4;//反向旋转
sbit Stop=P1^5;//停止
sbit IN1=P3^0;//
sbit IN2=P3^1;//电机控制引脚
sbit PWM_FC=P1^0;
int e ,e1 ,e2 ;
float uk ,uk1 ,duk ;//pid输出值
float Kp=15,Ki=12,Kd=1.6;
int out=0;
uint SpeedSet=380;//初始速度
uint cnt=0;
uint Inpluse=0,num=0;//脉冲计数
uint PWMTime=100;//脉冲宽度
unsigned char arry[];
void SendString(uint ch);
void PIDControl();
void SystemInit();
void delay(uchar x);
void PWMOUT();
void SetSpeed();
void SegRefre();
/**************主函数************/
void main()
{
SystemInit();
while(1)
{
SetSpeed(); //按键设定速度
SegRefre(); //数码管显示刷新
PWMOUT(); //输出PWM
}
}
void PIDControl() //pid偏差计算
{
e=SpeedSet-num;
duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/50;
uk=uk1+duk;
out=(int)uk; //输出为占空比
if(out>1000)
{
out=1000;
}
else if(out<0)
{
out=0;
}
uk1=uk; //变量值移位
e2=e1;
e1=e;
PWMTime=out;
}
void delay(uchar x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=50;j>0;j--);
}
void PWMOUT()
{
if(cnt<PWMTime)
{
PWM_FC=1;
}
else
{
PWM_FC=0;
}
if(cnt>1000) cnt=0;
}
void SystemInit()
{
TMOD=0X21; // 0010 0001 定时器1使用工作方式2;T0工作在方式1 8位计时计数器,可自动重新载入计数值 (256) 16位计时计数器 (65536)
TH0=THC0;//T0高8位计数器预装载值63759
TL0=TLC0;//T0低8位计数器预装载值
//定时2ms,计算计时器初值 M = 2^K-X*Fosc/12 T0方式0: K=16,X=2ms,Fosc=11.0592MHz
//65536-2*921.6=63692.8
TH1=0xC0;//T1高8位计数器预装载值1,843.2
TL1=0XC0;//T1低8位计数器预装载值
ET1=1;//整体中断允许位;EA=1允许中断。
ET0=1;//T0中断允许位;ET0=1允许中断。
TR0=1; //TR0=1表示T0开始运行。(单片机中T1引脚,需要高低电平的驱动)
TR1=1; //TR1=1表示T1开始运行。(单片机中T0引脚,需要高低电平的驱动)
EX0=1; //INT0中断允许位;EX0=1允许中断。
IT0=1; //IT0=1表示INT0为下降沿(负跳变)触发,IT0=0表示INT0为低电平触发。
EA=1;//整体中断允许位;EA=1允许中断。
e =0;
e1=0;
e2=0;
IN1 = 1;
IN2 = 0;
}
void SetSpeed()
{
if(AddSpeed==0)
{
delay(200); //消抖处理
if(AddSpeed==0)
{
SpeedSet+=10;
if(SpeedSet>1500)
{
SpeedSet=1500;
}
}
}
if(SubSpeed==0)
{
delay(200);
if(SubSpeed==0)
{
SpeedSet-=10;
if(SpeedSet<0) SpeedSet=0;
}
}
if(TurnForward==0)
{
delay(200);
if(TurnForward==0)
{
IN1 = 1;
IN2 = 0;
while(TurnForward==0);
}
}
if(TurnBackward==0)
{
delay(200);
if(TurnBackward==0)
{
IN1 = 0;
IN2 = 1;
while(TurnBackward==0);
}
}
if(Stop==0)
{
delay(200);
if(Stop==0)
{
IN1 = 1;
IN2 = 1;
while(Stop==0);
}
}
}
void SegRefre() //显示刷新
{
Data_Buffer[0]=SpeedSet/1000; //分离设定值各位
Data_Buffer[1]=SpeedSet%1000/100;
Data_Buffer[2]=SpeedSet%100/10;
Data_Buffer[3]=SpeedSet%10;
Data_Buffer[4]=num/1000;
Data_Buffer[5]=num%1000/100;
Data_Buffer[6]=num%100/10;
Data_Buffer[7]=num%10;
}
void int0() interrupt 0
{
Inpluse++; //采集外部脉冲
}
void t0() interrupt 1
{
static unsigned char Bit=0;
static unsigned int time=0;
TH0=THC0;
TL0=TLC0;
Bit++;
time++; //转速测量周期
if(Bit>8) Bit=0;
P0=0xff;
P2=Duan[Data_Buffer[Bit]]; //显示段码
switch(Bit) //数码管位选
{
case 0:P0=0X7F;break;
case 1:P0=0XBF;break;
case 2:P0=0XDF;break;
case 3:P0=0XEF;break;
case 4:P0=0XF7;break;
case 5:P0=0XFB;break;
case 6:P0=0XFD;break;
case 7:P0=0XFE;break;
}
if(time>100)
{
time=0;
num=Inpluse*5;
Inpluse=0;
PIDControl();
}
}
void timer_1() interrupt 3
{
cnt++; //cnt越大占空比越高2.5Khz
}
- 完整资料下载
创作不易,分享难得,请多多收藏和关注,是我继续创作和开源分享的动力支持。
链接:https://pan.baidu.com/s/1I6wGZIWeLkWS4XeRQ6uFAg
提取码:dao5
以上是关于单片机直流电机转速控制(数码管显示独立按键控制正反转停止开始PID算法)的主要内容,如果未能解决你的问题,请参考以下文章