这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » “2025年Let'sdo第4期”基于单片机的直流电机控制【结果贴1】

共1条 1/1 1 跳转至

“2025年Let'sdo第4期”基于单片机的直流电机控制【结果贴1】

菜鸟
2026-01-30 00:25:32     打赏

(按键交互版)

目前完成的是基础任务,控制电机的启停,正反转以及控制转速。在设计过程中,我注意到MCXA153开发板有除复位按键之外的两个按键,于是打算用这两个按键实现这些控制功能。实现过程如下,代码以附件形式附上,视频将在下个结果贴中补充。

 

一、核心硬件原理1.1 TB6612FNG 驱动芯片控制逻辑

TB6612FNG是一款专为直流电机设计的双通道H桥驱动芯片,相比传统L298N,它具有功耗低、集成度高、自带续流二极管等优势,其核心控制逻辑如下:

AIN1 电平

AIN2 电平

电机状态

正转

反转

/

/

刹车/停止

此外,芯片的PWMA(对应A通道)引脚接收PWM波输入,通过调整PWM占空比可线性调节电机转速:占空比越高,电机转速越快;占空比为0时,电机停止。

 

1.2 硬件连接设计

本方案中MCUTB6612FNG、外设的核心连接关系:

      PWM输出MCUFlexPWM模块输出通道(BOARD_PWM_BASEADDR)连接TB6612FNGPWMA引脚,用于输出调速PWM波;

      方向控制MCU的两个GPIO引脚(BOARD_Direct1/Direct2)分别连接TB6612FNGAIN1/AIN2,通过电平翻转控制电机转向;

      按键输入SW2/SW3两个按键分别接MCUGPIO中断引脚(下降沿触发),用于交互控制;

      状态指示MCUGPIO引脚控制LED,用于指示PWM运行状态(电机启停)。

 

二、软件实现(基于MCUX SDK2.1 开发环境

      开发工具:Keil5

      底层驱动:NXP MCUX SDK(适配目标MCU,包含PWMGPIO、中断等底层驱动)

      核心功能:PWM初始化与占空比更新、GPIO中断(按键)、按键长短按识别、电机状态控制。

 

2.2 代码架构与核心模块解析

完整代码基于模块化设计,核心分为PWM初始化GPIO与中断配置按键交互逻辑主循环四大模块,以下是关键代码解析:

 

2.2.1 宏定义与全局变量(核心配置)

        
    /* 按键长按判定阈值(ms),超过该时间判定为长按 */   
    #define LONG_PRESS_THRESHOLD 500   
    /* 占空比调整步长,每次按键±10% */   
    #define DUTY_STEP 10   
    /* 默认PWM频率1kHz,兼顾调速精度与电机响应 */   
    #define APP_DEFAULT_PWM_FREQUENCY (1000UL)   
        
    /* 全局状态标记 */   
    volatile bool g_Button2Press = false;  // SW2按键按下标记   
    volatile bool g_Button3Press = false;  // SW3按键按下标记   
    volatile bool g_PwmRunning = false;    // PWM运行状态(电机启停)   
    volatile uint32_t g_PwmDuty = 50;      // PWM占空比(0-100)   
    volatile bool g_DirectionState = false;// 方向引脚状态(控制AIN1/AIN2电平)   
        

 

2.2.2 PWM初始化(FlexPWM配置)

针对TB6612FNG的驱动需求,配置FlexPWM模块为中心对齐模式SignedCenterAligned),并设置死区时间(防止H桥桥臂直通):

        
    static void PWM_DRV_Init3PhPwm(void)   
    {   
        uint16_t deadTimeVal;   
        pwm_signal_param_t pwmSignal;   
        uint32_t pwmSourceClockInHz = PWM_SRC_CLK_FREQ;   
        uint32_t pwmFrequencyInHz = APP_DEFAULT_PWM_FREQUENCY;   
        
        /* 死区时间配置:约650ns,防止H桥上下管同时导通 */   
        deadTimeVal = ((uint64_t)pwmSourceClockInHz * 650) / 1000000000;   
        
        /* 配置PWM信号参数:A通道、高电平有效、初始占空比50% */   
        pwmSignal.pwmChannel       = kPWM_PwmA;   
        pwmSignal.level            = kPWM_HighTrue;   
        pwmSignal.dutyCyclePercent = g_PwmDuty;   
        pwmSignal.deadtimeValue    = deadTimeVal;   
        pwmSignal.pwmchannelenable = true;   
        
        /* 初始化PWM模块0,中心对齐模式,1kHz频率 */   
        PWM_SetupPwm(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmSignal, 1, kPWM_SignedCenterAligned,    
                     pwmFrequencyInHz, pwmSourceClockInHz);   
    }   
        

 

