創建工程
這次因為沒有新增功能所以新建功能部分我就先略過了,大家可以參考一下上篇文章,其中我修改Kconfig,開啟PWM5 CH1/2/3的部分已經提交PR了,各位之后導入工程時可以先看一下RT-Thread Setting中是否已經顯示。
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會溢出。
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。
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()函數,這個函數可以將字符串轉化為無符號長整型。
/*
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 %sn",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,就會顯示如下顏色。
PWM教程之蜂鳴器唱歌
蜂鳴器部分主要參考了RT-Thread文檔中心的蜂鳴器播放器,大家有需要的話可以直接去看官方教程,我這里因為篇幅原因會有縮減。
蜂鳴器基礎知識
蜂鳴器是一種能夠通過電子信號控制的發聲器件。在生活中,幾乎所有能夠發出嗶嗶響聲的電子器件中都裝有蜂鳴器。蜂鳴器能夠為使用者提供直觀的聲音信息,是一種常見的人機交互模式。
根據是否內置震蕩電路可分為有源蜂鳴器和無源蜂鳴器。有源蜂鳴器只需要提供直流電壓就可以通過內部的震蕩電路產生震蕩電流進而發出聲音,而無源蜂鳴器需要輸入特定頻率的方波才能發出聲音。兩者比較起來,有源蜂鳴器的控制更加簡單,但是只能發出單一頻率的聲音,而無源蜂鳴器雖然控制起來比較麻煩,但是可以通過改變輸入方波的頻率發出不同音調的聲音,甚至可以用來演奏樂曲。
這里我們板載的是無源貼片蜂鳴器,這也是我們這個篇章的先決條件。
程序設計
本次我們需要的外設蜂鳴器,查看原理圖后發現我們需要的PWM4 CH3已經開好了,我們直接去RT-Thread Setting中開啟即可
之后創建beep.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/HZ10^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的功能。
#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;
}
后面關于音樂數據編碼解碼方面的知識,我自己也是完全是跟著教程的復刻,所以這里就不進行教程的搬運了,大家自行跟著官方教程吧。
-
led燈
+關注
關注
22文章
1592瀏覽量
108235 -
RGB
+關注
關注
4文章
801瀏覽量
58628 -
蜂鳴器
+關注
關注
12文章
893瀏覽量
46050 -
RT-Thread
+關注
關注
31文章
1305瀏覽量
40303 -
PWM輸出
+關注
關注
1文章
66瀏覽量
5207
發布評論請先 登錄
相關推薦
評論