本文将基于FRDM-MCXA153实现直流电机控制,包括电机的启动、正反转和停止,以及使用串口完成电机转速的控制
根据TB6612的文档,可以看到如果希望控制一路直流电机,例如控制A路电机,可以通过向PWMA引脚输入PWM信号,利用调整占空比来控制电机转速,INA1和INA2可以控制电机的转动状态

INA和电机转动方式关系如下
| INA1=0 | INA1=1 | |
| INA2=0 | 电机滑行 | 电机正转 |
| INA2=1 | 电机反转 | 电机刹车 |
在MCUXpresso中定义引脚如下,LPUART用于串口收发,GPIO用于电机运行方式控制,FlexPWM用于电机转速控制
其中FlexPWM0对应开发板上的P3_0,连接电机驱动板的PWMA,P2_4和P2_5分别连接电机驱动板的INA1和INA2
电源的正负极分别连接电机驱动板的VM和GND,开发板上的3.3V引脚连接电机驱动板的Vcc,同时保证开发板和电源共地
直流电机的正负引脚连接MOT.A的两个引脚
代码实现如下
对PWM进行初始化
static void PWM_DRV_InitPwm(void)
{
uint16_t deadTimeVal;
pwm_signal_param_t pwmSignal;
uint32_t pwmSourceClockInHz;
uint32_t pwmFrequencyInHz = APP_DEFAULT_PWM_FREQUENCY;
pwmSourceClockInHz = PWM_SRC_CLK_FREQ;
/* Set deadtime count, we set this to about 650ns */
deadTimeVal = ((uint64_t)pwmSourceClockInHz * 650) / 1000000000;
pwmSignal.pwmChannel = kPWM_PwmA;
pwmSignal.level = kPWM_HighTrue;
pwmSignal.dutyCyclePercent = 0; /* 1 percent dutycycle */
pwmSignal.deadtimeValue = deadTimeVal;
pwmSignal.faultState = kPWM_PwmFaultState0;
pwmSignal.pwmchannelenable = true;
PWM_SetupPwm(
FLEXPWM0,
kPWM_Module_0,
&pwmSignal,
1,
kPWM_SignedCenterAligned,
pwmFrequencyInHz,
pwmSourceClockInHz
);
}定义电机运行状态
// 电机滑行
static inline void motor_slid(void)
{
GPIO_PinWrite(AIN_GPIO, AIN1_PIN, 0);
GPIO_PinWrite(AIN_GPIO, AIN2_PIN, 0);
}
// 电机正转
static inline void motor_forward(void)
{
GPIO_PinWrite(AIN_GPIO, AIN1_PIN, 1);
GPIO_PinWrite(AIN_GPIO, AIN2_PIN, 0);
}
// 电机反转
static inline void motor_reverse(void)
{
GPIO_PinWrite(AIN_GPIO, AIN1_PIN, 0);
GPIO_PinWrite(AIN_GPIO, AIN2_PIN, 1);
}
// 电机刹车
static inline void motor_coast(void)
{
GPIO_PinWrite(AIN_GPIO, AIN1_PIN, 1);
GPIO_PinWrite(AIN_GPIO, AIN2_PIN, 1);
}设置PWM更新函数
/* 占空比 0~100% 更新 */
static void motor_set_duty(uint8_t duty)
{
if (duty > 100U) {
duty = 100U;
}
PWM_UpdatePwmDutycycle(FLEXPWM0,
kPWM_Module_0, /* 子模块0 */
kPWM_PwmA, /* 通道A = PWM0_A0 */
kPWM_SignedCenterAligned,
duty);
PWM_SetPwmLdok(FLEXPWM0, kPWM_Control_Module_0, true);
}在主函数中,完成外设初始化,并实现串口输入控制PWM以及电机反复正转加速-减速-反转加速-反转减速
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
BOARD_InitDebugConsole();
pwm_config_t pwmConfig;
pwm_fault_param_t faultConfig;
uint32_t duty = 0;
motor_coast();
pwmConfig.enableDebugMode = false;
pwmConfig.reloadSelect = kPWM_LocalReload;
pwmConfig.clockSource = kPWM_BusClock;
pwmConfig.prescale = kPWM_Prescale_Divide_1;
pwmConfig.initializationControl = kPWM_Initialize_LocalSync;
pwmConfig.forceTrigger = kPWM_Force_Local;
pwmConfig.reloadFrequency = kPWM_LoadEveryOportunity;
pwmConfig.reloadLogic = kPWM_ReloadImmediate;
pwmConfig.pairOperation = kPWM_Independent;
PWM_GetDefaultConfig(&pwmConfig);
#ifdef DEMO_PWM_CLOCK_DEVIDER
pwmConfig.prescale = DEMO_PWM_CLOCK_DEVIDER;
#endif
pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
pwmConfig.pairOperation = kPWM_ComplementaryPwmA;
pwmConfig.enableDebugMode = true;
if (PWM_Init(FLEXPWM0, kPWM_Module_0, &pwmConfig) == kStatus_Fail ||
PWM_Init(FLEXPWM0, kPWM_Module_1, &pwmConfig) == kStatus_Fail)
{
PRINTF("PWM initialization failed\n");
return 1;
}
pwmConfig.clockSource = kPWM_Submodule0Clock;
pwmConfig.prescale = kPWM_Prescale_Divide_1;
pwmConfig.initializationControl = kPWM_Initialize_MasterSync;
PWM_FaultDefaultConfig(&faultConfig);
#ifdef DEMO_PWM_FAULT_LEVEL
faultConfig.faultLevel = DEMO_PWM_FAULT_LEVEL;
#endif
/* Sets up the PWM fault protection */
PWM_SetupFaults(FLEXPWM0, kPWM_Fault_0, &faultConfig);
PWM_SetupFaults(FLEXPWM0, kPWM_Fault_1, &faultConfig);
PWM_SetupFaults(FLEXPWM0, kPWM_Fault_2, &faultConfig);
PWM_SetupFaults(FLEXPWM0, kPWM_Fault_3, &faultConfig);
/* Set PWM fault disable mapping for submodule 0/1/2 */
PWM_SetupFaultDisableMap(FLEXPWM0, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0,
kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
PWM_DRV_InitPwm();
/* Set the load okay bit for all submodules to load registers from their buffer */
PWM_SetPwmLdok(FLEXPWM0, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2, true);
/* Start the PWM generation from Submodules 0, 1 and 2 */
PWM_StartTimer(FLEXPWM0, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2);
while(1) {
#if UART_CONTROL
motor_forward();
if (SCANF("%d", &duty) == 1) {
if (duty < 0) {
duty = 0;
}
if (duty > 100) {
duty = 100;
}
motor_set_duty(duty);
PRINTF("duty=%d\r\n", duty);
} else {
int ch;
while (1)
{
ch = GETCHAR();
if (ch == '\r' || ch == '\n') break;
}
}
#else
motor_forward();
for (duty = 0; duty < 100; duty++) {
motor_set_duty(duty);
SDK_DelayAtLeastUs((200000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
}
SDK_DelayAtLeastUs((10000000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
for (duty = 100; duty > 0; duty--) {
motor_set_duty(duty);
SDK_DelayAtLeastUs((200000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
}
SDK_DelayAtLeastUs((10000000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
motor_coast();
motor_reverse();
for (duty = 0; duty < 100; duty++) {
motor_set_duty(duty);
SDK_DelayAtLeastUs((200000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
}
SDK_DelayAtLeastUs((10000000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
for (duty = 100; duty > 0; duty--) {
motor_set_duty(duty);
SDK_DelayAtLeastUs((200000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
}
SDK_DelayAtLeastUs((10000000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
motor_coast();
#endif
}
return 0 ;
}具体实现效果和代码汇总详见成果帖
我要赚赏金
