电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
基于鸿蒙操作系统的爱若琉璃(蜂鸣器版本)
分 享
扫描二维码分享
基于鸿蒙操作系统的爱若琉璃(蜂鸣器版本)
鸿蒙
蜂鸣器
PWM
嵌入式从0到1
关注
发布时间: 2020-11-19
丨
阅读: 3759
### 前言 经过一段时间的分享,基于Hi3861开发板的鸿蒙开发已经完成了下面核心板和OLED板两个子板的分享了。 ![](https://img-blog.csdnimg.cn/20201118213047611.png?#pic_center) 我们今天分享红绿黄灯板上的资源,对应原理图在下面文件中: HiSpark_WiFi_IoT_SSL_VER.A.pdf 这个红绿灯板子上有三个LED,分别是红黄绿三种颜色; 此外还有一个按键和一个无源蜂鸣器; 对应资源如下表所示: | 板载资源 | 系统资源 | | :---: | :--- | | 红灯_RED | D10(GPIO10)/UART2_CTS/SPI0_CLK/PWM1_OUT/I2C0_SDA | | 黄灯_YELLOW | A12(GPIO12)/UART2_RXD/SPI0_CS1/ADC0/PWM3_OUT | | 绿灯_GREEN | A11(GPIO11)/UART2_TXD/SPI0_RXD/ADC5/PWM2_OUT | | 蜂鸣器_BEEP(MLT-8530) | A9(**GPIO09**)/UART2_RTS/SPI0_TXD/ADC4/PWM0_OUT/I2C0_SC | | 按键_SWITCH | MOSI(SPI0_TXD)/@@**GPIO08**/PWM1_OUT | LED和按键的驱动我们之前已经分享过了,请参见下文: [**HarmonyOS实现点亮LED**](https://mp.weixin.qq.com/s/3TtqTvsF5NAn0uappeKTUQ) [**基于鸿蒙OS的按键驱动**](https://mp.weixin.qq.com/s/Ddb4h6EnlYI5yn45_qIQSA) [**一个ADC实现多个按键检测**](https://mp.weixin.qq.com/s/iZV_5Qe2YbA5Mw_ucIIBCg) 今天我们介绍一下鸿蒙系统下PWM的使用方法。 ### 实现目标 ##### 1. 蜂鸣器演奏歌曲《爱若琉璃》 ##### 2. 解决上次《你笑起来真好看》遗留问题,实现点击蜂鸣器板子上的按键,控制音乐播放或停止 ### 蜂鸣器原理图 ![](https://img-blog.csdnimg.cn/20201118213138679.png?#pic_center) 当BEEP为高电平的时候,三极管MMBT3904导通,蜂鸣器B1有电流流过;当BEEP为低电平的时候,三极管截止,蜂鸣器B1没有电流流过。 ### 按键中断 #### 按键初始化 设置按键对应GPIO08为输入、上拉模式的GPIO,并设置上升沿的中断函数为:`OnButtonPressed_isr` ```C IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO); GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_IN); IoSetPull(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_PULL_UP); GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_INT_TYPE_EDGE, WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH, OnButtonPressed_isr, NULL); ``` #### 按键中断函数 中断函数中主要改变控制音乐播放的一个布尔变量,在真和假之间来回切换。 ```C static void OnButtonPressed_isr(char* arg) { (void)arg; printf("[beep_demo.c] OnButtonPressed() \r\n"); bSongPlaying = !bSongPlaying; } ``` ### PWM脉冲产生 #### PWM初始化 ```C hi_pwm_set_clock(PWM_CLK_XTAL); //设置时钟源为晶体时钟; IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT);//IO复用为PWM功能 ret = GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);//设置为输出 if (ret != WIFI_IOT_SUCCESS) { printf("=====ERROR======gpio -> GpioSetDir ret:%d \r\n", ret); return; } hi_pwm_init(HI_PWM_PORT_PWM0);//初始化PWM ``` ### BUILD.gn文件 改写工程中的两个BUILD.gn文件。 ![](https://img-blog.csdnimg.cn/2020111821321620.png?#pic_center) ### 编译 添加完上面代码,如果直接编译的话,会报如下错误: ![](https://img-blog.csdnimg.cn/20201118213235258.png?#pic_center) 出错的原因是未开启PWM功能,开启PWM功能: 在 \vendor\hisi\hi3861\hi3861\build\config\usr_config.mk 文件中下图位置,添加一行代码:`CONFIG_PWM_SUPPORT=y` ![](https://img-blog.csdnimg.cn/20201118213252961.png?#pic_center) 再编译就没有问题了。 ### 测试PWM功能 改变PWM输出使用如下两个函数: ```C hi_u32 hi_pwm_stop(hi_pwm_port port) hi_u32 hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq) ``` 修改参数freq可以修改输出脉冲的频率,修改参数 duty可以改变占空比。 执行hi_pwm_start()函数开始PWM输出,执行hi_pwm_stop()函数PWM输出停止。 ##### 测试一 ```C hi_pwm_stop(HI_PWM_PORT_PWM0); hi_pwm_start(HI_PWM_PORT_PWM0, 1, 2); //25ns/25ns ``` ![测试一](https://img-blog.csdnimg.cn/20201118213315289.png?#pic_center) ##### 测试二 ```C hi_pwm_stop(HI_PWM_PORT_PWM0); hi_pwm_start(HI_PWM_PORT_PWM0, 3, 10); //75ns/250ns ``` ![测试二](https://img-blog.csdnimg.cn/2020111821333216.png?#pic_center) ##### 测试三 ```C hi_pwm_stop(HI_PWM_PORT_PWM0); hi_pwm_start(HI_PWM_PORT_PWM0, 30, 100); //0.75us/2.5us ``` ![测试三](https://img-blog.csdnimg.cn/20201118213352143.png?#pic_center) 由上面的测试,我们可以得出,参数 duty 和 freq 的值,1单位代表25 ns。 ### 实现《爱若琉璃》乐谱 现在我们实现了PWM输出的控制,接下来就是实现本文的目标了,实现蜂鸣器演奏《爱若琉璃》,蜂鸣器演奏音乐的原理详见之前网文: [**蜂鸣器演奏音乐“你笑起来真好看”**](https://mp.weixin.qq.com/s/ayGBE-ptwKJ1qPuFRcLj7Q) 由上面的网文我们知道,要想完成一个乐谱,我们只要确定“**音符(音调)**”和“**节拍**”即可。 音调表示一个音符响的频率,节拍表示一个音符该唱多长的时间。 #### 音符(音调)的确定 一般钢琴键盘有88个按键: ![](https://img-blog.csdnimg.cn/20201118213525444.png?#pic_center) 钢琴上88按键的频率如下表所示: ![](https://img-blog.csdnimg.cn/20201118213540361.png?#pic_center) 比如中央C音的标准频率就是261,在上面表格中就是:音名为C4的按键。 程序中定义一个音频的数组: ![](https://img-blog.csdnimg.cn/20201118213556779.png?#pic_center) 因为上面初始化PWM的时候,使用的是外部晶振作为时钟源`hi_pwm_set_clock(PWM_CLK_XTAL); ` ![](https://img-blog.csdnimg.cn/2020111821361559.png?#pic_center) 根据上面示波器中实测的结果可以推算出,这个时钟源为40M。 而输出的脉冲频率由这个函数决定的:`hi_u32 hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq)` 参数freq决定了脉冲的频率,这个参数是hi_u16类型,那么这个参数的有效范围为:2~65535。 所以输出的脉冲的最低频率为:40M / 65535 (下面有计算方法) ,即 40 * 1000 * 1000 / 65535 = 610.3608758678569 所以这个Hi3861芯片只能产生频率610以上的音,即`D#5`及以上的按键音,所以我们选择`C6`那组按键的音作为主音。所以我们预定义正常音的C6对应数组的索引为63。`#define N_B 63` ![](https://img-blog.csdnimg.cn/20201118213654925.png?#pic_center) 我们要想让蜂鸣器发出某个音只需要让PWM输出对应频率的脉冲即可: 网上找个《爱若琉璃》的简谱,然后按照对应关系创建如下乐谱数组: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201118213704713.png?#pic_center) #### 节拍的确定 节拍就是一个音持续的时间,这里就是PWM脉冲持续的时间,那么持续的时间如何确定呢? ![](https://img-blog.csdnimg.cn/20201118213717381.png?#pic_center) #### 播放一个音 音符(音调)和节拍的计算方法我们上面介绍完了,那么如果我们利用蜂鸣器播放第一个音,应该怎么确定呢? ![](https://img-blog.csdnimg.cn/20201118213731823.png?#pic_center) 要想播放一个音,就要使用`hi_pwm_start()`函数来产生一定频率的脉冲信号。 那频率是怎么计算出来的呢?也就是下面代码中delay_time这个变量是怎么计算出来的呢? ```C delay_time = 40 * 1000 * 1000/((hi_u32)pitch_names_frequency[ai_ruo_liu_li[0]]); hi_pwm_start(HI_PWM_PORT_PWM0, delay_time / 2, delay_time); ``` 由上面示波器我们得出,hi_pwm_start()函数的最后一个参数,一个单位长度为25ns(即:1/(40\*1000\*1000)),所以我们发送一定频率的脉冲,其实传进去的参数即为单位长度(25ns)的个数,具体推导过程如下: ![参数换算原理](https://img-blog.csdnimg.cn/20201118213759879.png?#pic_center) 一个音确定完之后,只要将这个音按照节拍播放即可,然后遍历完咱们自己转换的乐谱数组即可完成整首歌曲的播放。 因为在按键的中断函数中,每按一次,改变一次布尔变量`bSongPlaying`的真假。 ![](https://img-blog.csdnimg.cn/2020111821381641.png?#pic_center) 通过布尔变量`bSongPlaying`的真假,我们可以实现控制音乐播放的开启或停止。 ![](https://img-blog.csdnimg.cn/20201118213830910.png?#pic_center) ### 结果展示 视频展示请移步B站观看: https://www.bilibili.com/video/BV1sa411w7rh#reply3721065146 ### 资料获取 公众号**留言区置顶留言**获取本文对应工程文件及《爱若琉璃》的简谱。 ps: 文章首发于电子发烧友。 ### 欢迎关注 **程序员小哈**带你玩转嵌入式,微信搜索:**嵌入式从0到1**,更多干货等着你。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
嵌入式从0到1
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交