8044|3

4

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

51单片机舵机控制程序 [复制链接]

前两天偶然要用到舵机,试着写了一下,结果很不理想,网上搜罗了半天也是没有好的方法,要么只能转固定的角度要么要用到两个定时器,非常占用资源。
因为一直以来用着arduino所以就研究了一下Servo的库,官方只介绍了用法,具体该如何实现却没有说明,最后只得研究其核心代码Servo.cpp,结果在这里有了一点收获Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
知道了用16位定时器,那么如何实现驱动多个舵机呢,研究了一下代码(水平不够没看懂,汗!!),不得已只有暴力破解了。
最后搬出了示波器,按照介绍直接用arduino定义了8个舵机逐个分析,搞明白了,激动。arduino的servo库是用一个16位定时器,将每个舵机的角度映射为相应的高电平时间,然后逐次设为溢出时间。比如51的(12M晶振为例)20ms周期那么值为20000,如果一个舵机转最大角度180度,那么高电平值为2500(2.5ms),20000/2500=8,因此可定义八个舵机。(个人愚见,arduino的servo库说支持12个,但是示波器显示周期已经变为26ms,所以个人觉得很不靠谱)
具体的细节就不多讨论了,下面附上我的代码大家自行理解吧。欢迎大神的批评指导,这个也只是原始的代码。
应用:
  1. <font color="#008000">#include<reg52.h>

  2. typedef unsigned int uint;
  3. typedef unsigned char uchar;

  4. extern void Servo(char ServoNumber, int Servo_Angle);

  5. void delay_ms(uint x)
  6. {
  7.         uint i;
  8.         while(x--) for(i=0;i<125;i++);
  9. }

  10. void main(void)
  11. {
  12.         uint i = 0;
  13.        
  14. //         Servo(0, 0);
  15. //         while(1);
  16.        
  17.         while(1){
  18.                 for(i = 0; i <= 180; i++){
  19.                                 Servo(0, i);
  20.                                 Servo(1, i);
  21.                                 Servo(2, i);
  22.                                 Servo(3, i);
  23.                                 Servo(4, i);
  24.                                 Servo(5, i);
  25.                                 Servo(6, i);
  26.                                 Servo(7, i);
  27.                                 delay_ms(50);
  28.                 }
  29.         }
  30. }</font>
