找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3009|回复: 0
收起左侧

单片机+H桥控制直流电机调速程序+Proteus仿真电路

[复制链接]
ID:568482 发表于 2020-5-20 15:35 | 显示全部楼层 |阅读模式
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
Snipaste_2020-05-20_15-31-22.png

单片机源程序如下:
  1. #include <reg51.h>
  2. #include "lcd1602.h"

  3. #define THC0 0xf9
  4. #define TLC0 0x0f        //

  5. /***********端口定义**************/
  6. //按键
  7. sbit StopAndStart        =P0^0;
  8. sbit KeyTurnForward =P0^1;
  9. sbit KeyTurnBackward=P0^2;
  10. sbit KeyAddSpeed        =P0^3;
  11. sbit KeySubSpeed        =P0^4;

  12. //电机
  13. sbit CONT1=P2^3;
  14. sbit CONT2=P2^4;
  15. sbit EN   =P2^5;

  16. //
  17. sbit LED1 = P2^0;
  18. sbit LED2 = P2^1;
  19. sbit LED3 = P2^2;




  20. /*^^^^^^^^转态变量^^^^^^^^^^*/
  21. unsigned char motoEn;
  22. unsigned char motoDirection;


  23. /***********变量定义**************/
  24. unsigned int SpeedSet = 100;        //速度设置
  25. unsigned int Impluse = 0;                //脉冲计数
  26. unsigned int num = 0;                        //速度显示
  27. unsigned int cnt = 0;
  28. unsigned int PWMTime=500;                //脉冲宽度


  29. int e,e1,e2;
  30. float uk,uk1,duk;        //PID输出值
  31. float Kp=15,Ki=12,Kd=1.6;
  32. int out=0;


  33. /*^^^^^^^^延时函数^^^^^^^^^^*/
  34. void delay_xms(unsigned char ms)
  35. {
  36.         unsigned int i,j;
  37.         for(i=0;i<ms;i++)
  38.         {
  39.                 for(j=0;j<333;j++);        
  40.         }
  41. }


  42. /*########系统初始化########*/
  43. void SystemInit()
  44. {

  45.         //外部中断0        
  46.         IT0 = 1;  //下降沿触发
  47.         EX0 = 1;  //开外部中断
  48.         EA  = 1;          //开总中断

  49.         //定时器0 1
  50.         ET0=1;          //开定时器中断
  51.         TMOD=0X21;//T0方式2 T1方式2        
  52.         TH0 = THC0;
  53.         TL0 = TLC0;
  54.         TR0 = 1;  //启动定时器0

  55.         TH1=0x10;
  56.         TL1=0x10;
  57.         ET1=1;
  58.         TR1=1;

  59.         e  = 0;
  60.         e1 = 0;
  61.         e2 = 0;

  62.         motoEn=0;
  63.         motoDirection=1;
  64.         //LCD
  65.         LCD1602_Init();
  66.         
  67. }

  68. /*########按键扫描##########*/
  69. void key_scan()
  70. {        
  71.         //启/停
  72.         if(StopAndStart == 0)                  //判断按下
  73.         {
  74.                 delay_xms(10);
  75.                 if(StopAndStart == 0)
  76.                 {
  77.                         
  78.                         while(StopAndStart == 0 ); //判断松手
  79.                         //执行按键功能
  80.                         motoEn=~motoEn;

  81.                         //EN=1;
  82.                 }
  83.         }
  84.         
  85.         //正转
  86.         if(KeyTurnForward == 0)                  //判断按下
  87.         {
  88.                 delay_xms(10);
  89.                 if(KeyTurnForward == 0)
  90.                 {
  91.                         
  92.                         while(KeyTurnForward == 0 ); //判断松手
  93.                         //执行按键功能
  94.                         motoDirection=1;
  95.                         //CONT1 = 1;
  96.                         //CONT2 = 0;
  97.                 }
  98.         }

  99.         //反转
  100.         if(KeyTurnBackward == 0)                  //判断按下
  101.         {
  102.                 delay_xms(10);
  103.                 if(KeyTurnBackward == 0)
  104.                 {
  105.                         while(KeyTurnForward == 0 ); //判断松手
  106.                         //执行按键功能
  107.                         motoDirection=0;
  108.                         //CONT1 = 0;
  109.                         //CONT2 = 1;                                
  110.                 }
  111.         }
  112.         
  113.         //加速
  114.         if(KeyAddSpeed == 0)
  115.         {
  116.                 delay_xms(10);
  117.                 if(KeyAddSpeed == 0)        //判断按下
  118.                 {
  119.                         unsigned char i=0;
  120.                         while(KeyAddSpeed == 0 && i<255){delay_xms(1);i++;}        //判断松手
  121.                         //执行按键功能
  122.                         SpeedSet += 5;
  123.                         if(SpeedSet>300)
  124.                         {
  125.                                 SpeedSet = 300;
  126.                         }               
  127.                 }
  128.         }

  129.         //减速
  130.         if(KeySubSpeed == 0)                  //判断按下
  131.         {
  132.                 delay_xms(10);
  133.                 if(KeySubSpeed == 0)
  134.                 {
  135.                         unsigned char i=0;
  136.                         while(KeySubSpeed == 0 && i<255){delay_xms(1);i++;} //判断松手
  137.                         //执行按键功能
  138.                         SpeedSet -= 5;
  139.                         if(SpeedSet<0)
  140.                         {
  141.                                 SpeedSet = 0;
  142.                         }               
  143.                 }
  144.         }


  145. }

  146. /*##########电机状态动作###########*/
  147. void MotoControl()
  148. {
  149.         if(motoEn == 0)
  150.         {
  151.                 EN=0;
  152.                 CONT1=0;
  153.                 CONT2=0;
  154.                 LED1 = 1;
  155.         }
  156.         else
  157.         {
  158.                 EN=1;
  159.                 LED1 = 0;
  160.                 if(motoDirection == 1)
  161.                 {
  162.                         CONT1=1;
  163.                         CONT2=0;
  164.                         LED2 = 0;
  165.                         LED3 = 1;
  166.                 }
  167.                 else                                   
  168.                 {
  169.                         CONT1=0;
  170.                         CONT2=1;
  171.                         LED2 = 1;
  172.                         LED3 = 0;
  173.                 }
  174.         }
  175. }
  176. /*########LCD显示###########*/
  177. void LCDDis()
  178. {
  179.         LCD1602_4num(0,8,num);
  180.         LCD1602_4num(1,8,SpeedSet);        
  181. }


  182. /*^^^^^^^^PWM 输出^^^^^^^^^*/
  183. void PWMOUT()
  184. {
  185.         if(motoDirection == 1)
  186.         {
  187.                 if(cnt<PWMTime)
  188.                 {
  189.                         CONT1=1;
  190.                 }
  191.                 else
  192.                 {
  193.                         CONT1=0;
  194.                 }
  195.         }
  196.         else
  197.         {
  198.                 if(cnt<PWMTime)
  199.                 {
  200.                         CONT2=1;
  201.                 }
  202.                 else
  203.                 {
  204.                         CONT2=0;
  205.                 }               
  206.         }
  207.         if(cnt>1000) cnt = 0;
  208. }
  209. /*########PID调速############*/

  210. void PIDControl()        //pid偏差计算
  211. {
  212.         e=SpeedSet-num;
  213.         duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/50;
  214.         uk=uk1+duk;
  215.         out=(int)uk;
  216.         if(out>1000)
  217.         {
  218.                 out=1000;
  219.         }
  220.         else
  221.         if(out<0)
  222.         {
  223.                 out=0;
  224.         }
  225.         uk1=uk;          //变量值偏移位
  226.         e2=e1;
  227.         e1=e;
  228.         PWMTime=out;


  229. }
  230. /********************/
  231. void main()
  232. {
  233.         SystemInit();
  234.         while(1)
  235.         {
  236.                 key_scan();//按键扫描
  237.                 LCDDis();//LCD显示
  238.                 MotoControl();//根据按键扫描出的结果做出响应
  239.                 PWMOUT();
  240.         
  241.         }
  242. }

  243. /*@@@@@@@@@@外部中断0@@@@@@@@@@@@@@*/
  244. void inter0() interrupt 0
  245. {
  246.         Impluse++;        //采集外部脉冲数据
  247. }
  248. /*@@@@@@@@@@定时器中断0@@@@@@@@@@@@@@*/
  249. void inter1() interrupt 1
  250. {
  251.         static unsigned int time=0;
  252.         TH0=THC0;
  253.         TL0=TLC0;

  254.         time++;        //转速测量周期

  255.         if(time>100)
  256.         {
  257.                 time=0;
  258.                 num=Impluse*5;
  259.                 Impluse=0;
  260.                 PIDControl();
  261.         }
  262. }

  263. void inter3() interrupt 3
  264. {
  265.         cnt++;
  266.         if(motoDirection == 1)
  267.         {
  268.                 if(cnt<PWMTime)
  269.                 {
  270.                         CONT1=1;
  271.                 }
  272.                 else
  273.                 {
  274.                         CONT1=0;
  275.                 }
  276.         }
  277.         else
  278.         {
  279.                 if(cnt<PWMTime)
  280.                 {
  281.                         CONT2=1;
  282.                 }
  283.                 else
  284.                 {
  285.                         CONT2=0;
  286.                 }               
  287.         }
  288.         if(cnt>1000) cnt = 0;
  289. }
复制代码

全部资料51hei下载地址:
直流调速.zip (94.76 KB, 下载次数: 149)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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