Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
PWM
PWM
RT-Thread 中配置 PWM 输出详细过程
发布于 2021-12-15 17:28:12 浏览:3585
订阅该版
[tocm] ## RT-Thread 中配置 PWM 输出详细过程 **强烈建议,在配置PWM输出前,先将PWM对应管脚配置成普通GPIO,并高低切换输出,用示波器或万用表检测输出,以验证电路板的没问题!** 官方教程: ```c /** if you want to use pwm you can use the following instructions. * * STEP 1, open pwm driver framework support in the RT-Thread Settings file * * STEP 2, define macro related to the pwm * such as #define BSP_USING_PWM1 * * STEP 3, copy your pwm timer init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end if board.c file * such as void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) and * void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) * * STEP 4, modify your stm32xxxx_hal_config.h file to support pwm peripherals. define macro related to the peripherals * such as #define HAL_TIM_MODULE_ENABLED * */ ``` ### 1、配置 RT-Thread Setting 这个没啥好说的,用rt thread studio就配置,用mdk5就用env中的menuconfig配置 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20139723b9eb474bb487cb9c3db87717.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5L-u55CG5bel5bCP5YiY,size_20,color_FFFFFF,t_70,g_se,x_16) ### 2、board.h中给出定义 这个地方要加入,BSP_USING_PWM1_CH1,这类通道宏,这样才能通过drv_pwm.c文件中pwm_get_channel()函数打开通道。 当然工程中如果没有drv_pwm.h和drv_pwm.c,可以从rt thread源文件中拷贝出来。 ```c #define BSP_USING_PWM1 #define BSP_USING_PWM1_CH1 #define BSP_USING_PWM1_CH2 #define BSP_USING_PWM1_CH3 #define BSP_USING_PWM3 #define BSP_USING_PWM3_CH1 #define BSP_USING_PWM3_CH2 #define BSP_USING_PWM3_CH3 #define BSP_USING_PWM4 #define BSP_USING_PWM4_CH1 #define BSP_USING_PWM4_CH2 #define BSP_USING_PWM4_CH3 ``` pwm_get_channel()函数原型如下 ```c static void pwm_get_channel(void) { #ifdef BSP_USING_PWM1_CH1 stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 0; #endif #ifdef BSP_USING_PWM1_CH2 stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 1; #endif #ifdef BSP_USING_PWM1_CH3 stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 2; #endif .................... } ``` ### 3、加入cubemx生成的配置函数 在stm32裸机配置外设中,无非三个步骤,1、配置管脚,2、使能时钟(管脚时钟和外设时钟),3、配置外设 rt thread通过使用rt device的方法,帮你封装了第三步,配置外设,而前两个步骤就需要自己配置 官方给出需要拷贝void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) 和void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)这两个函数到board.c中 void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim);这个函数是配置对应管脚,相信大家在配置如IIC,ADC都遇到类似函数 void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base);这个函数是配置时钟的函数。 在配置完成后,generate code,生成对应工程,但可能是由于cubemx版本问题, 在time.c文件中只找到配置管脚void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim); 函数, 而配置时钟的void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) ;没有找到 ![在这里插入图片描述](https://img-blog.csdnimg.cn/70c647da94ac471a98105c3b80ee0525.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5L-u55CG5bel5bCP5YiY,size_20,color_FFFFFF,t_70,g_se,x_16) ```c /**************************************************************************** * 名称:HAL_TIM_MspPostInit * 功能:配置tim管脚 * 参数: * 作者:cubeMx * 日期:2021年12月15日 ****************************************************************************/ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle) { rt_kprintf("tim_gpio_init\r\n"); GPIO_InitTypeDef GPIO_InitStruct = {0}; if(timHandle->Instance==TIM1) { /* USER CODE BEGIN TIM1_MspPostInit 0 */ /* USER CODE END TIM1_MspPostInit 0 */ __HAL_RCC_GPIOE_CLK_ENABLE(); /**TIM1 GPIO Configuration PE9 ------> TIM1_CH1 PE11 ------> TIM1_CH2 PE13 ------> TIM1_CH3 */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_11|GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* USER CODE BEGIN TIM1_MspPostInit 1 */ /* USER CODE END TIM1_MspPostInit 1 */ } else if(timHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ __HAL_RCC_GPIOC_CLK_ENABLE(); /**TIM3 GPIO Configuration PC6 ------> TIM3_CH1 PC7 ------> TIM3_CH2 PC8 ------> TIM3_CH3 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* USER CODE BEGIN TIM3_MspPostInit 1 */ /* USER CODE END TIM3_MspPostInit 1 */ } else if(timHandle->Instance==TIM4) { /* USER CODE BEGIN TIM4_MspPostInit 0 */ /* USER CODE END TIM4_MspPostInit 0 */ __HAL_RCC_GPIOD_CLK_ENABLE(); /**TIM4 GPIO Configuration PD12 ------> TIM4_CH1 PD13 ------> TIM4_CH2 PD14 ------> TIM4_CH3 */ GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM4; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* USER CODE BEGIN TIM4_MspPostInit 1 */ /* USER CODE END TIM4_MspPostInit 1 */ } } ``` 虽然没有找到 void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) ;, 但是找到了同样功能的 void HAL_TIM_OC_MspInit(TIM_HandleTypeDef* tim_ocHandle); 作用都是将TIM的时钟使能,将这个函数复制到board.c中,并在drv_pwm.c中调用,调用位置可以放在 static rt_err_t stm32_hw_pwm_init(struct stm32_pwm *device)中的靠前部分(测试过,靠后可能失效) 其实,知道原理的话,这个问题好解,比如可以自己将__HAL_RCC_TIM1_CLK_ENABLE();放到函数static int stm32_pwm_init(void)中调用,效果也是一样的,都是使能时钟罢了。 ```c void HAL_TIM_OC_MspInit(TIM_HandleTypeDef* tim_ocHandle) { if(tim_ocHandle->Instance==TIM1) { /* USER CODE BEGIN TIM1_MspInit 0 */ /* USER CODE END TIM1_MspInit 0 */ /* TIM1 clock enable */ __HAL_RCC_TIM1_CLK_ENABLE(); /* USER CODE BEGIN TIM1_MspInit 1 */ /* USER CODE END TIM1_MspInit 1 */ } else if(tim_ocHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspInit 0 */ /* USER CODE END TIM3_MspInit 0 */ /* TIM3 clock enable */ __HAL_RCC_TIM3_CLK_ENABLE(); /* USER CODE BEGIN TIM3_MspInit 1 */ /* USER CODE END TIM3_MspInit 1 */ } else if(tim_ocHandle->Instance==TIM4) { /* USER CODE BEGIN TIM4_MspInit 0 */ /* USER CODE END TIM4_MspInit 0 */ /* TIM4 clock enable */ __HAL_RCC_TIM4_CLK_ENABLE(); /* USER CODE BEGIN TIM4_MspInit 1 */ /* USER CODE END TIM4_MspInit 1 */ } } ``` 调用位置: ```c static rt_err_t stm32_hw_pwm_init(struct stm32_pwm *device) { rt_err_t result = RT_EOK; TIM_HandleTypeDef *tim = RT_NULL; TIM_OC_InitTypeDef oc_config = {0}; TIM_MasterConfigTypeDef master_config = {0}; TIM_ClockConfigTypeDef clock_config = {0}; RT_ASSERT(device != RT_NULL); tim = (TIM_HandleTypeDef *)&device->tim_handle; /* configure the timer to pwm mode */ tim->Init.Prescaler = 0; tim->Init.CounterMode = TIM_COUNTERMODE_UP; tim->Init.Period = 0; tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4) tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; #endif //时钟配置,调用位置在此处,尽量放在前面,经过测试,放在后面就失效了 HAL_TIM_OC_MspInit(tim); if (HAL_TIM_PWM_Init(tim) != HAL_OK) { LOG_E("%s pwm init failed", device->name); result = -RT_ERROR; goto __exit; } 省略..... } ``` ### 4、在stm32f4xx_hal_conf.h中打开宏: ```c #define HAL_TIM_MODULE_ENABLED ``` ### 5、放个简单测试代码 ```c #include
#include
//PWM使能管脚 #define PWM_PITCH_EN 78 //PE14 #define PWM_ROLL_EN 38 //PC6 #define PWM_YAW_EN 60 //PD12 #define PWM_DEV_NAME "pwm1" /* PWM设备名称 */ #define PWM_DEV_CHANNEL 1 /* PWM通道 */ struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */ static int pwm() { rt_uint32_t period, pulse; period = 10000; /* 周期为0.5ms,单位为纳秒ns */ //500000 8s pulse = 0; /* PWM脉冲宽度值,单位为纳秒ns */ /* 查找设备 */ pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME); if (pwm_dev == RT_NULL) { rt_kprintf("pwm sample run failed! can't find %s device!\n",PWM_DEV_NAME); return RT_ERROR; } /* 使能设备 */ rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL); pulse = period/2; /* 设置PWM周期和脉冲宽度 */ rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse); return 0; } INIT_APP_EXPORT(pwm); ``` ### 6、结果 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1bc46cc94d314c3bae30f5bad1fa824b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5L-u55CG5bel5bCP5YiY,size_20,color_FFFFFF,t_70,g_se,x_16)
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
龙王赘婿
油腻才是必杀技
文章
3
回答
10
被采纳
0
关注TA
发私信
相关文章
1
玩iot camera笔记之3测试试用3路pwm
2
[已解决]PWM输出异常分析
3
给RT-Thread添加PWM驱动框架
4
关于rt-thread-3.1.0 pwm
5
关于rt-thread的PWM框架在stm32f103vf应用的疑问
6
rt-thread stm32 bsp adc pwm 外设适配好了吗
7
stm32f103ze 添加pwm 设备失败
8
【正点原子】潘多拉IoT-STM32L475开发板 用menuconfig 看不到PWM....
9
关于rtthread 4.0.0版本中pwm的初始化定时器寄存器读写问题
10
RT-Thread正点原子战舰V3使用PWM设备驱动没有输出
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
线程
RT-Thread Nano
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
807
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部