复制代码
实现方法:
  1. /*
  2.         £¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡
  3.         Servo ½«Õ¼óö¨ê±Æ÷ 0
  4. */
  5. #include <reg52.h>
  6. /************************************************/
  7. /*
  8.         Set the two selection below, before to build!!!!
  9. */
  10. //Set the output pin
  11. sbit servo_0 = P1^0;                //Servo Signal Output Pin
  12. sbit servo_1 = P1^1;
  13. sbit servo_2 = P1^2;
  14. sbit servo_3 = P1^3;
  15. sbit servo_4 = P1^4;
  16. sbit servo_5 = P1^5;
  17. sbit servo_6 = P1^6;
  18. sbit servo_7 = P1^7;

  19. //Set Servo Amount
  20. unsigned char ServoAmount = 8;

  21. //Select the KDS Mode
  22. bit KDS12M = 0;                //if 1: 12MHz,else 0: 11.0592Mhz

  23. /************************************************/
  24. unsigned char Timer_cycle = 0;

  25. bit ServoNotWorking = 1;

  26. unsigned int Servo_HeighTime = 0;
  27. unsigned int Servo_LowTime = 0;

  28. unsigned char ServoAngle[8];
  29. unsigned int Servo_HeighTimeValue[9];                //Servo_HeighTimeValue[8] store the Servo_LowTime

  30. void init_ServoAngle(){
  31.         //Set the star angle
  32.         ServoAngle[0] = 90;
  33.         ServoAngle[1] = 90;
  34.         ServoAngle[2] = 90;
  35.         ServoAngle[3] = 90;
  36.         ServoAngle[4] = 90;
  37.         ServoAngle[5] = 90;
  38.         ServoAngle[6] = 90;
  39.         ServoAngle[7] = 90;
  40. }

  41. long map(long x, long in_min, long in_max, long out_min, long out_max)
  42. {
  43.         return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  44. }

  45. void setServoValue(){
  46.         char i = 0;
  47.         Servo_HeighTime = 0;
  48.         if(KDS12M){
  49.                 for(i = 0; i < ServoAmount; i++){
  50.                         Servo_HeighTimeValue[i] = map(ServoAngle[i], 0, 180, 0, 2000) + 470;        //0~180¶è->0~2000us + 3õê¼μÄ500us(470)
  51.                         Servo_HeighTime += Servo_HeighTimeValue[i];
  52.                         Servo_LowTime = 19520 - Servo_HeighTime;                //19520μ÷ÕûÖüÆú
  53.                 }       
  54.         }
  55.         else {
  56.                 for(i = 0; i < ServoAmount; i++){
  57.                         Servo_HeighTimeValue[i] = map(ServoAngle[i], 0, 180, 0, 1850) + 427;        //0~180¶è->0~2000us + 3õê¼μÄ500us(470)
  58.                         Servo_HeighTime += Servo_HeighTimeValue[i];
  59.                         Servo_LowTime = 17880 - Servo_HeighTime;                //17880μ÷ÕûÖüÆú
  60.                 }
  61.         }
  62.         Servo_HeighTimeValue[8] = Servo_LowTime;
  63. }

  64. void InitServoTimer(){
  65.         TMOD &= 0xf1;                //°′λó룬2»ó°ÏìÆäËû¶¨ê±Æ÷éèÖÃ
  66.         TH0  = -Servo_HeighTimeValue[0] / 256;
  67.         TL0  = -Servo_HeighTimeValue[0] % 256;
  68.         EA   = 1;
  69.         ET0  = 1;
  70.         TR0  = 0;
  71. }

  72. void timer0() interrupt 1 {
  73.         switch(Timer_cycle){
  74.                 case 0:                                                  servo_0 = 1; break;
  75.                 case 1: servo_0 = 0; servo_1 = 1; break;
  76.                 case 2: servo_1 = 0; servo_2 = 1; break;
  77.                 case 3: servo_2 = 0; servo_3 = 1; break;
  78.                 case 4: servo_3 = 0; servo_4 = 1; break;
  79.                 case 5: servo_4 = 0; servo_5 = 1; break;
  80.                 case 6: servo_5 = 0; servo_6 = 1; break;
  81.                 case 7: servo_6 = 0; servo_7 = 1; break;
  82.                 case 8: servo_7 = 0;                                                         break;
  83.         }
  84.         TH0 = -Servo_HeighTimeValue[Timer_cycle] / 256;
  85.         TL0 = -Servo_HeighTimeValue[Timer_cycle] % 256;
  86.         Timer_cycle++;
  87.         if(Timer_cycle > ServoAmount){
  88.                 Timer_cycle = 0;
  89.         }
  90. }

  91. /* The Main Servo Funtion */

  92. /*
  93.         *ServoNumber :¶æ»úμÄDòoÅ
  94.         *Servo_Angle :¶æ»úμĽǶè
  95. */

  96. void Servo(char ServoNumber, int Servo_Angle){
  97.         //3õê¼»ˉ
  98.         if (ServoNotWorking){
  99.                 ServoNotWorking = 0;
  100.                 init_ServoAngle();
  101.                 setServoValue();
  102.                 InitServoTimer();
  103.                 P1 = 0x00;
  104.                 servo_0 = 0;
  105.                 servo_1 = 0;
  106.                 servo_2 = 0;
  107.                 servo_3 = 0;
  108.                 servo_4 = 0;
  109.                 servo_5 = 0;
  110.                 servo_6 = 0;
  111.                 servo_7 = 0;
  112.                 TR0  = 1;
  113.         }
  114.         //ÖØéè2Îêy
  115.         ServoAngle[ServoNumber] = Servo_Angle;               
  116.         setServoValue();       
  117. }


复制代码
(因为用的ARM版的Keil汉字编码问题,汉语注释无法显示)





此帖出自51单片机论坛

最新回复

本帖最后由 philipchiu 于 2016-7-31 00:57 编辑 觉得你是否把简单事情复杂化,觉得你可以用mcu模拟红外发送方法去实现,本论坛就有相关帖子。另外keik4以上可以设置更改语言  详情 回复 发表于 2016-7-31 00:19
点赞 关注
 

回复
举报

157

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
使用中文编码
此帖出自51单片机论坛
 
 
 

回复

216

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
本帖最后由 philipchiu 于 2016-7-31 00:57 编辑

觉得你是否把简单事情复杂化,觉得你可以用mcu模拟红外发送方法去实现,本论坛就有相关帖子。另外keik4以上可以设置更改语言
此帖出自51单片机论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(中级)

4
 
philipchiu 发表于 2016-7-31 00:19
觉得你是否把简单事情复杂化,觉得你可以用mcu模拟红外发送方法去实现,本论坛就有相关帖子。另外keik4以上 ...

我没有翻到相关的帖子,这个程序还是相当粗糙的,日后我会完善的,但是我确实不知道其他的更好的想法(不是代码,而是思路),能否详细的说一下,或者是链接,谢谢
此帖出自51单片机论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表