低端单片机(8bit)的16路舵机调速分析与实现
By 马冬亮(凝霜 Loki)
一个人的战争(http://blog.csdn.net/MDL13412)
今年的英特尔杯准备做机器人方向,所以在淘宝上买了机器人套件,自己进行组装和编程。机器人装配完如下图所示:
(注:这款机器人由17路舵机组成,其中左右手各2路,左右腿各4路,身体4路,头部1路。)
装配好机器人,首要任务就是让机器人运动起来。看了一下卖家给的控制程序,写的很混乱,维护极差,于是准备自己写一套控制程序,也算是给学弟学妹们留下的一份礼物吧^_^。
首先简单介绍一下我们使用的舵机参数:
由于是控制机器人,所以我对转角范围的需求是0~180度,那么舵机由0度转到180度需要至少0.6s的时间。
舵机的调速原理其实很简单,通过给定连续的PWM信号,舵机就可以旋转到相应的角度。我们的这款舵机和竞赛的通用舵机基本一致,PWM周期为20ms,复位需要T1=0.5ms的高电平,T2=(20 - 0.5)ms的低电平。每增加1度,需要在T1的基础上加10us。为了让舵机完整的转到对应角度,我们需要至少对舵机连续送0.6s的PWM信号。
由于舵机调速对PWM精度要求很高,传统的12T 8051单片机每个指令周期占12个机器周期,速度不能达到要求。我们选择了STC12C5A60S2这款单片机,这款单片机较传统的12T 8051快至少6倍以上,并配合24MHZ的晶振来控制机器人。
舵机调速一般有两种方法,一种是使用定时器中断进行调速,另外一种是使用软件延时进行调速。
首先分析定时器中断调速的方法:
我的调速精度要求是1度,所以定时器需要定时10us,那么,每200次定时器中断完成一个PWM调速周期。这种编程方式的优点是实现简单,代码容易读懂。其缺点是只能处理少数舵机,不能对大量舵机进行调速。因为每10us发生一次定时中断,而每个机器周期为(1 * 1000 * 1000) / (24 * 1000 * 1000)=0.0417us,则在每个定时器中断中有10 / 0.0417=240个指令周期。我们看下面的程序:
- #include <STC_NEW_8051.H>
- void main()
- {
- volatile int cnt = 0;
- volatile int pwm = 0;
- volatile int pwmCycle = 10;
- cnt = (cnt + 1) % 40;
- if (++cnt < pwmCycle)
- pwm = 1;
- else
- pwm = 0;
- }
- C:0x0097 F50C MOV 0x0C,A 3
- C:0x0099 750D0A MOV 0x0D,#0x0A 3
- C:0x009C E509 MOV A,0x09 2
- C:0x009E 2401 ADD A,#0x01 2
- C:0x00A0 FF MOV R7,A 2
- C:0x00A1 E4 CLR A 1
- C:0x00A2 3508 ADDC A,0x08 3
- C:0x00A4 FE MOV R6,A 2
- C:0x00A5 7C00 MOV R4,#0x00 2
- C:0x00A7 7D28 MOV R5,#0x28 2
- C:0x00A9 120003 LCALL C?SIDIV(C:0003)
- C:0x00AC 8C08 MOV 0x08,R4 3
- C:0x00AE 8D09 MOV 0x09,R5 3
- C:0x00B0 0509 INC 0x09 4
- C:0x00B2 E509 MOV A,0x09 2
- C:0x00B4 7002 JNZ C:00B8 3
- C:0x00B6 0508 INC 0x08 4
- C:0x00B8 AE08 MOV R6,0x08 4
- C:0x00BA C3 CLR C 1
- C:0x00BB 950D SUBB A,0x0D 3
- C:0x00BD E50C MOV A,0x0C 2
- C:0x00BF 6480 XRL A,#P0(0x80) 2
- C:0x00C1 F8 MOV R0,A 2
- C:0x00C2 EE MOV A,R6 1
- C:0x00C3 6480 XRL A,#P0(0x80) 2
- C:0x00C5 98 SUBB A,R0 2
- C:0x00C6 5007 JNC C:00CF 3
- C:0x00C8 750A00 MOV 0x0A,#0x00 3
- C:0x00CB 750B01 MOV 0x0B,#0x01 3
- //C:0x00CE 22 RET
- 多个if情况时这里应该是一个跳转 3
- C:0x00CF E4 CLR A 1
- C:0x00D0 F50A MOV 0x0A,A 3
- C:0x00D2 F50B MOV 0x0B,A 3
接下来我们来分析软件延时的方法进行调速,首先我们需要一个延时函数,那么我们定义一个延时10us的函数如下所示:
- void Delay10us(UINT16 ntimes)
- {
- for (delayVar1 = 0; delayVar1 < ntimes; ++delayVar1)
- for (delayVar2 = 0; delayVar2 < 21; ++delayVar2)
- _nop_();
- }
同时对8路舵机进行调速的话,我们首先需要对舵机的调速角度进行排序(升序),然后计算出两两舵机舵机的差值,这样就可以同时对8路舵机进行调速了。对于出现的非法角度,我们给这路舵机送全为高电平的PWM信号,使此路舵机保持先前状态。代码如下所示:
- void InitPwmPollint()
- {
- UCHAR8 i;
- UCHAR8 j;
- UCHAR8 k;
- UINT16 temp;
- for (i = 0; i < USED_PIN; ++i)
- {
- for (j = 0; j < 7; ++j)
- {
- for (k = j; k < 8; ++k)
- {
- if (g_diffAngle[i][j] > g_diffAngle[i][k])
- {
- temp = g_diffAngle[i][j];
- g_diffAngle[i][j] = g_diffAngle[i][k];
- g_diffAngle[i][k] = temp;
- temp = g_diffAngleMask[i][j];
- g_diffAngleMask[i][j] = g_diffAngleMask[i][k];
- g_diffAngleMask[i][k] = temp;
- }
- }
- }
- }
- for (i = 0; i < USED_PIN; ++i)
- {
- for (j = 0; j < 8; ++j)
- {
- if (INVALID_JOINT_VALUE == g_diffAngle[i][j])
- {
- g_diffAngle[i][j] = STEERING_ENGINE_FULL_CYCLE;
- }
- }
- }
- for (i = 0; i < USED_PIN; ++i)
- {
- for (j = 7; j >= 1; --j)
- {
- g_diffAngle[i][j] = g_diffAngle[i][j] - g_diffAngle[i][j - 1];
- }
- }
- }
下面我们举例说明上述代码,假设 g_diffAngle[0][] = {10, 20, 40, 40, 50, 80, 90, 10},那么经过排序后,其变为g_diffAngle[0][] = {10, 10, 20, 40, 40, 50, 80, 90},而g_diffAngleMask[0][]中的值对应个角度使用的管脚的掩码,例如P0.0,则其掩码为0x01,对P0 & 0x01进行掩码计算,就可以对指定的管脚进行操作。我们对角度排序的同时,需要更新管脚的掩码,以达到相互对应的目的。
接下来对角度进行校验,对于不合法的角度,我们使用STEERING_ENGINE_FULL_CYCLE来进行填充,使这路舵机在PWM调速周期内全为高电平。
最后计算差值,计算后g_diffAngle[0][]={10, 0, 10, 20, 0, 10, 30, 10},这样就求出了后面的舵机相对于其前面一路的差值。我们对g_diffAngle[0][0]对应的舵机延时Delay10us(g_diffAngle[0][0])即Delay10us(10),延时完成后我们将这路舵机给低电平,这用到了前面定义的掩码操作。延时完成后,开始延时g_diffAngle[0][1]对应的舵机,Delay10us(g_diffAngle[0][1])即Delay10us(0),然后将此路舵机送低电平。再延时Delay10us(g_diffAngle[0][2])即Delay10us(10),然后再移除,依次类推。这样就能保证在一个PWM周期内对8路舵机同时调速。调速部分代码如下:
- #define PWM_STEERING_ENGINE(group) \
- { \
- counter = STEERING_ENGINE_INIT_DELAY; \
- for (i = 0; i < 8; ++i) \
- counter += g_diffAngle[PIN_GROUP_##group][i]; \
- \
- for (i = 0; i < 30; ++i) \
- { \
- GROUP_##group##_CONTROL_PIN = 0xFF; \
- Delay10us(STEERING_ENGINE_INIT_DELAY); \
- \
- for (j = 0; j < 8; ++j) \
- { \
- Delay10us(g_diffAngle[PIN_GROUP_##group][j]); \
- GROUP_##group##_CONTROL_PIN &= ~(g_diffAngleMask[PIN_GROUP_##group][j]); \
- } \
- \
- Delay10us(STEERING_ENGINE_CYCLE - counter); \
- } \
- }
- while (1)
- {
- PWM_STEERING_ENGINE(1);
- }
总结:
对于只有1、2路舵机的情况,我们可以使用定时器中断进行调速,其具有实现简单,通俗易懂的有点。而对于多路舵机的情形,就需要使用软件延时进行操作,其优点是可以同时对8路舵机进行调速,效率高,但是其代码不容易实现与调试。
附完整程序:
(注:由于需求变动很大,包括功能和管脚分配等,所以本程序大量使用宏及enum)
- /**
- * @file ControlRobot.h
- * @author 马冬亮
- * @brief 用于对机器人进行控制.
- */
- #ifndef CONTROLROBOT_H
- #define CONTROLROBOT_H
- /**
- * @brief 关节角度非法值.
- * @ingroup ControlRobot
- *
- * @details 当关节角度无法确定或捕获关节失败时, 设置为此数值, 机器人接收到此数值则不转动舵机.
- */
- #define INVALID_JOINT_VALUE 200
- /**
- * @brief 定义关节常量用于存取关节角度.
- * @ingroup ControlRobot
- */
- typedef enum RobotJoint
- {
- ROBOT_LEFT_SHOULDER_VERTICAL = 0, ///< 左肩膀, 前后转动的舵机
- ROBOT_LEFT_SHOULDER_HORIZEN = 1, ///< 左肩膀, 上下转动的舵机
- ROBOT_LEFT_ELBOW = 2, ///< 左肘, 左臂肘关节的舵机
- ROBOT_RIGHT_SHOULDER_VERTICAL = 3, ///< 右肩膀, 前后转动的舵机
- ROBOT_RIGHT_SHOULDER_HORIZEN = 4, ///< 右肩膀, 上下转动的舵机
- ROBOT_RIGHT_ELBOW = 5, ///< 右肘, 右臂肘关节的舵机
- ROBOT_LEFT_HIP_VERTICAL = 6, ///< 左髋, 左右转动的舵机
- ROBOT_LEFT_HIP_HORIZEN = 7, ///< 左髋, 前后转动的舵机
- ROBOT_LEFT_KNEE = 8, ///< 左膝盖, 左膝关节的舵机
- ROBOT_LEFT_ANKLE = 9, ///< 左踝, 这个舵机不使用
- ROBOT_RIGHT_HIP_VERTICAL = 10, ///< 右髋, 左右转动的舵机
- ROBOT_RIGHT_HIP_HORIZEN = 11, ///< 右髋, 前后转动的舵机
- ROBOT_RIGHT_KNEE = 12, ///< 右膝盖, 右膝关节的舵机
- ROBOT_RIGHT_ANKLE = 13, ///< 右踝, 这个舵机不使用
- ROBOT_LEFT_FOOT = 14, ///< 左脚, 这个舵机不使用
- ROBOT_RIGHT_FOOT = 15, ///< 右脚, 这个舵机不使用
- ROBOT_HEAD = 16, ///< 头, 这个舵机不使用
- ROBOT_JOINT_AMOUNT = ROBOT_HEAD + 1
- } RobotJoint;
- typedef enum RobotSteeringEnginePinIndex
- {
- ROBOT_PIN_INDEX_LEFT_SHOULDER_VERTICAL = 0,
- ROBOT_PIN_INDEX_LEFT_SHOULDER_HORIZEN = 1,
- ROBOT_PIN_INDEX_LEFT_ELBOW = 2,
- ROBOT_PIN_INDEX_RIGHT_SHOULDER_VERTICAL = 3,
- ROBOT_PIN_INDEX_RIGHT_SHOULDER_HORIZEN = 4,
- ROBOT_PIN_INDEX_RIGHT_ELBOW = 5,
- ROBOT_PIN_INDEX_LEFT_HIP_VERTICAL = 6,
- ROBOT_PIN_INDEX_RIGHT_HIP_VERTICAL = 7,
- ROBOT_PIN_INDEX_LEFT_HIP_HORIZEN = 0,
- ROBOT_PIN_INDEX_LEFT_KNEE = 1,
- ROBOT_PIN_INDEX_LEFT_ANKLE = 2,
- ROBOT_PIN_INDEX_LEFT_FOOT = 3,
- ROBOT_PIN_INDEX_RIGHT_HIP_HORIZEN = 4,
- ROBOT_PIN_INDEX_RIGHT_KNEE = 5,
- ROBOT_PIN_INDEX_RIGHT_ANKLE = 6,
- ROBOT_PIN_INDEX_RIGHT_FOOT = 7
- } RobotSteeringEnginePinIndex;
- typedef enum RobotSteeringEnginePinMask
- {
- ROBOT_PIN_MASK_LEFT_SHOULDER_VERTICAL = 0x01,
- ROBOT_PIN_MASK_LEFT_SHOULDER_HORIZEN = 0x02,
- ROBOT_PIN_MASK_LEFT_ELBOW = 0x04,
- ROBOT_PIN_MASK_RIGHT_SHOULDER_VERTICAL = 0x08,
- ROBOT_PIN_MASK_RIGHT_SHOULDER_HORIZEN = 0x10,
- ROBOT_PIN_MASK_RIGHT_ELBOW = 0x20,
- ROBOT_PIN_MASK_LEFT_HIP_VERTICAL = 0x40,
- ROBOT_PIN_MASK_RIGHT_HIP_VERTICAL = 0x80,
- ROBOT_PIN_MASK_LEFT_HIP_HORIZEN = 0x01,
- ROBOT_PIN_MASK_LEFT_KNEE = 0x02,
- ROBOT_PIN_MASK_LEFT_ANKLE = 0x04,
- ROBOT_PIN_MASK_LEFT_FOOT = 0x08,
- ROBOT_PIN_MASK_RIGHT_HIP_HORIZEN = 0x10,
- ROBOT_PIN_MASK_RIGHT_KNEE = 0x20,
- ROBOT_PIN_MASK_RIGHT_ANKLE = 0x40,
- ROBOT_PIN_MASK_RIGHT_FOOT = 0x80
- } RobotSteeringEnginePinMask;
- #define PROTOCOL_HEADER "\xC9\xCA"
- #define PROTOCOL_END "\xC9\xCB"
- #define PROTOCOL_END_LENGTH 2
- #define PROTOCOL_HEADER_LENGTH 2
- #define COMMAND_STR_LENGTH (PROTOCOL_HEADER_LENGTH + ROBOT_JOINT_AMOUNT + PROTOCOL_END_LENGTH)
- #define COMMAND_STR_BUFFER_SIZE ((COMMAND_STR_LENGTH) + 2)
- #endif /* CONTROLROBOT_H */
- #include <STC_NEW_8051.H>
- #include "ControlRobot.h"
- #include<intrins.h>
- #define DEBUG_PROTOCOL
- typedef unsigned char UCHAR8;
- typedef unsigned int UINT16;
- #undef TRUE
- #undef FALSE
- #define TRUE 1
- #define FALSE 0
- #define MEMORY_MODEL
- UINT16 MEMORY_MODEL delayVar1;
- UCHAR8 MEMORY_MODEL delayVar2;
- #define BAUD_RATE 0xF3
- #define USED_PIN 2
- #define PIN_GROUP_1 0
- #define PIN_GROUP_2 1
- #define GROUP_1_CONTROL_PIN P0
- #define GROUP_2_CONTROL_PIN P2
- #define STEERING_ENGINE_CYCLE 2000
- #define STEERING_ENGINE_INIT_DELAY 50
- #define STEERING_ENGINE_FULL_CYCLE ((STEERING_ENGINE_CYCLE) - (STEERING_ENGINE_INIT_DELAY))
- volatile UCHAR8 MEMORY_MODEL g_angle[2][ROBOT_JOINT_AMOUNT];
- volatile bit MEMORY_MODEL g_fillingBufferIndex = 0;
- volatile bit MEMORY_MODEL g_readyBufferIndex = 1;
- volatile bit MEMORY_MODEL g_swapBuffer = FALSE;
- volatile UINT16 MEMORY_MODEL g_diffAngle[USED_PIN][8];
- volatile UCHAR8 MEMORY_MODEL g_diffAngleMask[USED_PIN][8] =
- {
- {
- ROBOT_PIN_MASK_LEFT_SHOULDER_VERTICAL,
- ROBOT_PIN_MASK_LEFT_SHOULDER_HORIZEN,
- ROBOT_PIN_MASK_LEFT_ELBOW,
- ROBOT_PIN_MASK_RIGHT_SHOULDER_VERTICAL,
- ROBOT_PIN_MASK_RIGHT_SHOULDER_HORIZEN,
- ROBOT_PIN_MASK_RIGHT_ELBOW,
- ROBOT_PIN_MASK_LEFT_HIP_VERTICAL,
- ROBOT_PIN_MASK_RIGHT_HIP_VERTICAL
- },
- {
- ROBOT_PIN_MASK_LEFT_HIP_HORIZEN,
- ROBOT_PIN_MASK_LEFT_KNEE,
- ROBOT_PIN_MASK_LEFT_ANKLE,
- ROBOT_PIN_MASK_LEFT_FOOT,
- ROBOT_PIN_MASK_RIGHT_HIP_HORIZEN,
- ROBOT_PIN_MASK_RIGHT_KNEE,
- ROBOT_PIN_MASK_RIGHT_ANKLE,
- ROBOT_PIN_MASK_RIGHT_FOOT
- }
- };
- #ifdef DEBUG_PROTOCOL
- sbit P10 = P1 ^ 0; // 正在填充交换区1
- sbit P11 = P1 ^ 1; // 正在填充交换区2
- sbit P12 = P1 ^ 2; // 交换区变换
- sbit P13 = P1 ^ 3; // 协议是否正确
- #endif
- void Delay10us(UINT16 ntimes)
- {
- for (delayVar1 = 0; delayVar1 < ntimes; ++delayVar1)
- for (delayVar2 = 0; delayVar2 < 21; ++delayVar2)
- _nop_();
- }
- void InitPwmPollint()
- {
- UCHAR8 i;
- UCHAR8 j;
- UCHAR8 k;
- UINT16 temp;
- for (i = 0; i < USED_PIN; ++i)
- {
- for (j = 0; j < 7; ++j)
- {
- for (k = j; k < 8; ++k)
- {
- if (g_diffAngle[i][j] > g_diffAngle[i][k])
- {
- temp = g_diffAngle[i][j];
- g_diffAngle[i][j] = g_diffAngle[i][k];
- g_diffAngle[i][k] = temp;
- temp = g_diffAngleMask[i][j];
- g_diffAngleMask[i][j] = g_diffAngleMask[i][k];
- g_diffAngleMask[i][k] = temp;
- }
- }
- }
- }
- for (i = 0; i < USED_PIN; ++i)
- {
- for (j = 0; j < 8; ++j)
- {
- if (INVALID_JOINT_VALUE == g_diffAngle[i][j])
- {
- g_diffAngle[i][j] = STEERING_ENGINE_FULL_CYCLE;
- }
- }
- }
- for (i = 0; i < USED_PIN; ++i)
- {
- for (j = 7; j >= 1; --j)
- {
- g_diffAngle[i][j] = g_diffAngle[i][j] - g_diffAngle[i][j - 1];
- }
- }
- }
- void InitSerialPort()
- {
- AUXR = 0x00;
- ES = 0;
- TMOD = 0x20;
- SCON = 0x50;
- TH1 = BAUD_RATE;
- TL1 = TH1;
- PCON = 0x80;
- EA = 1;
- ES = 1;
- TR1 = 1;
- }
- void OnSerialPort() interrupt 4
- {
- static UCHAR8 previousChar = 0;
- static UCHAR8 currentChar = 0;
- static UCHAR8 counter = 0;
- if (RI)
- {
- RI = 0;
- currentChar = SBUF;
- if (PROTOCOL_HEADER[0] == currentChar) // 协议标志
- {
- previousChar = currentChar;
- }
- else
- {
- if (PROTOCOL_HEADER[0] == previousChar && PROTOCOL_HEADER[1] == currentChar) // 协议开始
- {
- counter = 0;
- previousChar = currentChar;
- g_swapBuffer = FALSE;
- }
- else if (PROTOCOL_END[0] == previousChar && PROTOCOL_END[1] == currentChar) // 协议结束
- {
- previousChar = currentChar;
- if (ROBOT_JOINT_AMOUNT == counter) // 协议接受正确
- {
- if (0 == g_fillingBufferIndex)
- {
- g_readyBufferIndex = 0;
- g_fillingBufferIndex = 1;
- }
- else
- {
- g_readyBufferIndex = 1;
- g_fillingBufferIndex = 0;
- }
- g_swapBuffer = TRUE;
- #ifdef DEBUG_PROTOCOL
- P13 = 0;
- #endif
- }
- else
- {
- g_swapBuffer = FALSE;
- #ifdef DEBUG_PROTOCOL
- P13 = 1;
- #endif
- }
- counter = 0;
- }
- else // 接受协议正文
- {
- g_swapBuffer = FALSE;
- previousChar = currentChar;
- if (counter < ROBOT_JOINT_AMOUNT)
- g_angle[g_fillingBufferIndex][counter] = currentChar;
- ++counter;
- }
- } // if (PROTOCOL_HEADER[0] == currentChar)
- SBUF = currentChar;
- while (!TI)
- ;
- TI = 0;
- } // (RI)
- }
- void FillDiffAngle()
- {
- // 设置舵机要调整的角度
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_LEFT_SHOULDER_VERTICAL];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_LEFT_SHOULDER_HORIZEN];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_ELBOW] = g_angle[g_readyBufferIndex][ROBOT_LEFT_ELBOW];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_SHOULDER_VERTICAL];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_SHOULDER_HORIZEN];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_ELBOW] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_ELBOW];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_HIP_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_LEFT_HIP_VERTICAL];
- g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_HIP_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_HIP_VERTICAL];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_HIP_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_LEFT_HIP_HORIZEN];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_KNEE] = g_angle[g_readyBufferIndex][ROBOT_LEFT_KNEE];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_ANKLE] = g_angle[g_readyBufferIndex][ROBOT_LEFT_ANKLE];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_FOOT] = g_angle[g_readyBufferIndex][ROBOT_LEFT_FOOT];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_HIP_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_HIP_HORIZEN];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_KNEE] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_KNEE];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_ANKLE] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_ANKLE];
- g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_FOOT] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_FOOT];
- // 复位舵机管脚索引
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_VERTICAL] = ROBOT_PIN_MASK_LEFT_SHOULDER_VERTICAL;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_HORIZEN] = ROBOT_PIN_MASK_LEFT_SHOULDER_HORIZEN;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_ELBOW] = ROBOT_PIN_MASK_LEFT_ELBOW;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_VERTICAL] = ROBOT_PIN_MASK_RIGHT_SHOULDER_VERTICAL;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_HORIZEN] = ROBOT_PIN_MASK_RIGHT_SHOULDER_HORIZEN;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_ELBOW] = ROBOT_PIN_MASK_RIGHT_ELBOW;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_HIP_VERTICAL] = ROBOT_PIN_MASK_LEFT_HIP_VERTICAL;
- g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_HIP_VERTICAL] = ROBOT_PIN_MASK_RIGHT_HIP_VERTICAL;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_HIP_HORIZEN] = ROBOT_PIN_MASK_LEFT_HIP_HORIZEN;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_KNEE] = ROBOT_PIN_MASK_LEFT_KNEE;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_ANKLE] = ROBOT_PIN_MASK_LEFT_ANKLE;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_FOOT] = ROBOT_PIN_MASK_LEFT_FOOT;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_HIP_HORIZEN] = ROBOT_PIN_MASK_RIGHT_HIP_HORIZEN;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_KNEE] = ROBOT_PIN_MASK_RIGHT_KNEE;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_ANKLE] = ROBOT_PIN_MASK_RIGHT_ANKLE;
- g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_FOOT] = ROBOT_PIN_MASK_RIGHT_FOOT;
- }
- #define PWM_STEERING_ENGINE(group) \
- { \
- counter = STEERING_ENGINE_INIT_DELAY; \
- for (i = 0; i < 8; ++i) \
- counter += g_diffAngle[PIN_GROUP_##group][i]; \
- \
- for (i = 0; i < 30; ++i) \
- { \
- GROUP_##group##_CONTROL_PIN = 0xFF; \
- Delay10us(STEERING_ENGINE_INIT_DELAY); \
- \
- for (j = 0; j < 8; ++j) \
- { \
- Delay10us(g_diffAngle[PIN_GROUP_##group][j]); \
- GROUP_##group##_CONTROL_PIN &= ~(g_diffAngleMask[PIN_GROUP_##group][j]); \
- } \
- \
- Delay10us(STEERING_ENGINE_CYCLE - counter); \
- } \
- }
- void main()
- {
- UCHAR8 i;
- UCHAR8 j;
- UINT16 counter;
- InitSerialPort();
- P1 = 0xFF;
- // 初始化舵机角度
- for (i = 0; i < ROBOT_JOINT_AMOUNT; ++i)
- {
- g_angle[0][i] = 45;
- g_angle[1][i] = 45;
- }
- for (i = 0; i < USED_PIN; ++i)
- for (j = 0; j < 8; ++j)
- g_diffAngle[i][j] = 0;
- FillDiffAngle();
- InitPwmPollint();
- while (1)
- {
- #ifdef DEBUG_PROTOCOL
- if (g_fillingBufferIndex)
- {
- P11 = 0;
- P10 = 1;
- }
- else
- {
- P11 = 1;
- P10 = 0;
- }
- if (g_swapBuffer)
- P12 = 0;
- else
- P12 = 1;
- #endif
- if (g_swapBuffer)
- {
- FillDiffAngle();
- g_swapBuffer = FALSE;
- InitPwmPollint();
- }
- PWM_STEERING_ENGINE(1)
- PWM_STEERING_ENGINE(2)
- }
- }