找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机3个定时器驱动机器人PWM无刷直流电机进行编程运动 源程序

[复制链接]
跳转到指定楼层
楼主
买了几个机器人PWM无刷直流电机,内部有驱动器,所有功能都可以单片编程IO口控制,弄了个简单程序先动行一下,有1602液晶显示器,可同时驱动4路PWM信号,用了3个定时器

制作出来的实物图如下:


单片机程序源码:
  1. #include"reg52.h"
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. //sfr T2MOD =0xC9;  //定时器中断2TMOD必须定义
  5. /*-----------------------PWM定义---------------------------*/
  6. sbit RS = P2^6 ;
  7. sbit RW = P2^5 ;
  8. sbit EN = P2^7 ;

  9. sbit STA7 = P0^7;

  10. uchar PWM_T=0;//PWM脉冲周期PWM_T(max)=256*中断定时时间(1ms)


  11. //PWM物理地址通道定义,物理地址根据需要自由定义
  12. sbit PWM_IO0 = P1^0;//接电机NO.1
  13. sbit PWM_IO1 = P1^1;//接电机NO.2
  14. sbit PWM_IO2 = P1^2;//接电机NO.3
  15. sbit PWM_IO3 = P1^3;//接电机NO.4


  16. //PWM脉冲占空比
  17. uint PWM_IO0_ZKB=20;  //脉冲占空比,0~255,=0时输出最大
  18. uint PWM_IO1_ZKB=20;
  19. uint PWM_IO2_ZKB=20;
  20. uint PWM_IO3_ZKB=20;


  21. /*---------------------------------------------------------*/


  22. sbit s0 = P3^6; //按s0减小占空比
  23. sbit s1 = P3^7;//按s1增加占空比


  24. sbit RL = P3^5;//按健 正反转
  25. sbit RUN_STOP = P3^4;//按健启动与停止


  26. sbit RL1 = P3^3;//输出 正反转
  27. sbit RUN_STOP1 = P3^2;//输出 启动与停止


  28. uint KG;//开关
  29. uint FX;//方向




  30. void Delay1ms(uint a)                //@11.0592MHz
  31. {
  32.         unsigned char i, j;


  33.       
  34.         i = 2;
  35.         j = 199;
  36.         do
  37.         {
  38.                 while (--j);
  39.         } while (--i);
  40. }






  41. /*---------------定时器2初始化-------------------*/
  42. void timer2_init()//定时器2初始化
  43. {
  44.         RCAP2H=0xff;  //16位计数器,定时39us
  45.         RCAP2L=0xdc;  //X=0xffdc=65500;T=(65536-X)*机器周期(11.0592MHz,1.085us)
  46.         //TH2=RCAP2H;     //会自动重装
  47.         //TL2=RCAP2L;
  48.         T2CON=0;
  49.         T2MOD=0;
  50.         EA=1;
  51.         ET2=1;
  52.         TR2=1;
  53. }


  54. /*--------------定时器2中断服务程序----------------------------*/
  55. void timer2() interrupt 5
  56. {      
  57.         TF2=0; //注意:定时器2必须由软件对溢出标志位清零,
  58.                //这里与定时器0和定时器1不同
  59.         //PWM处理
  60.            PWM_T++;
  61.         if(PWM_T == 255)//取到最大值
  62.         {PWM_T = PWM_IO0 = PWM_IO1 = PWM_IO2 = PWM_IO3 = 0;}        //所有通道脉冲拉至低电平
  63.       
  64.         //通道脉冲电平拉高
  65.         if(PWM_T == PWM_IO0_ZKB)  //通道0脉冲得高电平
  66.                 PWM_IO0 = 1;      
  67.       
  68.         if(PWM_T == PWM_IO1_ZKB)  //通道1脉冲得高电平
  69.                 PWM_IO1 = 1;
  70.       
  71.         if(PWM_T == PWM_IO2_ZKB)  //通道2脉冲得高电平
  72.         PWM_IO2 = 1;
  73.                
  74.         if(PWM_T == PWM_IO3_ZKB)  //通道3脉冲得高电平
  75.                 PWM_IO3 = 1;      
  76. }
  77. /**
  78. * 等待繁忙标志
  79. */
  80. void wait(void)
  81. {
  82.         P0 = 0xFF;
  83.       
  84.         do
  85.         {
  86.                 RS = 0;
  87.                 RW = 1;
  88.                 EN = 0;
  89.                 EN = 1;
  90.         }while (STA7 == 1);
  91.         EN = 0;
  92. }


  93. /**
  94. * 写数据
  95. */
  96. void w_dat(uint dat)
  97. {
  98.         wait();
  99.         EN = 0;
  100.         P0 = dat;
  101.         RS = 1;
  102.         RW = 0;
  103.         EN = 1;
  104.         EN = 0;
  105. }


  106. /**
  107. * 写命令
  108. */
  109. void w_cmd(uint cmd)
  110. {
  111.         wait();
  112.         EN = 0;
  113.         P0 = cmd;
  114.         RS = 0;
  115.         RW = 0;
  116.         EN = 1;
  117.         EN = 0;
  118. }


  119. /**
  120. * 发送字符串到LCD
  121. */
  122. void write_zfc(uchar *p)//定义一个带指针的函数?(字符串)
  123. {
  124.         while(*p!=0)//不能用";"
  125.         w_dat(*p++);
  126. }


  127. /**
  128. * 初始化1602
  129. */
  130. void Init_LCD1602(void)
  131. {
  132.         w_cmd(0x38);  // 16*2显示,5*7点阵,8位数据接口
  133.         w_cmd(0x0C);  // 显示器开、光标开、光标允许闪烁
  134.         w_cmd(0x06);  // 文字不动,光标自动右移
  135.         w_cmd(0x01);  // 清屏
  136. }


  137. void KEY()//
  138.   {
  139.   if(s0==0) //按s0减小占空比
  140.                 {
  141.                 while(!s0);//等待
  142.                         {
  143.                               
  144.                                         PWM_IO0_ZKB = PWM_IO0_ZKB-1;  
  145.                                         PWM_IO1_ZKB = PWM_IO1_ZKB-1;
  146.                                         PWM_IO2_ZKB = PWM_IO2_ZKB-1;
  147.                                         PWM_IO3_ZKB = PWM_IO3_ZKB-1;                              
  148.                        
  149.                         }
  150.                         if(PWM_IO0_ZKB<=20)PWM_IO0_ZKB=20;//太小不能启动
  151.                        
  152.                        
  153.                 }
  154.                 if(s1==0)  //按s1增加占空比
  155.                 {
  156.                         while(!s1);//等待
  157.                         {                       
  158.                                         PWM_IO0_ZKB = PWM_IO0_ZKB+1;  
  159.                                         PWM_IO1_ZKB = PWM_IO1_ZKB+1;
  160.                                         PWM_IO2_ZKB = PWM_IO2_ZKB+1;
  161.                                         PWM_IO3_ZKB = PWM_IO3_ZKB+1;                                       
  162.                                                                
  163.                         }
  164.                         if(PWM_IO0_ZKB>100)PWM_IO0_ZKB=100;//太大不能启动                       
  165.                 }

  166.           if(RL==0)  //按RL
  167.                 {
  168.                         Delay1ms(2);
  169.                         if(RL==0)  //按RL
  170.                  while(!RL);//等待按健松手
  171.                  RL1=~RL1;//取反(=1正转,=0反转)
  172.                 }
  173.            if(RUN_STOP==0)  //按启停
  174.                 {
  175.                        
  176.                         Delay1ms(2);
  177.                         if(RUN_STOP==0)  //按启停
  178.                        
  179.                  while(!RUN_STOP);//等待按健松手
  180.                  RUN_STOP1=~RUN_STOP1;//取反(=1启动,=0停止)                                       
  181.                 }


  182.   }
  183. /*------------------------------------------------
  184.                     定时器初始化子程序
  185. ------------------------------------------------*/
  186. void Init_Timer1(void)
  187. {
  188. TMOD |= 0x10;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
  189. TH1=0x00;              //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
  190. TL1=0x00;
  191. EA=1;            //总中断打开
  192. ET1=1;           //定时器中断打开
  193. TR1=1;           //定时器开关打开
  194. }
  195. /*------------------------------------------------
  196.                     定时器初始化子程序
  197. ------------------------------------------------*/
  198. void Init_Timer0(void)
  199. {
  200. TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
  201. TH0=0x00;              //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
  202. TL0=0x00;
  203. EA=1;            //总中断打开
  204. ET0=1;           //定时器中断打开
  205. TR0=1;           //定时器开关打开
  206. }


  207. void PIAY(void)////显示运行状态
  208. {
  209. if(RUN_STOP1==1)
  210.                 {
  211.     w_cmd(0xC0);//LCD1602显示地址为第一排第一个
  212.                 write_zfc("RUN");      
  213.                 }      
  214.                 else
  215.                 {
  216.     w_cmd(0xC0);//LCD1602显示地址为第一排第一个
  217.                 write_zfc("OFF");
  218.                 }      
  219. if(RL1==0)
  220.                 {
  221.     w_cmd(0xC0+4);//LCD1602显示地址为第一排第一个
  222.                 write_zfc("<<--");                       
  223.                 }      
  224.                 else
  225.                 {
  226.     w_cmd(0xC0+4);//LCD1602显示地址为第一排第一个
  227.                 write_zfc("-->>");
  228.                 }      
  229.         }
  230. /*------------主函数---------------*/
  231. void main()
  232. {
  233.         timer2_init();//定时器2初始化
  234.   Init_LCD1602();   //LCD1602初始化
  235.         Init_Timer0();//定时器0初始化
  236.         Init_Timer1();//定时器1初始化
  237.       
  238.         RL1=1;//初始化=1,开机电机正转
  239.         RUN_STOP1=1;//初始化=1,开机电机转动
  240.                
  241.         while(1)
  242.         {
  243.              KEY();//按健扫描      
  244.                  PIAY();//显示运行状态
  245.                         
  246.                  
  247.                 w_cmd(0x80);//LCD1602显示地址为第一排第一个
  248.                 write_zfc("PWM:");               
  249.                 //w_dat(PWM_IO0_ZKB/1000+0x30);
  250.                 w_dat(PWM_IO0_ZKB%1000/100+0x30);
  251.                 w_dat(PWM_IO0_ZKB%100/10+0x30);
  252.                 w_dat(PWM_IO0_ZKB%10+0x30);
  253.                 //write_zfc(" KHz");
  254.                
  255.                
  256.                 w_cmd(0xc0+9);//LCD1602显示地址为第一排第一个
  257.                 write_zfc("FX:");
  258.                
  259.                 //w_dat(PWM_IO0_ZKB/1000+0x30);
  260.                 w_dat(FX%1000/100+0x30);
  261.                 w_dat(FX%100/10+0x30);
  262.                 w_dat(FX%10+0x30);
  263.                
  264.                 w_cmd(0x80+9);//LCD1602显示地址为第一排第一个
  265.                 write_zfc("KG:");
  266.                
  267.                 //w_dat(PWM_IO0_ZKB/1000+0x30);
  268.                 w_dat(KG%1000/100+0x30);
  269.                 w_dat(KG%100/10+0x30);
  270.                 w_dat(KG%10+0x30);
  271.                
  272.         }
  273. }
  274. /*------------------------------------------------
  275.                  定时器中断子程序
  276. ------------------------------------------------*/
  277. void Timer1_isr(void) interrupt 3 using 1
  278. {
  279. TH1=0x00;                 //重新赋值
  280. TL1=0x00;
  281.         FX++;//运行方向调节
  282.         if(FX>30)
  283.         {
  284.         FX=0;
  285.         //RUN_STOP1=~RUN_STOP1;//取反(=1启动,=0停止)
  286.   省去几多行…………
复制代码

全部资料51hei下载地址:
1602显并STC89机器人电机PWM控器OK3.zip (54.21 KB, 下载次数: 80)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:614355 发表于 2019-9-21 11:21 | 只看该作者
很详细的程序
回复

使用道具 举报

板凳
ID:521117 发表于 2019-9-27 22:21 | 只看该作者
学习学习
回复

使用道具 举报

地板
ID:921641 发表于 2021-10-24 10:15 | 只看该作者
楼主你好,我用的是STC89C58RD单片机,在使用3个定时器中断功能时,发现通过中断控制引脚输出高低电平会出现紊乱的情况;
比如定时器0是50毫秒中断,定时器1是10毫秒中断,定时器2是1毫秒中断
然后第一个灯用定时器0控制是中断20次,亮灭交替,也就是每1秒交替闪烁;
第二个灯用定时器1控制是中断50次,亮灭交替,也就是每500毫秒交替闪烁;
第三个灯用定时器2控制,是中断100次,亮灭交替,也就是100毫秒交替闪烁。
然而实际下载到单片机运行时,发现第1个灯竟然比第二个灯闪烁还要快!!
而且第三个灯闪烁的频率远高于100毫秒,我把计数变量提高100倍才差不多。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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