1.前言
在上一篇文章中已经实现了启动电机,但是启动之后是一直运行,不会停止。
这篇文章将介绍,如何输出指定的脉冲数。
输出指定的脉冲数涉及到几个相关的函数。
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
UART串口通讯数据接收回调函数,UART接收到数据后会调用该函数。本例将在该函数中接受串口发送的数据,然后解析出当中脉冲数。
- void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
一次脉冲结束后的回调函数,当发送完一次脉冲后会调用该函数。
- HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
PWM启动函数
- HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
PWM停止函数
2.代码实现
- 在main 文件中定义全局变量【PwmNum】
uint16_t PwmNum=1600;
该变量指示目标脉冲数量
- 在串口回调函数中解析脉冲目标数量,并启动PWM输出
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart1) {
HAL_UART_Receive_IT(&huart1, (uint8_t *)Rx_Data, 10);
uint32_t compare= (Rx_Data[0] << 24) + (Rx_Data[1] << 16)+ (Rx_Data[2] << 8) + Rx_Data[3];
uint16_t pulseCnt = (Rx_Data[5] << 8) + Rx_Data[6];
uint8_t motorEnable = Rx_Data[4] & 0x1;
uint8_t motorRun = Rx_Data[4] & 0x2;
uint8_t motorDir = Rx_Data[4] & 0x4;
PwmNum = pulseCnt;
if (motorEnable) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
}
if (motorDir){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
}
if (motorRun){
HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1);
}
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, compare);
printf("TIM1.RCC = %d, pulseCnt=%d, dir=%d\n", (int)TIM1->CCR1, (int)pulseCnt, motorDir);
}
}
这我自己定义了指令通讯协议。
第0~3 个byte代表占空比;
第4个byte控制位:第0位电机使能,第1为运行,第2位方向;
第5~6 脉冲数 ;
- 记录已执行的脉冲数,判断是否已达到目标值
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { static uint16_t cnt = 0; cnt++; if (htim->Instance == TIM1) { if(cnt >= PwmNum-1) { cnt = 0; HAL_TIM_PWM_Stop_IT(&htim1,TIM_CHANNEL_1); } } }
cnt记录已完成的脉冲数,达到目标值后停止PWM输出
-
控制速度
PWM输出频率影响着电机的转动速度,可以通过调用下面的函数修改PWM的输出频率
__HAL_TIM_SET_AUTORELOAD(&htim1, autoreload);