找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2334|回复: 2
收起左侧

基于51单片机PWM调速L298芯片控制两选一直流电机正反运转的项目工程

[复制链接]
ID:171036 发表于 2020-5-19 21:47 | 显示全部楼层 |阅读模式
  1. #include"reg52.h"//单片机头文件
  2. #define uchar unsigned char//宏定义,用uchar表示unsigned char,叫无符号字符型数据类型,取值范围为:0到255。
  3. #define uint unsigned int//宏定义,用uint表示unsigned int,叫无符号整数型数据类型,取值范围为:0到65535。
  4. sbit qitingjian=P1^0;//位定义启停键
  5. sbit zhengzhuan=P1^1;//位定义正转键
  6. sbit fanzhuan=P1^2;//位定义反转键
  7. sbit jiasujian=P1^3;//位定义加速键
  8. sbit jiansujian=P1^4;//位定义减速键
  9. sbit xuanze=P1^5;//位定义选择键
  10. sbit IN1=P2^0;//位定义L298M芯片IN1端口
  11. sbit IN2=P2^1;//位定义L298M芯片IN2端口
  12. sbit IN3=P2^2;//位定义L298M芯片IN3端口
  13. sbit IN4=P2^3;//位定义L298M芯片IN4端口
  14. sbit ENA=P2^4;//位定义L298M芯片使能端ENA
  15. sbit ENB=P2^5;//位定义L298M芯片使能端ENB
  16. //sbit duan=P3^0;//位定义L298M芯片控制端IN1
  17. //sbit wei=P3^1;//位定义L298M芯片控制端IN2
  18. sbit qitingled=P3^4;//位定义启停指示灯
  19. sbit zhengzhuanled=P3^5;//位定义正转指示灯
  20. sbit fanzhuanled=P3^6;//位定义反转指示灯
  21. sbit xuanzeled=P3^7;//位定义选择指示灯
  22. uchar xuanzenum;//选择次数变量
  23. uchar motor1flag;//电机1启动标志位变量
  24. uchar motor2flag;//电机2启动标志位变量
  25. uchar motor1_pwm_flag;//电机1脉冲宽度调制标志位变量
  26. uchar motor2_pwm_flag;//电机2脉冲宽度调制标志位变量
  27. //sbit waibuzhongduanling=P3^2; //外部中断0端口
  28. //uint qian,bai,shi,ge,zhuansu;//数码管千位变量、百位变量、十位变量、个位变量以及转速变量
  29. //uint maichongcount,Time0num,Time1num,pwm,qitingnum,zhengzhuanflag,fanzhuanflag;//脉冲计数变量、定时器0定时计数变量、定时器1定时计数变量、脉冲宽度调制变量、启停键按下数次变量、正转标志位变量、反转标志位变量
  30. uint Time0num,pwm,qitingnum,zhengzhuanflag,fanzhuanflag;//定时器0定时计数变量、脉冲宽度调制变量、启停键按下数次变量、正转标志位变量、反转标志位变量
  31. //uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f,0x40,0x7c,0x39,0x5e,0x79,0x71,0x00};//共阴数码管段码,高电平点亮段码,低电平熄灭段码。
  32. //uchar code weima[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff};//共阴数码管位码,低电平点亮位码,高电平熄灭位码。
  33. //void delay(uint jishi);//毫秒延时函数
  34. //void TimerInit();//定时器初始化函数
  35. //void Time0();//定时器0定时函数
  36. //void Time1();//定时器1定时函数
  37. //void KeyScan();//按键扫描函数
  38. //void waibuzhongduanlingjishu();//外部中断0计数函数
  39. //void shumaguandisplay(uint qian,uint bai,uint shi,uint ge);//数码管显示函数
  40. //void shumaguannodisplay(uint qian,uint bai,uint shi,uint ge);//数码管无显示函数
  41.   void delay(uint jishi)//延时函数
  42. {
  43.    uint i,j;
  44.    for(i=jishi;i>0;i--)
  45.     for(j=110;j>0;j--);
  46.   }
  47.   void TimerInit()//定时器初始化函数
  48. {
  49.    TMOD=0x01;//设定定时器为定时器0和定时器1,工作模式都为1。
  50.    TH0=(65536-1000)/256;//TH0装初值为65536-1000=64536,即定时1000微妙,相当于1毫秒。
  51.    TL0=(65536-1000)%256;//TL0装初值为65536-1000=64536
  52. // TH1=(65536-50000)/256;//TH1装初值为65536-50000=15536,即定时50000微妙,相当于50毫秒。
  53. // TL1=(65536-50000)%256;//TL1装初值为65536-50000=15536
  54.    EA=1;//全局中断允许
  55.    ET0=1;//打开定时器0中断允许
  56.    TR0=0;//关定时器0      
  57. // EX0=1;//开外部中断0允许
  58. // IT0=1;//设置外部中断0下降触发中断
  59. // ET1=1;//打开定时器1中断允许
  60. // TR1=1;//开定时器1
  61. }
  62.   void Time0() interrupt 1//定时器0定时函数,每1毫秒产生PWM波一次。
  63. {      
  64.    TH0=(65536-1000)/256;//TH0重装初值为65536-1000=64536,即定时1000微妙,相当于1毫秒。
  65.    TL0=(65536-1000)%256;//TH0重装初值为65536-1000=64536
  66.    Time0num++;//定时器0定时计数变量先赋值再自加
  67.    if(motor1_pwm_flag==1&&motor2_pwm_flag==0)
  68. {
  69.     if(Time0num==20)//判断定时器0定时计数变量是否大于等于20,PWM波完整周期为20ms,定时器0定时计数变量Time0num数值越大,电机运转越快。
  70.   {
  71.      Time0num=0;//定时器0定时计数变量等于0
  72.     }
  73.     if(Time0num<pwm)//判断定时器0定时计数变量还否小于脉冲宽度调制变量      
  74.   {                              
  75.      ENA=1;//L298M芯片使能端ENA置高电平,电机运转。
  76. //   zhuansuled=0;//开转速指示灯
  77.     }
  78.     else
  79.   {
  80.      ENA=0;//L298M芯片使能端ENA置低电平,电机不运转。
  81. //   zhuansuled=1;//关转速指示灯
  82.     }
  83.    }
  84.    if(motor1_pwm_flag==0&&motor2_pwm_flag==1)
  85. {
  86.     if(Time0num==20)//判断定时器0定时计数变量是否大于等于20,PWM波完整周期为20ms,定时器0定时计数变量Time0num数值越大,电机运转越快。
  87.    {
  88.      Time0num=0;//定时器0定时计数变量等于0
  89.     }
  90.     if(Time0num<pwm)//判断定时器0定时计数变量还否小于脉冲宽度调制变量      
  91.    {                              
  92.      ENB=1;//L298M芯片使能端ENA置高电平,电机运转。
  93. //   zhuansuled=0;//开转速指示灯
  94.     }
  95.     else
  96.    {
  97.      ENB=0;//L298M芯片使能端ENA置低电平,电机不运转。
  98. //   zhuansuled=1;//关转速指示灯
  99.     }
  100.    }
  101. }
  102. //  void Time1() interrupt 3//定时器1定时函数,定时50ms,采集电机转速。      
  103. //{      
  104. //   TH1=(65536-50000)/256;//TH1装初值为65536-50000=15536,即定时50000微妙,相当于50毫秒。
  105. //   TL1=(65536-50000)%256;//TH1装初值为65536-50000=15536
  106. //   Time1num++;//定时器1定时计数变量先赋值再自加
  107. //   if(Time1num==20)//判断定时器1定时计数变量是否等于20,即每1秒测速一次。
  108. //  {      
  109. //    Time1num=0;//定时器1定时计数变量等于0
  110. //    EX0=0;//关外部中断0
  111. //    zhuansu=55*maichongcount/24;//电机转速=每分钟X脉冲计数变量/每转一圈需要的脉冲个数,即55*maichongcount/24,其中的55表示55秒,为什么不是一分钟60秒?由于Protues仿真电路图中的MOTOR-ENCODER仿真件存在误差,为了让MOTOR-ENCODER仿真件显示的转速达到数码管显示转速的效果,进行了一定秒数的修改,不过实际运用要以一分钟60秒为准,maichongcount为单片机从外部中断0端口处获取MOTOR-ENCODER仿真件旋转生产的脉冲计数变量,24为MOTOR-ENCODER仿真件每旋转一圈产生的脉冲个数。
  112. //    qian=zhuansu/1000;//数码管千位显示
  113. //    bai=zhuansu%1000/100;//数码管百位显示
  114. //    shi=zhuansu%100/10;//数码管十位显示
  115. //    ge=zhuansu%10;//数码管个位显示
  116. //    maichongcount=0;//脉冲计数变量归零
  117. //    EX0=1;//开外部中断0
  118. //   }
  119. //}
  120. //  void waibuzhongduanlingjishu() interrupt 0  using 1//外部中断0计数函数,外部脉冲计数。
  121. //{
  122. //   maichongcount++ ;//脉冲计数变量先赋值再自加
  123. //  }
  124.   void KeyScan()//按键扫描函数
  125. {
  126.    if(qitingjian==0)//判断启停键是否按下
  127. {
  128. //  shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  129.     delay(5);
  130.     if(qitingjian==0)//再次判断启停键是否按下
  131.   {
  132. //   shumaguandisplay(qian,bai,shi,ge);//数码管显示函数
  133.      qitingnum++;//启停键按下数次变量先赋值再加加
  134.      qitingled=0;//开启停指示灯
  135.      while(!qitingjian);//启停键释放
  136.      if(qitingnum==2)//判断启停键按下数次变量是否为2
  137.     {
  138.       TR0=0;
  139.       qitingnum=0;//启停键按下数次变量归零
  140.       xuanzenum=0;//选择次数变量清0
  141.       Time0num=0;//定时器0定时计数变量清0
  142.       pwm=0;//脉冲宽度调制变量清0
  143.       qitingled=1;//关启停指示灯
  144.       zhengzhuanled=1;//关正转指示灯
  145.       fanzhuanled=1;//关反转指示灯
  146.       xuanzeled=1;//关选择指示灯
  147.       zhengzhuanflag=0;//正转标志位变量为0
  148.       fanzhuanflag=0;//反转标志位变量为0
  149.       motor1flag=0;//电机1启动标志位变量置0
  150.       motor2flag=0;//电机2启动标志位变量置0
  151.       motor1_pwm_flag=0;//电机1脉冲宽度调制标志位变量
  152.       motor2_pwm_flag=0;//电机2脉冲宽度调制标志位变量
  153.       IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。
  154.       IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。
  155.       IN3=0;//L298M芯片控制端IN3置低电平,电机不运转。
  156.       IN4=0;//L298M芯片控制端IN4置低电平,电机不运转。
  157. //    shumaguannodisplay(qian,bai,shi,ge);//数码管无显示函数
  158.      }
  159.     }
  160.    }
  161.    if(qitingnum==1)//判断启停键是否第一次按下
  162. {     
  163.     if(xuanze==0)//判断选择键是否第一次按下
  164.   {
  165.         delay(5);
  166.      if(xuanze==0)//再次判断选择键是否按下
  167.    {
  168.       TR0=1;
  169.       xuanzeled=0;//选择指示灯
  170.       xuanzenum++;//选择次数变量自加
  171.       motor1flag=1;//电机1启动标志位变量置1
  172.       motor2flag=0;//电机2启动标志位变量置0
  173.       motor1_pwm_flag=1;//电机1脉冲宽度调制标志位变量置1
  174.       motor2_pwm_flag=0;//电机1脉冲宽度调制标志位变量置0
  175.       zhengzhuanled=1;//关正转指示灯
  176.       fanzhuanled=1;//关反转指示灯
  177.       IN3=0;//L298M芯片控制端IN3置低电平,电机不运转。
  178.       IN4=0;//L298M芯片控制端IN4置低电平,电机不运转。
  179.       while(!xuanze);//选择键释放
  180.      }
  181.     }
  182.      if(xuanzenum==2)//判断选择次数变量是否为2
  183.    {  
  184. //    TR0=0;
  185. //    Time0num=0;//定时器0定时计数变量清0
  186. //    pwm=0;//脉冲宽度调制变量清0
  187.       xuanzenum=0;//选择次数变量清0
  188.       motor1flag=0;//电机1启动标志位变量置1
  189.       motor2flag=1;//电机2启动标志位变量置0
  190.       motor1_pwm_flag=0;//电机1脉冲宽度调制标志位变量置0
  191.       motor2_pwm_flag=1;//电机1脉冲宽度调制标志位变量置1
  192.       xuanzeled=1;//关选择指示灯
  193.       zhengzhuanflag=0;//正转标志位变量为0
  194.       fanzhuanflag=0;//反转标志位变量为0
  195.       zhengzhuanled=1;//关正转指示灯
  196.       fanzhuanled=1;//关反转指示灯
  197.       IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。
  198.       IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。
  199.      }     
  200.      if(motor1flag==1&&motor2flag==0&&motor1_pwm_flag==1)//判断电机1启动标志位变量是否置1,电机2启动标志位变量是否置0 ,电机1脉冲宽度调制标志位变量置1,此处为电机1正反转。
  201.    {
  202.       if(zhengzhuan==0)//判断是否按下正转键
  203.     {
  204. //     shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  205.        delay(5);
  206.        if(zhengzhuan==0)//再次判断是否按下正转
  207.      {
  208. //      shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  209.         zhengzhuanled=0;//开正转指示灯
  210.         fanzhuanled=1;//关反转指示灯
  211.         zhengzhuanflag=1;//正转标志位变量为1
  212.         fanzhuanflag=0;//反转标志位变量为0
  213.         IN1=0;//L298N芯片控制端IN1置高电平
  214.         IN2=1;//L298N芯片控制端IN2置低电平
  215.         while(!zhengzhuan);//正转键释放
  216.        }
  217.       }
  218.       if(fanzhuan==0)//判断是否按下反转键
  219.     {
  220. //     shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  221.        delay(5);
  222.        if(fanzhuan==0)//再次判断是否按下反转键
  223.      {
  224. //      shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  225.         zhengzhuanled=1;//关正转指示灯
  226.         fanzhuanled=0;//开反转指示灯
  227.         zhengzhuanflag=0;//正转标志位变量为0
  228.         fanzhuanflag=1;//反转标志位变量为1
  229.         IN1=1;//L298N芯片控制端IN1置低电平
  230.         IN2=0;//L298N芯片控制端IN2置高电平
  231.         while(!fanzhuan);//反转键释放
  232.        }
  233.       }
  234.      }
  235.      if(motor1flag==0&&motor2flag==1&&motor2_pwm_flag==1)//判断电机1启动标志位变量是否置0,电机2启动标志位变量是否置1 ,电机2脉冲宽度调制标志位变量置1,此处为电机2正反转。
  236.    {
  237.       if(zhengzhuan==0)//判断是否按下正转键
  238.     {
  239. //     shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  240.        delay(5);
  241.        if(zhengzhuan==0)//再次判断是否按下正转
  242.      {
  243. //      shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  244.         zhengzhuanled=0;//开正转指示灯
  245.         fanzhuanled=1;//关反转指示灯
  246.         zhengzhuanflag=1;//正转标志位变量为1
  247.         fanzhuanflag=0;//反转标志位变量为0
  248.         IN3=0;//L298N芯片控制端IN3置高电平
  249.         IN4=1;//L298N芯片控制端IN4置低电平
  250.         while(!zhengzhuan);//正转键释放
  251.        }
  252.       }
  253.       if(fanzhuan==0)//判断是否按下反转键
  254.     {
  255. //      shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  256.        delay(5);
  257.        if(fanzhuan==0)//再次判断是否按下反转键
  258.      {
  259. //      shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  260.         zhengzhuanled=1;//关正转指示灯
  261.         fanzhuanled=0;//开反转指示灯
  262.         zhengzhuanflag=0;//正转标志位变量为0
  263.         fanzhuanflag=1;//反转标志位变量为1
  264.         IN3=1;//L298N芯片控制端IN3置低电平
  265.         IN4=0;//L298N芯片控制端IN4置高电平
  266.         while(!fanzhuan);//反转键释放
  267.        }
  268.       }
  269.      }
  270.      if(zhengzhuanflag==1||fanzhuanflag==1)//判断电机是否为正转或反转
  271.    {
  272.      if(jiasujian==0)//判断是否按下加速键
  273.     {
  274. //   shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  275.       delay(5);
  276.       if(jiasujian==0)//再次判断是否按下加速键
  277.      {
  278. //     shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  279.        if(pwm < 20)//判断脉冲宽度调制变量是否小于20
  280.        pwm++;//脉冲宽度调制变量先赋值再加加
  281.        if(pwm >= 20)//判断脉冲宽度调制变量是否大于等于20
  282.        pwm = 19;//脉冲宽度调制变量等于20
  283.        while(!jiasujian);//加速键释放                                 
  284.       }
  285.      }
  286.      if(jiansujian==0) //判断是否按下减速键
  287.     {
  288. //    shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  289.       delay(5);
  290.       if(jiansujian==0)//再次判断是否按下减键
  291.      {
  292. //     shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时
  293.        if(pwm > 0)//判断脉冲宽度调制变量是否大于0
  294.        pwm--;//脉冲宽度调制变量先赋值再减减
  295.        if(pwm <= 0)//判断脉冲宽度调制变量是否小于等于0
  296.        pwm = 0;//脉冲宽度调制变量等于0
  297.        while(!jiansujian);//减速键释放
  298.       }
  299.      }
  300.     }
  301.    }
  302.   }
  303. //  void shumaguandisplay(uint qian,uint bai,uint shi,uint ge)//数码管显示函数
  304. //{
  305. //   duan=1;//开数码管段码端口                     
  306. //   P0=table[qian];//数码千位显示
  307. //   duan=0;//关数码管段码端口
  308. //   P0=0x00;//关数码管段码显示
  309. //   wei=1;//开数码管位码端口
  310. //   P2=weima[0];//第1位数码管显示
  311. //   wei=0;//关数码管位码端口
  312. //   delay(1);//延时
  313. //   
  314. //   duan=1;//开数码管段码端口                     
  315. //   P0=table[bai];//数码百位显示
  316. //   duan=0;//关数码管段码端口
  317. //   P0=0x00;//关数码管段码显示
  318. //   wei=1;//开数码管位码端口
  319. //   P2=weima[1];//第2位数码管显示
  320. //   wei=0;//关数码管位码端口
  321. //   delay(1);//延时
  322. //
  323. //   duan=1;//开数码管段码端口                  
  324. //   P0=table[shi];//数码管十位显示
  325. //   duan=0;//关数码管段码端口
  326. //   P0=0x00;//关数码管段码显示
  327. //   wei=1;//开数码管位码端口
  328. //   P2=weima[2];//第3位数码管显示
  329. //   wei=0;//关数码管位码端口
  330. //   delay(1);//延时
  331. //
  332. //   duan=1;//开数码管段码端口                        
  333. //   P0=table[ge];//数码管个位显示
  334. //   duan=0;//关数码管段码端口
  335. //   P0=0x00;//关数码管段码显示
  336. //   wei=1;//开数码管位码端口
  337. //   P2=weima[3];//第4位数码管显示
  338. //   wei=0;//关数码管位码端口
  339. //   delay(1);//延时     
  340. // }
  341. //  void shumaguannodisplay(uint qian,uint bai,uint shi,uint ge)//数码管显示函数
  342. //{
  343. //   duan=1;//开数码管段码端口  
  344. //   P0=table[qian];//数码千位显示
  345. //   duan=1;//关数码管段码端口
  346. //   P0=0x00;//关数码管段码显示
  347. //   wei=1;//开数码管位码端口
  348. //   P2=weima[0];//第1位数码管显示
  349. //   wei=1;//关数码管位码端口
  350. //   delay(1);//延时
  351. //   
  352. //   duan=1;//开数码管段码端口                     
  353. //   P0=table[bai];//数码百位显示
  354. //   duan=1;//关数码管段码端口
  355. //   P0=0x00;//关数码管段码显示
  356. //   wei=1;//开数码管位码端口
  357. //   P2=weima[1];//第2位数码管显示
  358. //   wei=1;//关数码管位码端口
  359. //   delay(1);//延时
  360. //
  361. //   duan=1;//开数码管段码端口                  
  362. //   P0=table[shi];//数码管十位显示
  363. //   duan=1;//关数码管段码端口
  364. //   P0=0x00;//关数码管段码显示
  365. //   wei=1;//开数码管位码端口
  366. //   P2=weima[2];//第3位数码管显示
  367. //   wei=1;//关数码管位码端口
  368. //   delay(1);//延时
  369. //
  370. //   duan=1;//开数码管段码端口                        
  371. //   P0=table[ge];//数码管个位显示
  372. //   duan=1;//关数码管段码端口
  373. //   P0=0x00;//关数码管段码显示
  374. //   wei=1;//开数码管位码端口
  375. //   P2=weima[3];//第4位数码管显示
  376. //   wei=1;//关数码管位码端口
  377. //   delay(1);//延时     
  378. // }
  379.   void main()//主函数
  380. {
  381.    TimerInit();//定时器初始化函数
  382.    ENA=0;
  383.    ENB=0;
  384.    IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。
  385.    IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。
  386.    IN3=0;//L298M芯片控制端IN3置低电平,电机不运转。
  387.    IN4=0;//L298M芯片控制端IN4置低电平,电机不运转。
  388.    while(1)//死循环
  389. {
  390.     KeyScan();//按键扫描函数
  391. //  if(qitingnum==1)//判断启停键是否第一次按下
  392. //  shumaguandisplay(qian,bai,shi,ge);//数码管显示函数
  393.   }
  394. }
复制代码
图片111.png
图片112.png

评分

参与人数 2黑币 +62 收起 理由
neigebutong + 12 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:342911 发表于 2020-5-19 22:53 | 显示全部楼层
这注释,太到位了
回复

使用道具 举报

ID:337693 发表于 2020-6-6 02:27 来自手机 | 显示全部楼层
楼主问一下l298n驱动7.2 300ma的马达会不会过载
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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