RT-Thread Studio 使用STM32CubeMX联合开发——PWM使用

本文详细介绍了如何在RT-ThreadStudio中结合STM32CubeMX进行PWM配置,包括设置PWM通道、生成代码、RT-ThreadStudio配置、解决PWM输出及互补输出问题,旨在帮助开发者顺利实现PWM功能。
摘要由CSDN通过智能技术生成

引言

        本文为RT-Thread Studio 使用STM32CubeMX联合开发中——PWM的使用。PWM包含:

  • 通用PWM;
  • PWM互补输出;

一、CubeMX配置

        先创建一个RTT工程

        打开CubeMX Settings

        使用外置时钟需要自己配置一下,你们根据自己的配好。

        开串口、开定时器1,打开通道1PWM模式

        重点来了,这里按默认的勾选下面两个就行了,不要生成单独的.c和.h文件。IDE选MDK吧,不重要,选哪个都可以。选完点生成代码。

        最后,一定一定要记住,把CubeMX关了!不关了有些配置文件没给你写入,可能以后的版本会优化这个问题。

        看到提示,说明文件生成好了。并且多了一个cubemx文件夹,而且是帮你自动生成好这个SConscript脚本文件。如果没有自己新建一个。

        没有自动帮你生成SConscript文件的,新建一个然后粘贴一下代码就可以了,一样的:

import os
from building import *

cwd = GetCurrentDir()
src  = Glob('*.c')
# add cubemx drivers
src = Split('''
Src/stm32f4xx_hal_msp.c
Src/main.c
''')

path = [cwd]
path += [cwd + '/Inc']

group = DefineGroup('cubemx', src, depend = [''], CPPPATH = path)

Return('group')

        弄好之后,右键项目名称,点击同步scons配置,更新一下项目结构。然后编译,0错误0警告。

二、配置RT-Thread Studio

        打开RT-Thread settings。打开PWM设备。然后Ctrl + s保存。

        这时候编译会发现报几个错误。不要慌,因为还要配置一下代码。

        打开board.h文件,找到配置PWM的地方。修改好宏定义。这里的PWM1就是定时器1,PWM2就是定时器2,具体通道+CHx。我这里配置了定时器1通道1。

        这时候编译还有报错,这是因为RT-Thread的库没给你写好定时器1的配置代码,自己加一下就好了,很快。如果你是定时器2或者其他,它以及给你自己加好了。

        我们现在继续来解决定时器1的问题。

        来到pwm_config.h文件就发现,确实没加定时器1的代码。复制一下定时器2的上来改成1就行了。

        此时所有的配置完成。还有一个警告不用管,那个是 long unsigned int* 和 unsigned int* 类型不符合报的,不重要。

三、加入测试代码

        这个是main.c文件。主要是加入用PWM做呼吸灯的效果,加入后编译运行。

/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-04-26     RT-Thread    first version
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include "drivers/rt_drv_pwm.h"

rt_thread_t Pwm_thread1;

#define PWM2_DEV            "pwm1"
#define PWM_DEV_CHANNEL     1/* PWM通 道 */

struct rt_device_pwm *pwm_dev; /* PWM设 备 句 柄 */

void PWM_Thread(void *parameter)
{
    rt_uint32_t period, pulse, dir;

    period = 5000;
    dir = 1; /* PWM脉冲宽度值的增减方向 */
    pulse = 0; /* PWM脉冲宽度值 */

    pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM2_DEV);
    if (pwm_dev == RT_NULL)
    {
        LOG_E("pwm sample run failed! can't find %s device!\n", PWM2_DEV);
        goto EXIT_TASK;
    }
    /* 配置PWM */
    if (rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse) != RT_EOK)
    {
        LOG_E("rt_pwm_set ERROR");
        goto EXIT_TASK;
    }
    /*  使能PWM */
    if (rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL) != RT_EOK)
    {
        LOG_E("rt_pwm_enable Error");
        goto EXIT_TASK;
    }

    LOG_D("PWM device ready! find %s device!\n", PWM2_DEV);

    for(;;)
    {
        rt_thread_mdelay(50);
        if (dir)
        {
            pulse += 500;
        }
        else
        {
            pulse -= 500;
        }
        if (pulse >= period)
        {
            dir = 0;
        }
        if (0 == pulse)
        {
            LOG_D("rt_pwm_set Dir");
            dir = 1;
        }
        /* 配置PWM */
        if (rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse) != RT_EOK)
        {
            LOG_E("rt_pwm_set ERROR");
            break;
        }
    }
EXIT_TASK:
    rt_thread_mdelay(50);
}


