Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
技术分享
教程笔记
原创征文
基于RoboMasterC型开发板的RT-Thread使用分享(三)PWM扩展实验
发布于 2023-01-01 20:07:04 浏览:623
订阅该版
[tocm] 大家新年快乐!新年第一天继续填坑,本篇为一篇小文章,延续我们上一篇的PWM,我们来实现aRGB灯光调色与蜂鸣器唱歌的功能。 ### 创建工程 ****** 这次因为没有新增功能所以新建功能部分我就先略过了,大家可以参考一下上篇文章,其中我修改Kconfig,开启PWM5 CH1/2/3的部分已经提交PR了,各位之后导入工程时可以先看一下RT-Thread Setting中是否已经显示。上期链接如下 [RT-Thread-基于RoboMasterC型开发板的RT-Thread使用分享(二)RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/2240be90085f3b35.html) ### PWM教程之aRGB LED灯调色 ******* #### aRGB三原色 aRGB 为一种色彩模式,aRGB 分别代表了 alpha(透明度)、Red(红色)、Green(绿色)和Blue(蓝色)四个要素,一般我们给每个要素设置十进制下 0-255 的取值范围,通过 16 进制表示就是 0x00-0xFF,因此一个 aRGB 值可以通过八位十六进制数来描述,从前到后每两位依次对应 a,R,G,B。 在 aRGB 中,alpha 值越大色彩越不透明,RGB 中哪个值越大,对应的色彩就越强。比如纯红色可以用 8 位 16 进制表示为 0xFFFF0000,纯绿色可以表示为 0xFF00FF00,纯蓝色可以表示为 0xFF0000FF,黄色由蓝色和绿色合成,所以可以表示为 0xFF00FFFF。 #### 程序设计 根据上面的描述我们就可以创建一个rt_uint32_t类型变量作为我们的aRGB值。之后每八位分别作为我们的alpha(透明度)、Red(红色)、Green(绿色)和Blue(蓝色)四个要素。我这里为了代码变量的清晰,我定义了一个aRGB结构体,用于装载计算后的aRGB值。大家可以自行尝试一下。这里三原色的类型为rt_uint16_t的原因之后我们计算过程中需要给它们乘以alpha因此使用rt_uint8_t会溢出。 ```c typedef struct { rt_uint8_t alpha; /* 透明度 最大值为FF */ rt_uint16_t red; rt_uint16_t green; rt_uint16_t blue; } aRGB; ``` 下面就是计算函数,这里我们需要把传进来的rt_uint32_t整型进行位运算,将每八位的值移入给我们的结构体成员内。然后用透明度alpha与R、G、B三者依次相乘。后面我们就可以将R、G、B各值作为脉冲宽度。这里R、G、B三个值计算出来范围是0-65536,我们所以我们后面将PWM周期设置为65536。 ```C static void aRGB_count(aRGB* LED_aRGB, rt_uint32_t set_aRGB) { LED_aRGB->alpha = (set_aRGB & 0xFF000000) >> 24; LED_aRGB->red = ((set_aRGB & 0x00FF0000) >> 16) * LED_aRGB->alpha; LED_aRGB->green = ((set_aRGB & 0x0000FF00) >> 8) * LED_aRGB->alpha; LED_aRGB->blue = ((set_aRGB & 0x000000FF) >> 0) * LED_aRGB->alpha; } ``` 下面就放出完整代码,这里我是自定义了一个MSH命令,输入`aRGB_led_sample 0xFF00FF00`之类的命令即可设置aRGB值。 用于MSH命令输入的参数都是字符串,所以这里我使用了stroul()函数,这个函数可以将字符串转化为无符号长整型。 ```c /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-12-31 Goldengrandpa the first version */ #include
#include
#include "stdlib.h" /* 使用其中的函数:strtoul(); */ #define PWM_DEV_NAME "pwm5" /* PWM设备名称 */ #define PWM_DEV_LEDB_CHANNEL 1 /* 蓝灯PWM通道 */ #define PWM_DEV_LEDG_CHANNEL 2 /* 绿灯PWM通道 */ #define PWM_DEV_LEDR_CHANNEL 3 /* 红灯PWM通道 */ struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */ /*aRGB结构体*/ typedef struct { rt_uint8_t alpha; /* 透明度 最大值为FF */ rt_uint16_t red; rt_uint16_t green; rt_uint16_t blue; } aRGB; aRGB LED_aRGB={0,0,0,0}; static void aRGB_count(aRGB* LED_aRGB, rt_uint32_t set_aRGB) { LED_aRGB->alpha = (set_aRGB & 0xFF000000) >> 24; LED_aRGB->red = ((set_aRGB & 0x00FF0000) >> 16) * LED_aRGB->alpha; LED_aRGB->green = ((set_aRGB & 0x0000FF00) >> 8) * LED_aRGB->alpha; LED_aRGB->blue = ((set_aRGB & 0x000000FF) >> 0) * LED_aRGB->alpha; } static int aRGB_led_sample(int argc, char *argv[]) { /* 查找设备 */ 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_uint32_t ui32_aRGB = 0; /* 用于字符串数据的检测与转换 */ rt_kprintf("input para is: %s %s\n",argv[0],argv[1]); if(2!=argc) { rt_kprintf("error cmd! please input as: (0x7FFFFFFF) \n"); return RT_ERROR; } ui32_aRGB=(rt_uint32_t)strtoul(argv[1],NULL,16);/* 将字符串转换为16进制数 */ aRGB_count(&LED_aRGB, ui32_aRGB); rt_uint32_t period=65536; rt_pwm_set(pwm_dev, PWM_DEV_LEDB_CHANNEL, period, LED_aRGB.blue); rt_pwm_set(pwm_dev, PWM_DEV_LEDG_CHANNEL, period, LED_aRGB.green); rt_pwm_set(pwm_dev, PWM_DEV_LEDR_CHANNEL, period, LED_aRGB.red); rt_pwm_enable(pwm_dev, PWM_DEV_LEDB_CHANNEL); rt_pwm_enable(pwm_dev, PWM_DEV_LEDG_CHANNEL); rt_pwm_enable(pwm_dev, PWM_DEV_LEDR_CHANNEL); } MSH_CMD_EXPORT(aRGB_led_sample, pwm aRGB sample) ``` 实验效果如下我们在MSH控制台输入0xFF00FF00,就会亮绿灯。如果输入0x88888888,就会显示如下颜色。 ![screenshot_image-20230101103017816.png](https://oss-club.rt-thread.org/uploads/20230101/4a14365917ee3675acca58f8c8fe606e.png.webp) ![screenshot_image-20230101103744040.png](https://oss-club.rt-thread.org/uploads/20230101/181549eaa7c288240ebcb5c2f324ed2f.png.webp) ### PWM教程之蜂鸣器唱歌 ****** [简介 (rt-thread.org)](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/tutorial/beep-player/README) 蜂鸣器部分主要参考了RT-Thread文档中心的蜂鸣器播放器,大家有需要的话可以直接去看官方教程,我这里因为篇幅原因会有缩减。 #### 蜂鸣器基础知识 蜂鸣器是一种能够通过电子信号控制的发声器件。在生活中,几乎所有能够发出哔哔响声的电子器件中都装有蜂鸣器。蜂鸣器能够为使用者提供直观的声音信息,是一种常见的人机交互模式。 根据是否内置震荡电路可分为有源蜂鸣器和无源蜂鸣器。有源蜂鸣器只需要提供直流电压就可以通过内部的震荡电路产生震荡电流进而发出声音,而无源蜂鸣器需要输入特定频率的方波才能发出声音。两者比较起来,有源蜂鸣器的控制更加简单,但是只能发出单一频率的声音,而无源蜂鸣器虽然控制起来比较麻烦,但是可以通过改变输入方波的频率发出不同音调的声音,甚至可以用来演奏乐曲。 这里我们板载的是无源贴片蜂鸣器,这也是我们这个篇章的先决条件。 #### 程序设计 本次我们需要的外设蜂鸣器,查看原理图后发现我们需要的PWM4 CH3已经开好了,我们直接去RT-Thread Setting中开启即可 ![screenshot_image-20230101173626187.png](https://oss-club.rt-thread.org/uploads/20230101/f37b8b1792b33db4b8e079a1f3b03829.png.webp) ![screenshot_image-20230101173218753.png](https://oss-club.rt-thread.org/uploads/20230101/61ea00a15332e9ee080d7164da595426.png.webp) 之后创建beep.c文件,编写蜂鸣器相关代码 ```C /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-01-01 Goldengrandpa the first version */ #include "beep.h" #include
//使用 RT-Thread 的设备需要包含此头文件 struct rt_device_pwm *pwm_device = RT_NULL; //定义 pwm 设备指针 int beep_init(void) { /* 查找PWM设备 */ pwm_device = (struct rt_device_pwm *)rt_device_find(BEEP_PWM_DEVICE); if (pwm_device == RT_NULL) { rt_kprintf("pwm device %s not found!\n", BEEP_PWM_DEVICE); return -RT_ERROR; } return 0; } int beep_on(void) { rt_pwm_enable(pwm_device, BEEP_PWM_CH); //使能蜂鸣器对应的 PWM 通道 return 0; } int beep_off(void) { rt_pwm_disable(pwm_device, BEEP_PWM_CH); //失能蜂鸣器对应的 PWM 通道 return 0; } int beep_set(uint16_t freq, uint8_t volume) { rt_uint32_t period, pulse; /* 将频率转化为周期 周期单位:ns 频率单位:HZ */ period = 1000000000 / freq; //unit:ns 1/HZ*10^9 = ns /* 根据声音大小计算占空比 蜂鸣器低电平触发 */ pulse = period - period / 100 * volume; /* 利用 PWM API 设定 周期和占空比 */ rt_pwm_set(pwm_device, BEEP_PWM_CH, period, pulse);//channel,period,pulse return 0; } ``` 之后我们后面音符频率对周期进行设置,下面程序就实现了播放音符CDEFGAB的功能。 ```c #include
#include "beep.h" uint16_t freq_tab[12] = {262, 277, 294, 311, 330, 349, 369, 392, 415, 440, 466, 494}; //原始频率表 CDEFGAB uint8_t beep_volume = 3; int main(void) { /* user app entry */ int i; beep_init(); for (i = 0; i < 12; i++) { beep_set(freq_tab[i], beep_volume); beep_on(); rt_thread_mdelay(500); beep_off(); rt_thread_mdelay(500); } return 0; } ``` 后面关于音乐数据编码解码方面的知识,我自己也是完全是跟着教程的复刻,所以这里就不进行教程的搬运了,大家自行跟着官方教程吧。[音乐数据的编码与解码 (rt-thread.org)](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/tutorial/beep-player/decode) 这里再次祝大家元旦快乐!🤩 ### 往期教程 ******* [RT-Thread-基于RoboMasterC型开发板的RT-Thread使用分享(一)RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/09dffc578f32d85d.html) [RT-Thread-基于RoboMasterC型开发板的RT-Thread使用分享(二)RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/2240be90085f3b35.html)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
goldengrandpa
这家伙很懒,什么也没写!
文章
11
回答
19
被采纳
2
关注TA
发私信
相关文章
推荐文章
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
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
keil_MDK
msh
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部