找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5375|回复: 15
打印 上一主题 下一主题
收起左侧

基于51单片机PID算法控制直流电机转速且数码管显示实际转速与设定速度的项目工程

  [复制链接]
跳转到指定楼层
楼主
ID:171036 发表于 2020-5-3 15:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 51黑电子会员 于 2020-5-5 10:00 编辑
  1. #include<reg52.h>
  2. #include<stdio.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. uchar code Duan[]={0x3F, 0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//共阴极数码管0-9段码表,高电平导通数码管段显示,低电平导通数码管位显示。
  6. uchar Data_Buffer[8]={0,0,0,0,0,0,0,0};//声明数据缓存变量
  7. sbit PWM_FC=P1^0;//位定义脉冲宽度输入端口
  8. sbit AddSpeed=P1^1;//位定义加速按键端口
  9. sbit SubSpeed=P1^2;//位定义减速按键端口
  10. sbit qiting=P1^3;//位定义启停按键端口
  11. sbit led0=P1^4;//位定义启停led指示灯
  12. sbit IN1=P3^4;//L298输入端1
  13. sbit IN2=P3^5;//L298输入端2
  14. uchar qitingnum;//声明启停次数变量
  15. int e ,e1 ,e2 ;//声明当前偏差值变量、之后偏差值变量、再后偏差值变量
  16. int out=0;//PID调节后输出偏差值变量
  17. uint SetSpeed=0;//声明设定速度变量
  18. uint ActualSpeed=0;//声明实际速度变量
  19. uint cnt=0;//定时器1中断次数变量
  20. uint Inpluse=0;//声明脉冲计数变量、
  21. uint PWMTime=100;//声明脉冲宽度时间变量
  22. float uk ,uk1 ,duk ;//声明目前总偏差值变量、之后偏差值总变量、偏差值总变量
  23. float Kp=0.36,Ki=0.05,Kd=0.016;//声明比例系数、积分系数、微分系数
  24. void PIDControl();//PID控制函数
  25. void SystemInit();//系统初始化函数
  26. void delay(uchar x);//延时函数
  27. void PWMOUT();//脉冲宽度输出函数
  28. void SpeedSet();//设定速度函数
  29. void SegRefre();//数码管显示刷新函数
  30. /**************主函数************/
  31.   void main()
  32. {
  33.    SystemInit();//系统初始化函数
  34.    while(1)
  35. {
  36.     SpeedSet();//设定速度函数
  37.     SegRefre();//数码管显示刷新函数
  38.     PWMOUT();//脉冲宽度输出函数
  39.    }
  40. }
  41.   void delay(uchar x)//延时函数
  42. {
  43.    uint i,j;
  44.    for(i=x;i>0;i--)
  45.     for(j=50;j>0;j--);
  46.   }
  47.   void PIDControl()//PID控制函数
  48. {
  49.    e=SetSpeed-ActualSpeed;//计算当前偏差值变量
  50.    duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2));//PID连续系统离散化增量型PID算法,算出总偏差值变量。
  51.    uk=duk+uk1;//计算偏差值总变量加上之后偏差值总变量之和赋给目前总偏差值变量
  52.    out=(int)uk;//强制类型转化为整数型的目前总偏差值变量赋给PID调节后输出偏差值变量
  53.    if(out>100)//判断PID调节后输出偏差值变量是否大于100
  54. {
  55.     out=100;//PID调节后输出偏差值变量为100
  56.    }
  57.    else if(out<0)//判断PID调节后输出偏差值变量是否小于0
  58. {
  59.     out=0;//PID调节后输出偏差值变量为0
  60.   }
  61.    uk1=uk;//目前总偏差值变量赋给之后偏差值总变量
  62.    e2=e1;//之前偏差值变量赋给之后偏差值变量
  63.    e1=e;//当前偏差值变量赋给之前偏差值变量
  64.    PWMTime=out;//PID调节后输出偏差值变量赋给脉冲宽度时间变量
  65.   }
  66.   void PWMOUT()//脉冲宽度输出函数
  67. {
  68.    if(cnt<PWMTime)//判断定时器1中断次数变量是否小于脉冲宽度时间变量
  69. {
  70.     PWM_FC=1;//脉冲宽度输入端口输出高电平
  71.    }
  72.    else
  73. {
  74.     PWM_FC=0;//脉冲宽度输入端口输出低电平
  75.    }
  76.    if(cnt>100)//判断定时器1中断次数变量是否大于100
  77.    cnt=0;//定时器1中断次数变量归0
  78. }
  79.   void SystemInit()//系统初始化函数
  80. {
  81.    TMOD=0X21;//定时器0方式1,定时器1方式2。  
  82.    TH0=0xf8;//初装定时器0高八位寄存器定时数值
  83.    TL0=0x50 ;//初装定时器0低八位寄存器定时数值,即2毫秒。
  84.    TH1=0xC0;//初装定时器1高八位寄存器定时数值
  85.    TL1=0XC0;//初装定时器1低八位寄存器定时数值,即16毫秒。
  86.    EA=1;//开总中断
  87.    EX0=1;//开外部中断0
  88.    IT0=1;//外部中断0下降沿触发
  89.    ET0=1;//开定时器0中断允许
  90.    ET1=1;//开定时器1中断允许
  91.    TR0=1;//开定时器0中断
  92.    TR1=1;//开定时器1中断
  93.    e =0;//偏差值变量为0
  94.    e1=0;//之后偏差值变量为0
  95.    e2=0;//再后偏差值变量为0
  96.    IN1=1;
  97.    IN2=1;
  98.   }
  99.   void SpeedSet()//设定速度函数
  100. {
  101.    if(qiting==0)
  102. {
  103.     delay(200);
  104.     if(qiting==0)
  105.   {
  106.      IN1=0;
  107.      IN2=1;
  108.      qitingnum++;
  109.      while(qiting==1);
  110.     }
  111.    }
  112.    if(qitingnum==1)
  113. {
  114.     led0=0;
  115.     if(AddSpeed==0)//判断加速键是否按下
  116.   {
  117.      delay(200);//延时
  118.      if(AddSpeed==0)//再次判断加速键是否按下
  119.    {
  120.       SetSpeed+=10;//设定速度变量每次加10
  121.       if(SetSpeed>3500)//判断设定速度变量是否大于3500
  122.     {
  123.        SetSpeed=3500;//设定速度变量归为3500
  124.       }
  125.      }
  126.     }
  127.     if(SubSpeed==0)//判断减速键是否按下
  128.   {
  129.      delay(200);//延时
  130.      if(SubSpeed==0)//再次判断减速键是否按下
  131.    {
  132.       SetSpeed-=10;//设定速度变量每次减10
  133.       if(SetSpeed<0)//判断设定速度变量是否小于0
  134.       SetSpeed=0;//设定速度变量归0
  135.      }
  136.     }
  137.    }
  138.    if(qitingnum==2)
  139. {
  140.     qitingnum=0;
  141.     IN1=1;
  142.     IN2=1;
  143.     led0=1;
  144.    }
  145.   }
  146.   void SegRefre()//数码管显示刷新函数
  147. {
  148.    Data_Buffer[0]=SetSpeed/1000;//设定速度变量千位数
  149.    Data_Buffer[1]=SetSpeed%1000/100;//设定速度变量百位数
  150.    Data_Buffer[2]=SetSpeed%100/10;//设定速度变量十位数
  151.    Data_Buffer[3]=SetSpeed%10;//设定速度变量个位数
  152.    Data_Buffer[4]=ActualSpeed/1000;//实际速度变量千位数
  153.    Data_Buffer[5]=ActualSpeed%1000/100;//实际速度变量百位数
  154.    Data_Buffer[6]=ActualSpeed%100/10;//实际速度变量十位数
  155.    Data_Buffer[7]=ActualSpeed%10;//实际速度变量个位数
  156.   }
  157.   void int0() interrupt 0//外部中断0函数
  158. {
  159.    Inpluse++;//脉冲计数变量加加
  160. }
  161.   void Time0() interrupt 1//定时器0中断服务函数
  162. {
  163.    static uchar Bit=0;//数码管位码静态变量,退出程序,其数值保留。
  164.    static uint time=0;//转速测量周期变量
  165.    TH0=0xf8;//重装定时器0高八位寄存器计数值
  166.    TL0=0x50 ;//重装定时器0低八位寄存器计数值,即2毫秒。
  167.    time++;//转速测量周期变量加加
  168.    if(time>500)//判断转速测量周期变量是否大于500,等于500就是500x2毫秒=1000毫秒,也就是1s。
  169. {
  170.     time=0;//转速测量周期变量归0
  171.     ActualSpeed=Inpluse;//脉冲计数变量表示实际速度变量
  172.     Inpluse=0;//脉冲计数变量归0
  173.     PIDControl();//PID控制函数
  174.    }
  175.    PWMOUT();//脉冲宽度输出函数
  176.    Bit++;//数码管位码选择位变量
  177.    if(Bit>8)//判断数码管位码选择位变量是否大于8
  178.    Bit=0;//数码管位码选择位变量归0
  179.    P0=0xff;//数码管位码显示关闭
  180.    P2=Duan[Data_Buffer[Bit]];//数码管段码显示
  181.    switch(Bit)//数码管位码变量选择位
  182. {
  183.     case 0:
  184.            P0=0X7F;//实际速度变量千位
  185.            break;
  186.     case 1:
  187.            P0=0XBF;//实际速度变量百位
  188.            break;
  189.     case 2:
  190.            P0=0XDF;//实际速度变量十位
  191.            break;
  192.     case 3:
  193.            P0=0XEF;//实际速度变量个位
  194.            break;
  195.     case 4:
  196.            P0=0XF7;//设定速度变量千位
  197.            break;
  198.     case 5:
  199.            P0=0XFB;//设定速度变量百位
  200.            break;
  201.     case 6:
  202.            P0=0XFD;//设定速度变量十位
  203.            break;
  204.     case 7:
  205.            P0=0XFE;//设定速度变量个位
  206.            break;
  207.    }
  208. }
  209.   void Timer1() interrupt 3//定时器1中断服务函数
  210. {
  211.    cnt++;//定时器1中断次数变量
  212.   }
