前两天偶然要用到舵机,试着写了一下,结果很不理想,网上搜罗了半天也是没有好的方法,要么只能转固定的角度要么要用到两个定时器,非常占用资源。
因为一直以来用着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,所以个人觉得很不靠谱)
具体的细节就不多讨论了,下面附上我的代码大家自行理解吧。欢迎大神的批评指导,这个也只是原始的代码。
应用:
- <font color="#008000">#include<reg52.h>
- typedef unsigned int uint;
- typedef unsigned char uchar;
- extern void Servo(char ServoNumber, int Servo_Angle);
- void delay_ms(uint x)
- {
- uint i;
- while(x--) for(i=0;i<125;i++);
- }
- void main(void)
- {
- uint i = 0;
-
- // Servo(0, 0);
- // while(1);
-
- while(1){
- for(i = 0; i <= 180; i++){
- Servo(0, i);
- Servo(1, i);
- Servo(2, i);
- Servo(3, i);
- Servo(4, i);
- Servo(5, i);
- Servo(6, i);
- Servo(7, i);
- delay_ms(50);
- }
- }
- }</font>
复制代码 实现方法:- /*
- £¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡
- Servo ½«Õ¼óö¨ê±Æ÷ 0
- */
- #include <reg52.h>
- /************************************************/
- /*
- Set the two selection below, before to build!!!!
- */
- //Set the output pin
- sbit servo_0 = P1^0; //Servo Signal Output Pin
- sbit servo_1 = P1^1;
- sbit servo_2 = P1^2;
- sbit servo_3 = P1^3;
- sbit servo_4 = P1^4;
- sbit servo_5 = P1^5;
- sbit servo_6 = P1^6;
- sbit servo_7 = P1^7;
- //Set Servo Amount
- unsigned char ServoAmount = 8;
- //Select the KDS Mode
- bit KDS12M = 0; //if 1: 12MHz,else 0: 11.0592Mhz
- /************************************************/
- unsigned char Timer_cycle = 0;
- bit ServoNotWorking = 1;
- unsigned int Servo_HeighTime = 0;
- unsigned int Servo_LowTime = 0;
- unsigned char ServoAngle[8];
- unsigned int Servo_HeighTimeValue[9]; //Servo_HeighTimeValue[8] store the Servo_LowTime
- void init_ServoAngle(){
- //Set the star angle
- ServoAngle[0] = 90;
- ServoAngle[1] = 90;
- ServoAngle[2] = 90;
- ServoAngle[3] = 90;
- ServoAngle[4] = 90;
- ServoAngle[5] = 90;
- ServoAngle[6] = 90;
- ServoAngle[7] = 90;
- }
- long map(long x, long in_min, long in_max, long out_min, long out_max)
- {
- return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
- }
- void setServoValue(){
- char i = 0;
- Servo_HeighTime = 0;
- if(KDS12M){
- for(i = 0; i < ServoAmount; i++){
- Servo_HeighTimeValue[i] = map(ServoAngle[i], 0, 180, 0, 2000) + 470; //0~180¶è->0~2000us + 3õê¼μÄ500us(470)
- Servo_HeighTime += Servo_HeighTimeValue[i];
- Servo_LowTime = 19520 - Servo_HeighTime; //19520μ÷ÕûÖüÆú
- }
- }
- else {
- for(i = 0; i < ServoAmount; i++){
- Servo_HeighTimeValue[i] = map(ServoAngle[i], 0, 180, 0, 1850) + 427; //0~180¶è->0~2000us + 3õê¼μÄ500us(470)
- Servo_HeighTime += Servo_HeighTimeValue[i];
- Servo_LowTime = 17880 - Servo_HeighTime; //17880μ÷ÕûÖüÆú
- }
- }
- Servo_HeighTimeValue[8] = Servo_LowTime;
- }
- void InitServoTimer(){
- TMOD &= 0xf1; //°′λó룬2»ó°ÏìÆäËû¶¨ê±Æ÷éèÖÃ
- TH0 = -Servo_HeighTimeValue[0] / 256;
- TL0 = -Servo_HeighTimeValue[0] % 256;
- EA = 1;
- ET0 = 1;
- TR0 = 0;
- }
- void timer0() interrupt 1 {
- switch(Timer_cycle){
- case 0: servo_0 = 1; break;
- case 1: servo_0 = 0; servo_1 = 1; break;
- case 2: servo_1 = 0; servo_2 = 1; break;
- case 3: servo_2 = 0; servo_3 = 1; break;
- case 4: servo_3 = 0; servo_4 = 1; break;
- case 5: servo_4 = 0; servo_5 = 1; break;
- case 6: servo_5 = 0; servo_6 = 1; break;
- case 7: servo_6 = 0; servo_7 = 1; break;
- case 8: servo_7 = 0; break;
- }
- TH0 = -Servo_HeighTimeValue[Timer_cycle] / 256;
- TL0 = -Servo_HeighTimeValue[Timer_cycle] % 256;
- Timer_cycle++;
- if(Timer_cycle > ServoAmount){
- Timer_cycle = 0;
- }
- }
- /* The Main Servo Funtion */
- /*
- *ServoNumber :¶æ»úμÄDòoÅ
- *Servo_Angle :¶æ»úμĽǶè
- */
- void Servo(char ServoNumber, int Servo_Angle){
- //3õê¼»ˉ
- if (ServoNotWorking){
- ServoNotWorking = 0;
- init_ServoAngle();
- setServoValue();
- InitServoTimer();
- P1 = 0x00;
- servo_0 = 0;
- servo_1 = 0;
- servo_2 = 0;
- servo_3 = 0;
- servo_4 = 0;
- servo_5 = 0;
- servo_6 = 0;
- servo_7 = 0;
- TR0 = 1;
- }
- //ÖØéè2Îêy
- ServoAngle[ServoNumber] = Servo_Angle;
- setServoValue();
- }
复制代码 (因为用的ARM版的Keil汉字编码问题,汉语注释无法显示)