0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用恩智浦MCXN947 PWM控制直流电机驱动模块L9110S

安富利 ? 来源:与非网 ? 2025-04-09 15:33 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

前言

恩智浦“FRDM-MCXN947”评测活动由安富利和与非网协同举办。本篇内容由与非网用户发布,已获转载许可。原文可在与非网(eefocus)工程师社区查看。

背景

01 直流电机驱动模块L9110S

一个L9110S驱动可以控制一个电机,下图中的GroundStudio L9110s模块板载两个L9110s芯片,可以驱动两个直流电机。

72556adc-1459-11f0-9310-92fbcf53809c.png

02 引脚说明

此模块有6根引脚,如下:

727ae8ca-1459-11f0-9310-92fbcf53809c.jpg

简单来说L9110S的输入输出有以下四种情形:

728f2f1a-1459-11f0-9310-92fbcf53809c.jpg

从上图可知,只需要给IN1IN2管脚输入不同的电平就能实现正转、反转,输入相同的电平就能停转。

需要注意,不要直接由开发板来给模块供电,因为L9110S模块可能因为需求的驱动功率太高而导致板子上的供电不平衡。

03 MCXN947 PWM

从上表可知,使用GPIO给IN1IN2也能驱动电机,但是不能控制速度。现在我们需要实现能控制速度的电机驱动。自然而然想到了PWM调速。

假设给IN2管脚用GPIO控制,拉低电平,只需要PWM往IN1灌高电平就可以驱动电机正转,调节PWM占空比就可以实现电机转速;把IN2管脚拉高电平,用PMW往IN1灌低电平就可以实现电机反转,注意此时的占空比和转速是反着的,即占空比越大,转速越慢。

这里选择eFlexPWM产生PWM1_A通道的PWM波来控制电机,另外一个管脚用GPIO来控制电平调节正反转。

04 代码实现

为了方便调试,先实现命令行接口,可以方便的通过串口输入命令调节参数控制电机正反转和转速。然后实现对应的电机驱动接口。

05 命令行接口

FreeRTOS-CLI新增命令行,支持如下的3种命令:

(滑动查看)

motor stop    // 电机停转
motor left speed // 电机正转,speed 表示速度,取值范围[0, 100]
motor right speed // 电机反转,speed 表示范围,取值范围[0, 100]

当前命令行的解析函数prvMotorCommand()如下,其实最终调用的函数是分别是motor_stop(),motor_left(speed)motor_right(speed)这三个函数。

(滑动查看)

