无刷电机
KV 值
有刷直流电机是根据额定工作电压来标注额定转速的,无刷电机引入了 KV 值的概念,而让用
户可以直观的知道无刷电机在具体的工作电压下的具体转速。实际转速 =KV 值 * 工作电压,这
就是 KV 的物理意义,就是在 1V 工作电压下每分钟的转速。无刷直流电机的转速与电压呈正比
关系,电机的转速会随着电压上升而线性上升。例如,2212-850KV 电机在 10V 电压下的转速就
是:85010=850ORPM(RPM,每分钟转速)。KV 值与匝数是呈反比例关系的,例如 2212-850KV,
匝数是 30T(15 圈),那在 28T 的情况下的 KV 值是:850KV30T/28T=910KV。
一般是三相
这里控制电机靠的是三相六臂全桥电路。
注意不能同侧导通,那就短路了,整个控制过程就是通过霍尔传感器的状态,判断在那一个位置,后按电机旋转真值表来控制。
使用 PWM 控制直流无刷电机的策略包括
PWM-ON、ON-PWM、H_PWM-L_ON、H_ONL_PWM 和 H_PWM-L_PWM。这 5 种控制策略,均是电机处于 120° 运行方式下进行的
这 5 种调制方式为:
- PWM-ON 型。在 120° 导通区间,各开关管前 60° 采用 PWM 调制,后 60° 则恒通。
- ON-PWM 型。在 120° 导通区间,各开关管前 60° 恒通,后 60° 则采用 PWM 调制。
- H_PWM-L_ON 型。在 120° 导通区间,上桥臂开关管采用 PWM 调制,下桥臂恒通。
- H_ON-L_PWM 型。在 120° 导通区间,上桥臂开关管恒通,下桥臂采用 PWM 调制。
- H_PWM-L_PWM 型。在 120° 导通区间,上、下桥臂均采用 PWM 调制。
具体内容去看野火电机手册,这里只是个人笔记
配置
这里采用,H_PWM-L_ON 型。在 120° 导通区间,上桥臂开关管采用 PWM 调制,下桥臂恒通。
首先配置定时器5的霍尔编码器
这里差不多是10.1hz ,10/1 = 0.1s = 100ms ,是1秒执行10次
代码生成后
/* TIM5 init function */
void MX_TIM5_Init(void)
{
TIM_HallSensor_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim5.Instance = TIM5;
htim5.Init.Prescaler = 127;
htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
htim5.Init.Period = 0xFFFF;
htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.IC1Polarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 10;
sConfig.Commutation_Delay = 0;
if (HAL_TIMEx_HallSensor_Init(&htim5, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
我们这里需要注意的是sConfig.IC1Polarity,这里默认配置完就是TIM_INPUTCHANNELPOLARITY_RISING
我们需要改成TIM_INPUTCHANNELPOLARITY_BOTHEDGE的双边沿触发。
这里只是init,后面我们使能中断
void hall_enable(void)
{
//前面的IC1Polarity要修改为TIM_ICPOLARITY_BOTHEDGE
__HAL_TIM_ENABLE_IT(&htim5,TIM_IT_TRIGGER); //触发:有某个信号触发。
__HAL_TIM_ENABLE_IT(&htim5,TIM_IT_UPDATE); //更新:有某个寄存器被更新。
HAL_TIMEx_HallSensor_Start(&htim5);
HAL_TIM_TriggerCallback(&htim5);
}
使能中断,启动霍尔功能,在回调HAL_TIM_TriggerCallback(&htim5);
我们在开启定时器pwm功能
PH15,14,13 设置为定时器输出功能,控制下桥臂
/* TIM8 init function */
void MX_TIM8_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim8.Instance = TIM8;
htim8.Init.Prescaler = 1;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 5599;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim8);
}
我们要让TIM5控制TIM8和开启pwm所以在设置个函数
TIM5控制TIM8
void PWM_Configuration(void)
{
/* 配置触发源 */
HAL_TIMEx_ConfigCommutationEvent(&htim8, TIM_TS_ITR3, TIM_COMMUTATION_SOFTWARE); // 内部触发配置(TIM8->ITR3->TIM5)
/* 开启定时器通道1输出PWM */
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1);
/* 开启定时器通道2输出PWM */
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_2);
/* 开启定时器通道3输出PWM */
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_3);
// HAL_TIMEx_PWMN_Start(&htim8,TIM_CHANNEL_1);
// HAL_TIMEx_PWMN_Start(&htim8,TIM_CHANNEL_2);
// HAL_TIMEx_PWMN_Start(&htim8,TIM_CHANNEL_3);
}
思路
开启霍尔回调,回调开启后通过获取霍尔传感器的状态,在回调中输出相应的pwm和下桥臂开启或关闭,使无刷电机换相
uint8_t get_hall_state(void)
{
uint8_t state = 0;
#if 1
/* 读取霍尔传感器 U 的状态 */
if(HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_10) != GPIO_PIN_RESET)
{
state |= 0x01U << 0;
}
/* 读取霍尔传感器 V 的状态 */
if(HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_11) != GPIO_PIN_RESET)
{
state |= 0x01U << 1;
}
/* 读取霍尔传感器 W 的状态 */
if(HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_12) != GPIO_PIN_RESET)
{
state |= 0x01U << 2;
}
#else
state = (GPIOH->IDR >> 10) & 7; // 读 3 个霍尔传感器的状态
#endif
return state;
}
霍尔回调中,使无刷电机换相
void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
{
/* 获取霍尔传感器引脚状态,作为换相的依据 */
uint8_t step = 0;
step = get_hall_state();
#if 0
if(get_bldcm_direction() == MOTOR_FWD)
{
step = 7 - step; // 根据换向表的规律可知: REV = 7 - FWD;
}
#endif
if(get_bldcm_direction() == MOTOR_FWD)
{
switch(step)
{
case 1: /* U+ W- */
// printf("U+ W-\r\n");
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, bldcm_pulse); // 通道 1 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_SET); // 开启下桥臂
break;
case 2: /* V+ U- */
//printf("V+ U- \r\n");
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, bldcm_pulse); // 通道 2 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_SET); // 开启下桥臂
break;
case 3: /* V+ W- */
//printf("V+ W-\r\n");
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, bldcm_pulse); // 通道 2 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_SET); // 开启下桥臂
break;
case 4: /* W+ V- */
//printf("W+ V-\r\n");
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, bldcm_pulse); // 通道 3 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_SET); // 开启下桥臂
break;
case 5: /* U+ V -*/
//printf("U+ V -\r\n");
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, bldcm_pulse); // 通道 1 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_SET); // 开启下桥臂
break;
case 6: /* W+ U- */
//printf("W+ U-\r\n");
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, bldcm_pulse); // 通道 3 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_SET); // 开启下桥臂
break;
}
}
else
{
switch(step)
{
case 1: /* W+ U- */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, bldcm_pulse); // 通道 3 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_SET); // 开启下桥臂
break;
case 2: /* U+ V -*/
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, bldcm_pulse); // 通道 1 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_SET); // 开启下桥臂
break;
case 3: /* W+ V- */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, bldcm_pulse); // 通道 3 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_SET); // 开启下桥臂
break;
case 4: /* V+ W- */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, bldcm_pulse); // 通道 2 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_SET); // 开启下桥臂
break;
case 5: /* V+ U- */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0); // 通道 1 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, bldcm_pulse); // 通道 2 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_SET); // 开启下桥臂
break;
case 6: /* U+ W- */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0); // 通道 2 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0); // 通道 3 配置为 0
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, bldcm_pulse); // 通道 1 配置的占空比
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_SET); // 开启下桥臂
break;
}
}
HAL_TIM_GenerateEvent(&htim8, TIM_EVENTSOURCE_COM); // 软件产生换相事件,此时才将配置写入
update = 0;
}
如果霍尔传感器引脚状态无改变
update就不会变成0 当CNT与比较值相同时就触发了更新中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (update++ > 1) // 有一次在产生更新中断前霍尔传感器没有捕获到值
{
printf("堵转超时\r\n");
update = 0;
//HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
/* 堵转超时停止 PWM 输出 */
hall_disable(); // 禁用霍尔传感器接口
stop_pwm_output(); // 停止 PWM 输出
}
}
防止电机堵转,禁用电机
//禁用电机
void set_bldcm_disable(void)
{
/* 禁用霍尔传感器接口 */
hall_disable();
/* 停止 PWM 输出 */
stop_pwm_output();
/* 关闭 MOS 管 */
BLDCM_DISABLE_SD();
}
//停止pwm输出
void stop_pwm_output(void)
{
/* 关闭定时器通道1输出PWM */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, 0);
/* 关闭定时器通道2输出PWM */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0);
/* 关闭定时器通道3输出PWM */
__HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 0);
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET); // 关闭下桥臂
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_14, GPIO_PIN_RESET); // 关闭下桥臂
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_15, GPIO_PIN_RESET); // 关闭下桥臂
}
开启电机之前我们要先将SD引脚拉高
我们才能输出pwm
在main函数的控制逻辑
int main(void)
{
/* USER CODE BEGIN 1 */
__IO uint16_t ChannelPulse = 5500/10;
uint8_t i = 0;
//uint8_t flag = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM5_Init();
MX_USART1_UART_Init();
MX_TIM8_Init();
/* USER CODE BEGIN 2 */
//PWM_Configuration();
bldcm_init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(Key_Scan(KEY1_GPIO_Port,KEY1_Pin) == 1) {
/* 使能电机 */
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
//set_bldcm_direction(MOTOR_REV);
set_bldcm_speed(ChannelPulse);
set_bldcm_enable();
}
if(Key_Scan(GPIOG,KEY2_Pin) == 1) {
/* 停止电机 */
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
set_bldcm_disable();
}
if(Key_Scan(GPIOC,KEY3_Pin) == 1) {
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
/* 增大占空比 */
ChannelPulse += 5500/10;
if(ChannelPulse > 5500)
ChannelPulse = 5500;
set_bldcm_speed(ChannelPulse);
}
if(Key_Scan(GPIOG,KEY4_Pin) == 1) {
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
if(ChannelPulse < 5500/10)
ChannelPulse = 0;
else
ChannelPulse -= 5500/10;
set_bldcm_speed(ChannelPulse);
}
if(Key_Scan(GPIOG,KEY5_Pin) == 1) {
/* 转换方向 */
set_bldcm_direction( (++i % 2) ? MOTOR_FWD : MOTOR_REV);
}
}
/* USER CODE END 3 */
}
版权声明:本文为CSDN博主「IMXRT型Planck」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46942417/article/details/117510317
暂无评论