STM32编程直流有刷电机PID速度闭环精准变速控制 电机控制例程分享 (第十一期)
STM32编程利用HMI做上位机调参精准PID闭环控制 (第十二期)
模块连接图(够乱的吧 *-*)
利用STM32高级定时器的互补输出模式驱动电机运行
/**
* 函数功能: BDCMOTOR定时器初始化
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void BDCMOTOR_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig; // 定时器时钟
TIM_OC_InitTypeDef sConfigOC; // 定时器通道比较输出
TIM_BreakDeadTimeConfigTypeDef sBDTConfig; // 定时器死区时间比较输出
/* 基本定时器外设时钟使能 */
BDCMOTOR_TIM_RCC_CLK_ENABLE();
/* 定时器基本环境配置 */
htimx_BDCMOTOR.Instance = BDCMOTOR_TIMx; // 定时器编号
htimx_BDCMOTOR.Init.Prescaler = BDCMOTOR_TIM_PRESCALER; // 定时器预分频器
htimx_BDCMOTOR.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数方向:向上计数
htimx_BDCMOTOR.Init.Period = BDCMOTOR_TIM_PERIOD; // 定时器周期
htimx_BDCMOTOR.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; // 时钟分频
htimx_BDCMOTOR.Init.RepetitionCounter = BDCMOTOR_TIM_REPETITIONCOUNTER; // 重复计数器
/* 初始化定时器比较输出环境 */
HAL_TIM_PWM_Init(&htimx_BDCMOTOR);
/* 定时器时钟源配置 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; // 使用内部时钟源
HAL_TIM_ConfigClockSource(&htimx_BDCMOTOR, &sClockSourceConfig);
/* 死区刹车配置,配置有效电平是低电平 */
sBDTConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE ;
sBDTConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW ;
sBDTConfig.BreakState = TIM_BREAK_DISABLE ;
sBDTConfig.DeadTime = 0 ;
sBDTConfig.LockLevel = TIM_LOCKLEVEL_OFF ;
sBDTConfig.OffStateIDLEMode= TIM_OSSI_DISABLE ;
sBDTConfig.OffStateRunMode = TIM_OSSR_ENABLE ;
HAL_TIMEx_ConfigBreakDeadTime(&htimx_BDCMOTOR,&sBDTConfig);
/* 定时器比较输出配置 */
sConfigOC.OCMode = TIM_OCMODE_PWM1; // 比较输出模式:PWM1模式
sConfigOC.Pulse = PWM_Duty; // 占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; // 输出极性
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW; // 互补通道输出极性
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 快速模式
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; // 空闲电平
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; // 互补通道空闲电平
HAL_TIM_PWM_ConfigChannel(&htimx_BDCMOTOR, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_Base_Start(&htimx_BDCMOTOR);
}
驱动模块连接图
电机控制的几个基本操作又一下几个函数完成
/**
* 函数功能: 设置电机速度
* 输入函数: Duty,输出脉冲占空比
* 返 回 值: 无
* 说 明: 无
*/
void SetMotorSpeed(int16_t Duty)
{
__HAL_TIM_SetCompare(&htimx_BDCMOTOR,TIM_CHANNEL_1,Duty);
}
/**
* 函数功能: 设置电机转动方向
* 输入函数: Dir,电机转动方向
* 返 回 值: 无
* 说 明: 无
*/
void SetMotorDir(int16_t Dir)
{
if(Dir)
{
HAL_TIM_PWM_Start(&htimx_BDCMOTOR,TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1); // 停止输出
}
else
{
HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htimx_BDCMOTOR,TIM_CHANNEL_1); // 停止输出
}
}
/**
* 函数功能: 设置电机停止
* 输入函数: 无
* 返 回 值: 无
* 说 明: 无
*/
void SetMotorStop()
{
HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1); // 停止输出
}
/**
* 函数功能: 设置电机启动
* 输入函数: 无
* 返 回 值: 无
* 说 明: 无
*/
void SetMotorStart()
{
HAL_TIM_PWM_Start(&htimx_BDCMOTOR,TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1); // 停止输出
}
编码器电机连接图
电机速度控制反馈信号是利用STM32定时器编码器模式读取电机编码器脉冲信号
/**
* 函数功能: 通用定时器初始化并配置编码器模式
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void ENCODER_TIMx_Init(void)
{
ENCODER_TIM_RCC_CLK_ENABLE();
htimx_Encoder.Instance = ENCODER_TIMx;
htimx_Encoder.Init.Prescaler = ENCODER_TIM_PRESCALER;
htimx_Encoder.Init.CounterMode = TIM_COUNTERMODE_UP;
htimx_Encoder.Init.Period = ENCODER_TIM_PERIOD;
htimx_Encoder.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
sEncoderConfig.EncoderMode = TIM_ENCODERMODE_TIx;
sEncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sEncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sEncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sEncoderConfig.IC1Filter = 0;
sEncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sEncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sEncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sEncoderConfig.IC2Filter = 0;
__HAL_TIM_SET_COUNTER(&htimx_Encoder,0);
HAL_TIM_Encoder_Init(&htimx_Encoder, &sEncoderConfig);
__HAL_TIM_CLEAR_IT(&htimx_Encoder, TIM_IT_UPDATE); // 清除更新中断标志位
__HAL_TIM_URS_ENABLE(&htimx_Encoder); // 仅允许计数器溢出才产生更新中断
__HAL_TIM_ENABLE_IT(&htimx_Encoder,TIM_IT_UPDATE); // 使能更新中断
HAL_NVIC_SetPriority(ENCODER_TIM_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ENCODER_TIM_IRQn);
HAL_TIM_Encoder_Start(&htimx_Encoder, TIM_CHANNEL_ALL);
}