/**
* @brief 直流电机命令的实现
*
* motor left/right speed 其中 speed 取值范围是 [0, 100]
* motor stop
*
* 示例:
* motor left 0
* motor left 100
* motor right 20
* motor right 80
* motor stop 停转
*
* @param pcWriteBuffer
* @param xWriteBufferLen
* @param pcCommandString
* @return BaseType_t
*/
staticBaseType_tprvMotorCommand(char*pcWriteBuffer,size_txWriteBufferLen,constchar*pcCommandString )
{
configASSERT(pcWriteBuffer);
br
/* param1: left/right/stop */
constchar*paramMotorCmd1 =NULL;
 BaseType_t paramMotorCmd1Length =0;
br
/* param2: speed */
constchar*paramMotorCmd2 =NULL;
 BaseType_t paramMotorCmd2Length =0;
uint32_tspeed =0;
br
// 首先清除输出缓冲区旧的内容
memset(pcWriteBuffer,0, xWriteBufferLen);
br
/*     arg0 arg1    arg2  */
/* 命令形式1:motor left/right speed */
/* 命令形式2:motor stop       */
 paramMotorCmd1 =FreeRTOS_CLIGetParameter(pcCommandString,1, ?mMotorCmd1Length);
br
if(strncmp("stop", paramMotorCmd1, strlen("stop")) ==0){
 motor_stop();
 sprintf(pcWriteBuffer,"
 motor_stop() 
");
 }else{
 /* 获取 speed */
  paramMotorCmd2 =FreeRTOS_CLIGetParameter(pcCommandString,2, ?mMotorCmd2Length);
 if(paramMotorCmd2 !=NULL) {
   speed =strtoul(paramMotorCmd2,NULL,10);
br
  if(speed >=100){
    speed =99;/*NOTE:PWM 占空比 <= 100 但由于两个高电平导致电机停转,所以占空比应该 < 100 */
? ? ? }
? ? }
br
? ??if?(strncmp("left", paramMotorCmd1, strlen("left")) ==?0)?{
? ? ??sprintf(pcWriteBuffer,?"
 motor_left(%u) 
", speed);
? ? ??motor_left(speed);
? ? }?else?if?(strncmp("right", paramMotorCmd1,?strlen("right")) ==?0) {
? ? ??sprintf(pcWriteBuffer,?"
 motor_right(%u) 
", speed);
? ? ??motor_right(speed);
? ? }?else?{
? ? ??sprintf(pcWriteBuffer,?"
Error: arg1 should be left/right
");
? ? }
? }
br
??/* There is no more data to return after this single string, so return pdFALSE. */
??return?pdFALSE;
}

06 电机驱动实现

PWM和GPIO初始化

通过MCUXpresso Config Tools来实现,配置J3.15PWM1_A0,配置J3.13为GPIO输出模式。生成代码,自动保存在pin_mux.c文件中。

72ad6ed0-1459-11f0-9310-92fbcf53809c.png

在MCUXpresso Config Tools中,点击(1)处新建分组BOARD_MOTOR_Init,把电机相关的管脚都放在同一个组里初始化;

在(2)处可以看到J3.15配置为PWM1_A0信号J3.13配置为PIO2_7且为输出;

在(3)处给管脚添加标识符,会生成相对应的宏定义。

对应的管脚初始化代码如下:

(滑动查看)

voidBOARD_MOTOR_Init(void)
{
 /* Enables the clock for GPIO2: Enables clock */
 CLOCK_EnableClock(kCLOCK_Gpio2);
 /* Enables the clock for PORT2: Enables clock */
 CLOCK_EnableClock(kCLOCK_Port2);


  gpio_pin_config_t MOTOR_DIR_config = {
    .pinDirection= kGPIO_DigitalOutput,
    .outputLogic= 0U
  };
 /* Initialize GPIO functionality on pin PIO2_7 (pin L2) */
 GPIO_PinInit(MOTOR_MOTOR_DIR_GPIO,MOTOR_MOTOR_DIR_PIN, &MOTOR_DIR_config);


 /* PORT2_6 (pin K2) is configured as PWM1_A0 */
 PORT_SetPinMux(MOTOR_MOTOR_SPEED_PORT,MOTOR_MOTOR_SPEED_PIN, kPORT_MuxAlt5);


 PORT2->PCR[6] = ((PORT2->PCR[6] &
          /* Mask bits to zero which are setting */
           (~(PORT_PCR_IBE_MASK)))


          /* Input Buffer Enable: Enables. */
          |PORT_PCR_IBE(PCR_IBE_ibe1));


 /* PORT2_7 (pin L2) is configured as PIO2_7 */
 PORT_SetPinMux(MOTOR_MOTOR_DIR_PORT,MOTOR_MOTOR_DIR_PIN, kPORT_MuxAlt0);


 PORT2->PCR[7] = ((PORT2->PCR[7] &
          /* Mask bits to zero which are setting */
           (~(PORT_PCR_IBE_MASK)))


          /* Input Buffer Enable: Enables. */
          |PORT_PCR_IBE(PCR_IBE_ibe1));
}

电机控制

需要实现4个函数,分别是:

motor_init()

motor_stop()

motor_left()

motor_right()

公共的类型和变量

(滑动查看)

#include"pin_mux.h"
#include"fsl_gpio.h"
#include"fsl_pwm.h"
#include"bsp_motor.h"
#include"fsl_debug_console.h"
br
/*******************************************************************************
* Definitions
******************************************************************************/
/* The PWM base address */
#defineBOARD_PWM_BASEADDR PWM1
#definePWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)
#defineDEMO_PWM_FAULT_LEVEL true
#defineAPP_DEFAULT_PWM_FREQUENCY (10000UL)
/* Definition for default PWM frequence in hz. */
#ifndefAPP_DEFAULT_PWM_FREQUENCY
#defineAPP_DEFAULT_PWM_FREQUENCY (1000UL)
#endif
br
/* Macros ----------------------------------------------------------------------------------------*/
#defineMOTOR_DIR_SET_LEFT()   GPIO_PinWrite(MOTOR_MOTOR_DIR_GPIO, MOTOR_MOTOR_DIR_GPIO_PIN, 0)
#defineMOTOR_DIR_SET_RIGHT()   GPIO_PinWrite(MOTOR_MOTOR_DIR_GPIO, MOTOR_MOTOR_DIR_GPIO_PIN, 1)
br
br
/* Data Types ------------------------------------------------------------------------------------*/
br
typedefenum{
 MOTOR_DIR_LEFT =0,
 MOTOR_DIR_RIGHT =1,
} motor_dir_e;
br
staticuint32_tpwmSourceClockInHz;
staticuint32_tpwmFrequencyInHz;
staticpwm_signal_param_tpwmSignal = {0};
staticmotor_dir_e m_motor_dir = MOTOR_DIR_LEFT;

motor_init()

(滑动查看)

staticvoidPWM_DRV_Init2PhPwm(void)
{
uint16_tdeadTimeVal;
br
/* Set deadtime count, we set this to about 650ns */
 deadTimeVal = ((uint64_t)pwmSourceClockInHz *650) /1000000000;
br
 pwmSignal.pwmChannel = kPWM_PwmA;
 pwmSignal.level = kPWM_HighTrue;
 pwmSignal.dutyCyclePercent =30;/* x percent dutycycle */
 pwmSignal.deadtimeValue = deadTimeVal;
 pwmSignal.faultState = kPWM_PwmFaultState0;
 pwmSignal.pwmchannelenable =true;
br
/*********** PWMA_SM0 - phase A, configuration, setup 2 channel as an example ************/
PWM_SetupPwm(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmSignal,1,
  kPWM_SignedCenterAligned, pwmFrequencyInHz, pwmSourceClockInHz);
}
br
/**
* @brief 直流电机初始化,即 PWM1 的通道A和通道B初始化
*
* @return int 0 on success, others on failure.
*/
intmotor_init(void)
{
pwm_config_tpwmConfig;
pwm_fault_param_tfaultConfig;
br
 pwmSourceClockInHz = PWM_SRC_CLK_FREQ;
 pwmFrequencyInHz = APP_DEFAULT_PWM_FREQUENCY;
br
 SYSCON->PWM1SUBCTL |= SYSCON_PWM1SUBCTL_CLK0_EN_MASK;/* 只使能子模块0 */
br
PWM_GetDefaultConfig(&pwmConfig);
br
 pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; /* use full cycle reload */
 pwmConfig.pairOperation = kPWM_Independent;   /* PWM A & PWM B operate as 2 independent channels */
 pwmConfig.enableDebugMode =true;
br
if(PWM_Init(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmConfig) == kStatus_Fail)
 {
 PRINTF("PWM initialization failed
");
 return1;
 }
br
PWM_FaultDefaultConfig(&faultConfig);
br
#ifdefDEMO_PWM_FAULT_LEVEL
 faultConfig.faultLevel = DEMO_PWM_FAULT_LEVEL;
#endif
br
/* Sets up the PWM fault protection */
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_0, &faultConfig);
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_1, &faultConfig);
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_2, &faultConfig);
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_3, &faultConfig);
br
/* Set PWM fault disable mapping for submodule 0 */
PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0,
       kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
br
/* Call the init function with demo configuration */
PWM_DRV_Init2PhPwm();
br
/* Set the load okay bit for all submodules to load registers from their buffer */
PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true);
br
PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);
br
motor_stop();
br
return0;
}

