这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 基于FRDM-MCXA153的电机控制-成果贴

共1条 1/1 1 跳转至

基于FRDM-MCXA153的电机控制-成果贴

菜鸟
2026-01-17 22:11:24   被打赏 50 分(兑奖)     打赏

一、项目概述

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

二、硬件/实物连接图

image-20260117210945306.png


三、整体设计思路/功能效果

具体过程见过程贴,下面简单概括:

工作流程

  1. 初始化系统时钟、PWM模块、GPIO、ADC和串口

  2. (可选)进入主循环读取字符,转换为速度值

  3. (可选)读取ADC值,转换为速度值

  4. 调用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
 }

六、功能展示

视频展示:

七、心得体会

在调试过程中,通过串口输出调试信息是一种非常有效的方法。在合适的地方打log很重要,而且也发现目前的库里的PRINTF函数无法输出负数,希望bsp工程师能有改进吧。这个项目不仅让我掌握了MCXA153微控制器的基本使用方法,也培养了我的嵌入式系统思维。



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]