int main(void)
{
    int count = 1;

    /* 创建 PWM_Thread 线程 */
    Pwm_thread1 = rt_thread_create("PWM_Thread", PWM_Thread, RT_NULL, 1024, 10, 10);
    /* 创建成功则启动线程 */
    if (Pwm_thread1 != RT_NULL)
    {
        LOG_D("Create PWM_Thread success.");
        rt_thread_startup(Pwm_thread1);
    }

    while (count++)
    {
        LOG_D("Hello RT-Thread!");
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

效果。

RTT系统PWM使用测试效果

四、配置PWM互补

(1)CubeMX配置

        点开CubeMX settings,让它自动打开CubeMX。选择PWM互补,记住下互补输出引脚。然后生成代码关闭CubeMX。

(2)代码配置

        之前的代码不要动!加几行代码即可。主要是:PWM互补通道、使能PWM互补通道。

效果,PA7互补通道的输出。

PWM呼吸灯测试

五、PWM没有输出问题或者没有互补输出

        原因:在部分版本的RT-Thread代码中有些代码是没给你加的。例如:PWM的初始化、PWM的启动,这些都需要我们手动加一下。

        开始解决:请注意,你的RT-Thread代码版本至少保持在V4.1.0以上,然后按照上面的配置做好,然后接下来我们开始加代码。

(1)解决没有PWM输出的问题

        打开CubeMX生成的main.c文件,不是RT-Thread studio里面的那个!然后找到定时器的初始化函数,我们需要调用这个函数去初始化,否则你的PWM没有输出。

        在main.c文件里面另外写一个给外部调用这个自动生成的初始化函数的函数。

void RTT_STM32_HAL_PWM_Init(void)
{
    MX_TIM1_Init();
}

         然后去到board.c文件里面声明并调用这个函数。

        加入测试代码。     

/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-04-27     RT-Thread    first version
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

/* --------------------------------------> PWM Test <-------------------------------------- */

#include "drivers/rt_drv_pwm.h"

rt_thread_t Pwm_thread1;

#define PWM1_DEV "pwm1"
#define PWM1_DEV_CHANNEL 1 /* PWM通 道 */
#define PWM1_DEV_CHANNEL_N -1 /* PW互补M通道 */

struct rt_device_pwm *pwm_dev; /* PWM设 备 句 柄 */

void PWM_Thread(void *parameter)
{
    rt_uint32_t period, pulse;

    period = 1000 * 1000;           /* Unit: ns.  */
    pulse = 500 * 1000;             /* Unit: ns. */

    pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM1_DEV);
    if (pwm_dev == RT_NULL)
    {
        LOG_E("pwm sample run failed! can't find %s device!\n", PWM1_DEV);
        goto EXIT_TASK;
    }
    /* 配置PWM */
    if (rt_pwm_set(pwm_dev, PWM1_DEV_CHANNEL, period, pulse) != RT_EOK)
    {
        LOG_E("rt_pwm_set ERROR");
        goto EXIT_TASK;
    }
    /*  使能PWM */
    if (rt_pwm_enable(pwm_dev, PWM1_DEV_CHANNEL) != RT_EOK)
    {
        LOG_E("rt_pwm_enable Error");
        goto EXIT_TASK;
    }
    /*  使能PWM互补 */
    if (rt_pwm_enable(pwm_dev, PWM1_DEV_CHANNEL_N) != RT_EOK)
    {
        LOG_E("rt_pwm_enable complementary Error");
        goto EXIT_TASK;
    }

    LOG_D("PWM device ready! find %s device!\n", PWM1_DEV);

    for (;;)
    {
        rt_thread_mdelay(50);
    }
EXIT_TASK:
    rt_thread_mdelay(50);
}

/* --------------------------------------> PWM Test End <-------------------------------------- */

int main(void)
{
    int count = 1;

    /* 创建 PWM_Thread 线程 */
    Pwm_thread1 = rt_thread_create("PWM_Thread", PWM_Thread, RT_NULL, 2048, 10, 10);
    /* 创建成功则启动线程 */
    if (Pwm_thread1 != RT_NULL)
    {
        LOG_D("Create PWM_Thread success.");
        rt_thread_startup(Pwm_thread1);
    }

    while (count++)
    {
        LOG_D("Hello RT-Thread!");
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

        至此,可以解决PWM没有输出的问题,但是没有互补输出。

(2)解决没有PWM互补输出的问题

        上面的代码中,明显我们加了互补输出的代码,但是看通道2,并没有输出。原因是RT-Thread给你启动PWM的时候并没有写控制互补输出的代码。我们加一下。

        加入代码。注意!低版本的RT-Thread没有这个参数:configuration->complementary。这个参数是用来判断是否需要启动互补输出。

static rt_err_t drv_pwm_enable(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration, rt_bool_t enable)
{
    /* Converts the channel number to the channel number of Hal library */
    rt_uint32_t channel = 0x04 * (configuration->channel - 1);

    if (!enable)
    {
        if (configuration->complementary != RT_TRUE)
        {
            HAL_TIM_PWM_Stop(htim, channel);
        }
        else
        {
            HAL_TIMEx_PWMN_Stop(htim, channel);
        }
    }
    else
    {
        if (configuration->complementary != RT_TRUE)
        {
            HAL_TIM_PWM_Start(htim, channel);
        }
        else
        {
            HAL_TIMEx_PWMN_Start(htim, channel);
        }
    }

    return RT_EOK;
}

        编译,运行。可以发现有互补输出了!

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Troubadour~

觉得不错,打赏支持一下!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值