2.2.3 GPIO与中断配置(按键与方向控制)

      按键配置:SW2/SW3设为数字输入,下降沿触发中断,中断服务函数仅标记按键按下状态(避免中断内复杂操作);

      方向控制:AIN1/AIN2BOARD_Direct1/Direct2)设为数字输出,初始全低(电机刹车);

      LED配置:数字输出,初始关闭(PWM未运行)。

 

        
    /* SW2中断处理函数:仅标记按键按下,清中断标志 */   
    void BOARD_SW2_IRQ_HANDLER(void)   
    {   
        GPIO_PortClearInterruptFlags(BOARD_SW2_GPIO, 1U << BOARD_SW2_GPIO_PIN);   
        g_Button2Press = true;   
        SDK_ISR_EXIT_BARRIER;   
    }   
        
    /* 主函数中GPIO初始化 */   
    gpio_pin_config_t sw2_config = {kGPIO_DigitalInput, 0};   
    gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 1};   
    gpio_pin_config_t p_direction_config = {kGPIO_DigitalOutput, 0};   
        
    // 按键GPIO初始化   
    GPIO_PinInit(BOARD_SW2_GPIO, BOARD_SW2_GPIO_PIN, &sw2_config);   
    // 方向引脚初始化(AIN1/AIN2)   
    GPIO_PinInit(BOARD_Direct_GPIO, BOARD_Direct1_GPIO_PIN, &p_direction_config);   
    GPIO_PinInit(BOARD_Direct_GPIO, BOARD_Direct2_GPIO_PIN, &p_direction_config);   
    // 配置按键中断为下降沿触发   
    PORT_SetPinInterruptConfig(BOARD_SW2_PORT, BOARD_SW2_GPIO_PIN, kPORT_InterruptFallingEdge);   
    EnableIRQ(BOARD_SW2_IRQ);   
        

 

2.2.4 按键长短按交互逻辑(核心业务)

通过计时识别按键短按/长按,结合TB6612FNG控制逻辑实现以下功能:

按键

短按

长按

SW2

占空比+10%≤100%

电机启停+LED状态切换

SW3

占空比-10%≥10%

电机方向切换(翻转AIN1/AIN2电平)

