Github
整个RTT学习过程中对工程的完善和开发都记录在Github上的一个项目中,项目还会随着学习的深入进行更新
项目URL:https://github.com/HITLIVING/-RT-Thread-.git
读者可以通过Pull下来整个项目进一步了解
对PWM驱动的实现需要格外关注steering_app.csteering_app.h
两个文件
外设配置
STM32F1RCT6芯片
野火MINI开发板自带显示屏(240*320)(仅用来显示信息,与PWM自身无关)
显示屏控制芯片ILI9341(仅用来显示信息,与PWM自身无关)
Cube
配置Tim定时器引脚,绑定通道
- 在选定引脚上开启定时器(PA15,TIM2,通用定时器,Channel1)
- 选择时钟源内部时钟
- 配置通道1PWM通用输出功能
Kconfig
添加Env配置选项
在 menu "On-chip Peripheral Drivers" 下添加代码段
menuconfig BSP_USING_PWMbool "Enable pwm"default nselect RT_USING_PWMif BSP_USING_PWMmenuconfig BSP_USING_PWM1bool "Enable timer2 output pwm"default nif BSP_USING_PWM1config BSP_USING_PWN2_CH1bool "Enable PWM1 channel1"default nendifendif
使得可以通过Env开启PWM驱动的配置
Env
开启PWM外设




使用 scons 指令生成MDK5工程,完成配置
MDK

在驱动文件夹下看到 drv_pwm 即配置成功
此时点击编译会报错
需要手动在pwm_config.h 文件下添加对PWM1的定义pwm_config.h可通过drv_pwm.c->drv_config.h->pwm_config.h找到
#ifdef BSP_USING_PWM1#ifndef PWM1_CONFIG#define PWM1_CONFIG \{ \.tim_handle.Instance = TIM2, \.name = "pwm1", \.channel = 1 \}#endif /* PWM1_CONFIG */#endif /* BSP_USING_PWM1 */
再次编译,无错误时,PWM的驱动配置已经完成
接口函数
查找 PWM 设备
应用程序根据 PWM 设备名称获取设备句柄,进而可以操作 PWM 设备,查找设备函数如下所示:
rt_device_t rt_device_find(const char* name);
| 参数 | 描述 |
|---|---|
| name | 设备名称 |
| 返回 | —— |
| 设备句柄 | 查找到对应设备将返回相应的设备句柄 |
| RT_NULL | 没有找到设备 |
设备名称即为在pwm_config.h中定义的设备名称
设备句柄需要用RT-Thread定义的PWM设备描述结构体接收
struct rt_device_pwm *pwm_dev; /* PWM 设备句柄 */
设置 PWM 周期和脉冲宽度
通过如下函数设置 PWM 周期和占空比:
rt_err_t rt_pwm_set(struct rt_device_pwm *device,int channel,rt_uint32_t period,rt_uint32_t pulse);
| 参数 | 描述 |
|---|---|
| device | PWM 设备句柄 |
| channel | PWM 通道 |
| period | PWM 周期时间 (单位纳秒 ns) |
| pulse | PWM 脉冲宽度时间 (单位纳秒 ns) |
| 返回 | —— |
| RT_EOK | 成功 |
| -RT_EIO | device 为空 |
| -RT_ENOSYS | 设备操作方法为空 |
| 其他错误码 | 执行失败 |
使能 PWM 设备
设置好 PWM 周期和脉冲宽度后就可以通过如下函数使能 PWM 设备:
rt_err_t rt_pwm_enable(struct rt_device_pwm *device, int channel);
| 参数 | 描述 |
|---|---|
| device | PWM 设备句柄 |
| channel | PWM 通道 |
| 返回 | —— |
| RT_EOK | 设备使能成功 |
| -RT_ENOSYS | 设备操作方法为空 |
| 其他错误码 | 设备使能失败 |
关闭 PWM 设备通道
通过如下函数关闭 PWM 设备对应通道。
rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel);
| 参数 | 描述 |
|---|---|
| device | PWM 设备句柄 |
| channel | PWM 通道 |
| 返回 | —— |
| RT_EOK | 设备关闭成功 |
| -RT_EIO | 设备句柄为空 |
| 其他错误码 | 设备关闭失败 |
上机实验
#include <rtthread.h>#include <rtdevice.h>#include <stdio.h>#include "steering_app.h"#include "drv_ili9341_lcd.h"rt_uint32_t PWM1_freq = 2000;rt_uint32_t PWM1_duty = 20;rt_err_t Steering_PWM_init(void){rt_uint32_t PWM1_period = 1000000000/PWM1_freq;rt_uint32_t PWM1_pulse = PWM1_period/100*PWM1_duty;/* PWM device handle */struct rt_device_pwm *pwm_dev;/* find device */pwm_dev = (struct rt_device_pwm *)rt_device_find("pwm1");if (pwm_dev == RT_NULL){rt_kprintf("pwm sample run failed! can't find pwm1 device!\n");return RT_ERROR;}/* set PWM period and pulse*/rt_pwm_set(pwm_dev, 1, PWM1_period, PWM1_pulse);/* enable PWM device */rt_pwm_enable(pwm_dev, 1);uILI9341_DispStringLine_EN (LINE(4), "PWM Signal Frequence:");ILI9341_DispStringLine_EN (LINE(6), "PWM Signal Duty:");return RT_EOK;}void Steering_PWM_Condition(void){char str_freq[] = {0};char str_duty[] = {0};sprintf(str_freq, "%d", PWM1_freq);sprintf(str_duty, "%d", PWM1_duty);ILI9341_DispStringLine_EN (LINE(5), str_freq);ILI9341_DispStringLine_EN (LINE(7), str_duty);}void Steering_PWM_Disable(void){/* PWM device handle */struct rt_device_pwm *pwm_dev;/* find device */pwm_dev = (struct rt_device_pwm *)rt_device_find("pwm1");/* disable PWM device */rt_pwm_disable(pwm_dev, 1);}
因为PWM在使用时更常用频率和占空比,这里设置了频率为2kHz,占空比为20%的PWM信号,转换成周期和脉宽后写入pwm1设备
结合前面控制界面的配置,将PWM设备定义成steering舵机的一个功能块并添加在了菜单中,可以通过选择调用,并将配置信息显示在显示屏上
万用表上有测量电信号的频率和占空比的功能,将表上显示的数据与屏幕显示对比即可得知PWM信号正常与否
实验效果
- 开机界面

- 菜单界面,选择第三个选项,舵机控制

- 测量输出信号频率

- 测量输出信号占空比

