这是一个基于NXP FRDM-MCXA153开发板的PWM电机控制系统项目。利用FLEXPWM(灵活脉宽调制)和GPIO外设控制直流电机,支持通过串口命令、电位器旋钮控制电机的速度和方向。
二、硬件/实物连接图

三、整体设计思路/功能效果
具体过程见过程贴,下面简单概括:
工作流程
初始化系统时钟、PWM模块、GPIO、ADC和串口
(可选)进入主循环读取字符,转换为速度值
(可选)读取ADC值,转换为速度值
调用set_motor()函数设置电机速度和方向
四、具体实现情况任务功能完成状况
| 电机启停与方向控制 | 完成 |
| 电机调速控制 | 完成 并且配有一个变速控制的测试 |
| 基于电位器的模拟调速系统 | 完成 通过电位器转动来控制正转反转以及转速 |
| 指令控制 | 完成 输入0-9控制转速 |
五、关键代码介绍
/* 将ADC值(0-65535)映射到PWM值(-100到100) */
int map_adc_to_pwm(uint16_t adc_value)
{
// ADC值范围: 0 - 65535
// PWM值范围: -100 - 100
// 将ADC值从 [0, 65535] 映射到 [-100, 100]
// 公式: pwmVal = (adc_value * 200 / 65535) - 100
int pwm_val = ((int)adc_value * 200) / 65535 - 100;
// 确保pwm值在有效范围内
if (pwm_val > 100) {
pwm_val = 100;
} else if (pwm_val < -100) {
pwm_val = -100;
}
return pwm_val;
}
void set_motor(int pwmVal)
{
if(pwmVal < 0) {
pwmVal = -pwmVal;
GPIO_PinWrite(GPIO1, 4, 1);
GPIO_PinWrite(GPIO1, 5, 0);
PRINTF("set_motor:-%d\r\n",pwmVal);
}
else{
GPIO_PinWrite(GPIO1, 4, 0);
GPIO_PinWrite(GPIO1, 5, 1);
PRINTF("set_motor:%d\r\n",pwmVal);
}
if(pwmVal > 100) pwmVal = 100;
if(pwmVal < 10) pwmVal = 0;
PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned, pwmVal);
PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2, true);
}
/*!
* @brief Main function
*/
int main(void)
{
/* Board pin, clock, debug console init */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
INPUTMUX_Init(INPUTMUX0);
INPUTMUX_AttachSignal(INPUTMUX0, 0U, kINPUTMUX_TrigIn0ToFlexPwm0Fault);
INPUTMUX_AttachSignal(INPUTMUX0, 1U, kINPUTMUX_TrigIn1ToFlexPwm0Fault);
INPUTMUX_AttachSignal(INPUTMUX0, 2U, kINPUTMUX_TrigIn2ToFlexPwm0Fault);
INPUTMUX_AttachSignal(INPUTMUX0, 3U, kINPUTMUX_TrigIn3ToFlexPwm0Fault);
pwm_init();
#if 0//切换为串口控制电机
int getSpeed;
while (1)
{
getSpeed = (GETCHAR()-48)*10;
PRINTF("get speed: %d\r\n", getSpeed);
set_motor(getSpeed);
SDK_DelayAtLeastUs(500000U, CLOCK_GetFreq(kCLOCK_CoreSysClk)); /* 添加500ms延时 */
}
#else //切换为电位器控制电机
lpadc_conv_result_t mLpadcResultConfigStruct;
adc_init();
while (1)
{
LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */
while (!LPADC_GetConvResult(DEMO_LPADC_BASE, &mLpadcResultConfigStruct))
{
}
PRINTF("ADC valueP: %d\r\n", ((mLpadcResultConfigStruct.convValue) >> g_LpadcResultShift));
set_motor(map_adc_to_pwm(mLpadcResultConfigStruct.convValue));
SDK_DelayAtLeastUs(500000U, CLOCK_GetFreq(kCLOCK_CoreSysClk)); /* 添加500ms延时 */
}
#endif
#if 0//测试电机驱动
int pwmVal = 4;
while (1U)
{
/* Delay at least 100 PWM periods. */
SDK_DelayAtLeastUs((1000000U / APP_DEFAULT_PWM_FREQUENCY) * 100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
static int direction = 1; // 用于控制方向的静态变量
pwmVal = pwmVal + 4 * direction;
/* 改变方向 */
if (pwmVal >= 100)
{
pwmVal = 100;
direction = -1; // 向下减小
}
else if (pwmVal <= -100)
{
pwmVal = -100;
direction = 1; // 向上增加
}
set_motor(pwmVal);
}
#endif
}六、功能展示
七、心得体会
我要赚赏金