核心代码:

        
    static void Key_ProcessShortLongPress(void)   
    {   
        uint32_t press_time = 0;   
        
        /* 处理SW2按键 */   
        if (g_Button2Press)   
        {   
            g_Button2Press = false;   
            // 计时:等待按键释放,最长计时500ms(长按阈值)   
            while (GPIO_PinRead(BOARD_SW2_GPIO, BOARD_SW2_GPIO_PIN) == 0)   
            {   
                delay_ms(1);   
                press_time++;   
                if (press_time > LONG_PRESS_THRESHOLD) break;   
            }   
        
            // 长按:启停PWM + 控制AIN1/AIN2 + LED   
            if (press_time >= LONG_PRESS_THRESHOLD)   
            {   
                g_PwmRunning = !g_PwmRunning;   
                if (g_PwmRunning)   
                {   
                    // 电机运行:AIN1/AIN2电平相反(转向),启动PWM   
                    GPIO_PinWrite(BOARD_Direct_GPIO, BOARD_Direct1_GPIO_PIN, g_DirectionState);   
                    GPIO_PinWrite(BOARD_Direct_GPIO, BOARD_Direct2_GPIO_PIN, !g_DirectionState);   
                    PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);   
                    PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA,    
                                           kPWM_SignedCenterAligned, g_PwmDuty);   
                    GPIO_PinWrite(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, 0); // LED亮   
                }   
                else   
                {   
                    // 电机停止:AIN1/AIN2全低(刹车),PWM占空比置0并停止   
                    GPIO_PinWrite(BOARD_Direct_GPIO, BOARD_Direct1_GPIO_PIN, 0);   
                    GPIO_PinWrite(BOARD_Direct_GPIO, BOARD_Direct2_GPIO_PIN, 0);   
                    PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA,    
                                           kPWM_SignedCenterAligned, 0);   
                    PWM_StopTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);   
                    GPIO_PinWrite(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, 1); // LED灭   
                }   
            }   
            // 短按:占空比+10%(不超过100%)   
            else   
            {   
                g_PwmDuty = (g_PwmDuty + DUTY_STEP) > 100 ? 100 : (g_PwmDuty + DUTY_STEP);   
                PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA,    
                                       kPWM_SignedCenterAligned, g_PwmDuty);   
            }   
        }   
        
        /* 处理SW3按键(逻辑类似) */   
        if (g_Button3Press)   
        {   
            g_Button3Press = false;   
            while (GPIO_PinRead(BOARD_SW3_GPIO, BOARD_SW3_GPIO_PIN) == 0)   
            {   
                delay_ms(1);   
                press_time++;   
                if (press_time > LONG_PRESS_THRESHOLD) break;   
            }   
        
            // 长按:翻转方向引脚状态(切换AIN1/AIN2电平)   
            if (press_time >= LONG_PRESS_THRESHOLD)   
            {   
                g_DirectionState = !g_DirectionState;   
                GPIO_PinWrite(BOARD_Direct_GPIO, BOARD_Direct1_GPIO_PIN, g_DirectionState);   
                GPIO_PinWrite(BOARD_Direct_GPIO, BOARD_Direct2_GPIO_PIN, !g_DirectionState);   
            }   
            // 短按:占空比-10%(不低于10%)   
            else   
            {   
                g_PwmDuty = (g_PwmDuty - DUTY_STEP) < 11 ? 10 : (g_PwmDuty - DUTY_STEP);   
                PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA,    
                                       kPWM_SignedCenterAligned, g_PwmDuty);   
            }   
        }   
    }   
        

 

2.2.5 主循环

主循环仅轮询按键状态,调用长短按处理函数,降低系统资源占用:

        
    int main(void)   
    {   
        // 硬件初始化(GPIO、PWM、中断)   
        BOARD_InitHardware();   
        PWM_DRV_Init3PhPwm();   
        // 初始状态:PWM停止、LED灭、方向引脚全低   
        PWM_StopTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);   
        GPIO_PinWrite(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, 1);   
        
        // 主循环   
        while (1U)   
        {   
            Key_ProcessShortLongPress(); // 处理按键交互   
            delay_ms(10); // 降低循环频率,减少CPU占用   
        }   
    }   
        

 

三、测试验证

1. 硬件接线:按前文硬件连接方案,将MCUPWMGPIO引脚与TB6612FNG、按键、LED连接,电机接TB6612FNGA通道输出;

2. 烧录代码:通过Keil5将代码烧录至目标MCU

3. 功能验证

      SW2短按:电机转速逐步提升(占空比+10%),串口打印当前占空比;

      SW2长按:电机启停切换,LED同步亮灭(运行亮、停止灭);

      SW3短按:电机转速逐步降低(占空比-10%),串口打印当前占空比;

      SW3长按:电机方向瞬间切换(正转反转/反转正转)。

pwm.zip






关键词: Let's do 2025年第4期    

共1条 1/1 1 跳转至

回复

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