motor_stop()

(滑动查看)

voidmotor_stop(void)
{
if(m_motor_dir ==MOTOR_DIR_LEFT) {
 MOTOR_DIR_SET_LEFT();
 PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned,0);
 /* Set the load okay bit for all submodules to load registers from their buffer */
 PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true);
 }else{
 MOTOR_DIR_SET_RIGHT();
 PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned,100);
 /* Set the load okay bit for all submodules to load registers from their buffer */
 PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true);
 }
}

motor_left(speed)

(滑动查看)

/**
*@brief正转
*@paramspeed 占空比,[0~100]
*/
voidmotor_left(uint32_t speed)
{
MOTOR_DIR_SET_LEFT();
 m_motor_dir =MOTOR_DIR_LEFT;
br
PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned, speed);
/* Set the load okay bit for all submodules to load registers from their buffer */
PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true);
PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);
}

motor_right(speed)

(滑动查看)

/**
* @brief 反转
* @param speed
*/
voidmotor_right(uint32_tspeed)
{
MOTOR_DIR_SET_RIGHT();
 m_motor_dir = MOTOR_DIR_RIGHT;
 speed =100- speed;
br
PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned, speed);
// PWM_SetChannelOutput(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_InvertState);
/* Set the load okay bit for all submodules to load registers from their buffer */
PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true);
br
PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);
}