复制代码







评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:237239 发表于 2020-5-3 16:33 | 只看该作者
哇~很强,要是有设计说明和完整工程文件就更好了
回复

使用道具 举报

板凳
ID:573477 发表于 2020-5-7 17:14 | 只看该作者
值得学习
回复

使用道具 举报

地板
ID:703927 发表于 2020-5-10 08:47 | 只看该作者
值得学习
回复

使用道具 举报

5#
ID:744356 发表于 2020-5-10 10:07 | 只看该作者
感觉很好用
回复

使用道具 举报

6#
ID:703927 发表于 2020-5-13 09:41 | 只看该作者
感觉很好用
回复

使用道具 举报

7#
ID:703927 发表于 2020-5-14 08:17 | 只看该作者

值得学习
回复

使用道具 举报

8#
ID:703927 发表于 2020-5-15 09:11 | 只看该作者
值得学习
回复

使用道具 举报

9#
ID:618434 发表于 2020-5-17 22:22 | 只看该作者
值得学习
回复

使用道具 举报

10#
ID:762850 发表于 2020-5-30 14:46 | 只看该作者
能把仿真和程序都压缩发出来吗,谢谢了
回复

使用道具 举报

11#
ID:302325 发表于 2020-6-1 01:48 | 只看该作者
值得学习
回复

使用道具 举报

12#
ID:835142 发表于 2021-2-13 01:20 来自手机 | 只看该作者
值得初学者pid学习
回复

使用道具 举报

13#
ID:684871 发表于 2021-3-7 20:38 来自手机 | 只看该作者
1.电机转速的传递函数怎么写?
回复

使用道具 举报

14#
ID:684871 发表于 2021-3-7 20:38 来自手机 | 只看该作者
2.为什么用脉冲数代表实际转速,这样不准确吧?
回复

使用道具 举报

15#
ID:684871 发表于 2021-3-7 20:42 来自手机 | 只看该作者
传递函数怎么写?
回复

使用道具 举报

16#
ID:814885 发表于 2021-3-20 10:36 | 只看该作者
PID 的各个参数 怎么设定的?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表