STM32F103c8t6Tim2输出四路PWM以0.3m/s的速度控制舵机
时间: 2023-05-28 18:06:56 浏览: 121
首先,需要明确一下控制舵机的原理。舵机通过接收PWM信号来控制角度,一般情况下,PWM周期为20ms,脉宽为0.5ms-2.5ms,其中0.5ms代表舵机最小角度,2.5ms代表舵机最大角度。因此,我们需要在20ms的周期内输出4路PWM信号,每路信号的占空比控制舵机转动的角度。
以下是基于STM32 CubeMX和HAL库的代码实现:
1. 初始化TIM2定时器
在CubeMX中选择TIM2定时器,并配置如下参数:
- Clock Source: Internal Clock
- Prescaler: 72
- Counter Period: 1999(即20ms的周期)
- Counter Mode: Up
在HAL库的代码中,初始化代码如下:
```c
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
```
2. 初始化GPIO
根据舵机控制信号的接口,我们需要选择4个GPIO口作为PWM信号输出口。在HAL库的代码中,初始化代码如下:
```c
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
/*Configure GPIO pins : PA0 PA1 PA2 PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PA4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
```
其中,PA0~PA3为PWM输出口,PC13为LED指示灯输出口。
3. 编写PWM输出函数
根据舵机的控制要求,我们需要在20ms的周期内输出4路PWM信号,占空比分别为0.5ms、1.0ms、1.5ms、2.0ms。在HAL库的代码中,输出函数如下:
```c
void PWM_SetDuty(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t Duty)
{
uint32_t TIM_Period = htim->Init.Period;
Duty = (Duty * (TIM_Period + 1)) / 20000;
switch(Channel)
{
case TIM_CHANNEL_1:
htim->Instance->CCR1 = Duty;
break;
case TIM_CHANNEL_2:
htim->Instance->CCR2 = Duty;
break;
case TIM_CHANNEL_3:
htim->Instance->CCR3 = Duty;
break;
case TIM_CHANNEL_4:
htim->Instance->CCR4 = Duty;
break;
default:
break;
}
}
void PWM_SetAllDuty(uint32_t duty1, uint32_t duty2, uint32_t duty3, uint32_t duty4)
{
PWM_SetDuty(&htim2, TIM_CHANNEL_1, duty1);
PWM_SetDuty(&htim2, TIM_CHANNEL_2, duty2);
PWM_SetDuty(&htim2, TIM_CHANNEL_3, duty3);
PWM_SetDuty(&htim2, TIM_CHANNEL_4, duty4);
}
```
其中,PWM_SetDuty函数用于设置单路PWM信号的占空比,PWM_SetAllDuty函数用于设置4路PWM信号的占空比。
4. 控制舵机转动
根据舵机的控制要求,我们需要以0.3m/s的速度控制舵机转动。因此,我们需要在每20ms的周期内计算出舵机应该转动的角度,并通过PWM信号控制舵机转动。
在HAL库的代码中,主函数代码如下:
```c
int main(void)
{
HAL_Init();
MX_GPIO_Init();
MX_TIM2_Init();
HAL_TIM_Base_Start(&htim2);
PWM_SetAllDuty(1500, 1500, 1500, 1500);
uint32_t time = 0;
while (1)
{
if(HAL_GetTick() - time >= 20)
{
time = HAL_GetTick();
static float pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
pos1 += 0.3 / 1000.0 * 20.0;
pos2 += 0.3 / 1000.0 * 20.0;
pos3 += 0.3 / 1000.0 * 20.0;
pos4 += 0.3 / 1000.0 * 20.0;
uint32_t duty1 = 500 + pos1 * 1000 / 180.0;
uint32_t duty2 = 500 + pos2 * 1000 / 180.0;
uint32_t duty3 = 500 + pos3 * 1000 / 180.0;
uint32_t duty4 = 500 + pos4 * 1000 / 180.0;
PWM_SetAllDuty(duty1, duty2, duty3, duty4);
}
}
}
```
其中,pos1~pos4变量用于记录舵机当前的角度,根据速度计算出应该转动的角度,并通过PWM信号控制舵机转动。
需要注意的是,舵机的转动范围一般为0-180度,因此需要进行角度限制,防止舵机超出范围。
以上就是基于STM32F103c8t6和HAL库控制舵机的实现方法,希望对您有所帮助。