验证

01 示波器测量

上面黄色的是CH2,即PWM1_A信号(J3.15)

下面绿色的是CH1,即GPIO信号(J3.13)

电机正转motor left时CH1输出低电平

电机反转motor right时CH1输出高电平。

motor stop

两路信号都是低电平。电机停转。

72bcd758-1459-11f0-9310-92fbcf53809c.png

motor left 5

电机正转,速度为5。示波器观测PWM1_A占空比为5。

72e4af62-1459-11f0-9310-92fbcf53809c.png

motor left 70

电机正转,速度为70。示波器观测PWM1_A占空比为70。

72f66126-1459-11f0-9310-92fbcf53809c.png

motor left 100

虽然PWM占空比可以设置成100%,但是两个高电平导致电机停转,所以这里把占空比合理的范围是[0,99]。

7319cddc-1459-11f0-9310-92fbcf53809c.png

motor right 5

733685b2-1459-11f0-9310-92fbcf53809c.png

motor right 70

735e610e-1459-11f0-9310-92fbcf53809c.png

motor right 100

73723918-1459-11f0-9310-92fbcf53809c.png

关于安富利

安富利是全球领先的技术分销商和解决方案提供商,在过去一个多世纪里一直秉持初心,致力于满足客户不断变化的需求。通过遍布全球的专业化和区域化业务覆盖,安富利可在产品生命周期的每个阶段为客户和供应商提供支持。安富利能够帮助各种类型的公司适应不断变化的市场环境,在产品开发过程中加快设计和供应速度。安富利在整个技术价值链中处于中心位置,这种独特的地位和视角让其成为了值得信赖的合作伙伴,能够帮助客户解决复杂的设计和供应链难题,从而更快地实现营收。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动器
    +关注

    关注

    54

    文章

    8713

    浏览量

    150392
  • 恩智浦
    +关注

    关注

    14

    文章

    5991

    浏览量

    118588
  • 直流电机
    +关注

    关注

    36

    文章

    1736

    浏览量

    71981
  • 安富利
    +关注

    关注

    6

    文章

    462

    浏览量

    63068

原文标题:用户测评(五):MCXN947 PWM驱动直流电机L9110S驱动器

文章出处:【微信号:AvnetAsia,微信公众号:安富利】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    《电子发烧友电子设计周报》聚焦硬科技领域核心价值 第7期:2025.04.7--2025.04.11

    阻和高效散热能力的MOSFET器件,以及对电路设计中的各种配置方式。 7、使用MCXN947 PWM控制
    发表于 04-11 19:51

    一种直流电机驱动实验

    直流电机驱动实验实验现象本实验采用小型直流电机驱动L9110驱动一个小型
    发表于 06-30 07:36

    直流电机驱动GC9110 pin对pin兼容L9110

    的运动控制类应用提供了集成的电机驱动解决方案。芯片一般用了驱动一个直流电机或者使用两颗来驱动一个
    发表于 07-21 11:28

    STM32F103如何使用L9110s驱动直流电机

    STM32F103如何使用L9110s驱动直流电机
    发表于 10-09 06:53

    如何用L9110S控制小型直流电机

    L9110S是什么?L9110S有哪些应用?如何用L9110S控制小型直流电机的?
    发表于 10-18 09:03

    L9110S芯片是怎样控制电机的速度和方向的

    L9110S是什么?L9110S芯片有哪些基本参数?L9110S芯片是怎样控制电机的速度和方向的?
    发表于 10-18 14:09

    请问L9110H怎么驱动直流电机呢?

    请问L9110H怎么驱动直流电机呢?是不是要输入高低电平呢?
    发表于 03-17 10:07

    直流电机PWM控制

    直流电机PWM控制设计:基于VHDL语言实现直流电机PWM控制设计,有仿真,有程序,有结论
    发表于 11-08 18:51 ?52次下载

    直流电机PWM控制

    直流电机PWM控制(电源技术属于哪个期刊)-直流电机PWM控制,有需要的可以参考!
    发表于 09-15 15:29 ?142次下载
    <b class='flag-5'>直流电机</b><b class='flag-5'>PWM</b><b class='flag-5'>控制</b>

    L9110S直流电机H桥驱动电路

    L9110S是一款直流电机驱动电路,该产品为电池供电的玩具、低压或电池供电的控制应用提供了一种集成直流马达
    发表于 03-07 15:49 ?46次下载

    直流电机 H 桥驱动L9110S/HR9110/AT9110

    直流电机 H 桥驱动L9110S/HR9110/AT9110
    发表于 10-27 14:52 ?2600次阅读
    <b class='flag-5'>直流电机</b> H 桥<b class='flag-5'>驱动</b><b class='flag-5'>L9110S</b>/HR<b class='flag-5'>9110</b>/AT<b class='flag-5'>9110</b>

    MCX系列MCU的新品MCXN947

    鉴于 N54x 是 N94x 的简配版,我们今天主要聊 MCXN947 这个型号。老规矩先来看一下 MCXN947 内部模块框图,它搭载了两个 Arm Cortex-M33 内核,主频可达 150MHz,此外还为 CM33 配备
    的头像 发表于 12-21 12:57 ?2734次阅读

    PWM控制直流电机介绍

    直流电机属于大功率器件,GPIO无法直接驱动,需要电机驱动模块配合,才能驱动
    发表于 03-31 10:02 ?11次下载
    <b class='flag-5'>PWM</b><b class='flag-5'>控制</b><b class='flag-5'>直流电机</b>介绍

    中微爱芯L9110S电子锁驱动模块

    电压和输出驱动电流需求设计,满足各类电池供电的低压直流电机驱动需求。中微爱芯L9110S电子锁驱动模块
    的头像 发表于 04-29 17:31 ?2722次阅读
    中微爱芯<b class='flag-5'>L9110S</b>电子锁<b class='flag-5'>驱动</b><b class='flag-5'>模块</b>

    中微爱芯直流电机H桥驱动电路L9110S

    L9110S规格书下载
    发表于 08-16 11:18 ?8次下载