0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何用鸿蒙OS在蜂鸣器播放音乐

鸿蒙系统HarmonyOS 来源:oschina 作者:osc_2wq8ft8d 2020-11-11 12:04 次阅读

本文介绍如何在HiSpark Wi-Fi IoT套件上,使用Harmony OS IoT硬件子系统的PWM接口 驱动蜂鸣器 播放音乐。

用PWM输出方波

PWM输出的方波频率

通过PwmStart接口的注释,可以知道freq参数是分频倍数,PWM实际输出的方波频率等于 PWM时钟源频率 除以 分频倍数,即

f = Fcs / freq

其中,Fcs是PWM时钟源频率;

PWM输出方波的占空比

通过PwmStart接口的duty参数可以控制输出方波的占空比,占空比是指PWM输出的方波波形的高电平时间占整个方波周期的比例,具体占空比值是 duty 和 freq的比值,例如想要输出占空比 50%的方波信号,那么duty填的值就要是 freq/2;

音符-频率对应关系

参考:https://liam.page/2018/04/09/pitch-interval-and-harmonic/

开发板可以输出的最低频率

通过前面的公式,我们知道:

PWM输出的方波频率和freq成反比,freq越大,输出的方波频率越小;

freq是unsinged short类型,最大值为65535;
因此,输出频率的最小值取决于时钟源,PWM的默认时钟源为160M:

unsignedintHalPwmInit(HalWifiIotPwmPortport){if(hi_pwm_set_clock(PWM_CLK_160M)!=HI_ERR_SUCCESS){return(unsignedint)HAL_WIFI_IOT_FAILURE;
}returnhi_pwm_init((hi_pwm_port)port);
}

我们通过直接调用hi_pwm_set_clock接口,可以修改时钟源:

/**
*@ingroupiot_pwm
*
*EnumeratesthePWMclocksources.CNcomment:PWM时钟源枚举。CNend
*/typedefenum{
PWM_CLK_160M,/**< 160M APB clock.CNcomment:160M 工作时钟 CNend */
    PWM_CLK_XTAL, /**< 24M/40M crystal clock.CNcomment:24M或40M 晶体时钟 CNend */
    PWM_CLK_MAX   /**< Maximum value, which cannot be used.CNcomment:最大值,不可使用CNend */} hi_pwm_clk_source;hi_u32 hi_pwm_set_clock(hi_pwm_clk_source clk_type);

通过注释我们知道hi_pwm_set_clock(PWM_CLK_XTAL);可以将时钟源设置为晶体时钟,晶体时钟可能为24M或40M;
那么问题来了——晶体时钟到底是多少?

晶体时钟频率是多少?

我们可以通过通过实验,测算出晶体时钟频率,具体步骤如下:

使用hi_pwm_set_clock(PWM_CLK_XTAL);设置时钟源为晶体时钟;

使用PwmStart(WIFI_IOT_PWM_PORT_PWM0, 20*1000, 40*1000);输出方波信号;

使用示波器测量方波频率;
经实际测量,方波评率为1000Hz,因此,时钟频率为1000 * 40 * 1000也就是 40 MHz;

可以输出的方波最低频率

因此,方波最低频率就是 40M / 65535 ,也就是:

>>>40*1000*1000/65535
610.3608758678569

对照上面的频率表,可以知道,能够输出E♭以上的所有音符;

准备曲谱

为了代码实现起来简单,我选择了《两只老虎》的曲谱作为素材,很快找到了简谱:

简谱说明

对于缺乏音乐基础的同学,简谱上的一些记号可能不太清楚是什么意思,这里简单说明一下:

左上角的1=C是表示调式(可以不用关心),1是唱名,C是音名,1=C是正调(就是常规的对应关系: 1-C,2-D, 3-E, 4-F, 5-G, 6-A, 7-B);

左上角的 4/4 是四四拍,是指 四分音符为一拍, 每小节有四拍;

下面谱子上的竖线就是每个小节分隔符,和4/4对应;

“跑得快”上面5后面的横线表示延时一拍;

“一直没有眼睛”一句,5后面的点表示顺延半拍,一条下划线表示二分之一时间,两条下划线表示四分之一时间;

编写代码

有了以上知识,我们就可以编写代码了,关键部分代码如下:

staticvolatileintg_buttonPressed=0;staticconstuint16_tg_tuneFreqs[]={0,//40MHz对应的分频系数:
38223,//11046.5
34052,//21174.7
30338,//31318.5
28635,//41396.9
25511,//51568
22728,//61760
20249,//71975.5
51021//5_783.99//第一个八度的5};//曲谱音符staticconstuint8_tg_scoreNotes[]={//《两只老虎》简谱:http://www.jianpu.cn/pu/33/33945.htm
1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,4,3,1,5,6,5,4,3,1,1,8,1,1,8,1,//最后两个5应该是低八度的,链接图片中的曲谱不对,声音到最后听起来不太对劲};//曲谱时值,根据简谱记谱方法转写,4/4拍中下面划一条线是半拍,划两条线是四分之一拍,点是顺延半拍staticconstuint8_tg_scoreDurations[]={4,4,4,4,4,4,4,4,4,4,8,4,4,8,3,1,3,1,4,4,3,1,3,1,4,4,4,4,8,4,4,8,
};staticvoid*BeeperMusicTask(constchar*arg){
(void)arg;printf("BeeperMusicTaskstart!\r\n");

hi_pwm_set_clock(PWM_CLK_XTAL);//设置时钟源为晶体时钟(40MHz,默认时钟源160MHz)

for(size_ti=0;i< sizeof(g_scoreNotes)/sizeof(g_scoreNotes[0]); i++) {        uint32_t tune = g_scoreNotes[i]; // 音符
        uint16_t freqDivisor = g_tuneFreqs[tune];        uint32_t tuneInterval = g_scoreDurations[i] * (125*1000); // 音符时间
        printf("%d %d %d %d\r\n", tune, (40*1000*1000) / freqDivisor, freqDivisor, tuneInterval);
        PwmStart(WIFI_IOT_PWM_PORT_PWM0, freqDivisor/2, freqDivisor);
        usleep(tuneInterval);
        PwmStop(WIFI_IOT_PWM_PORT_PWM0);
    }    return NULL;
}

其中谱子最后两个5是谱子的错误,应该是低八度的5,也就是5下面应该打一个点;我修改了代码,让整个曲子听起来更自然;

编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 有源无源蜂鸣器

    关注

    0

    文章

    2

    浏览量

    1134
  • 鸿蒙
    +关注

    关注

    55

    文章

    1561

    浏览量

    42109
收藏 人收藏

    评论

    相关推荐

    鸿蒙HarmonyOS开发实战:【分布式音乐播放

    本示例使用fileIo获取指定音频文件,并通过AudioPlayer完成了音乐播放完成了基本的音乐播放、暂停、上一曲、下一曲功能;并使用DeviceManager完成了分布式设备列表
    的头像 发表于 04-10 17:51 383次阅读
    <b class='flag-5'>鸿蒙</b>HarmonyOS开发实战:【分布式<b class='flag-5'>音乐</b><b class='flag-5'>播放</b>】

    鸿蒙OS和开源鸿蒙什么关系?

    内核,其他功能都以模块的形式存在。     华为用的是鸿蒙OS 我们都知道,华为手机的鸿蒙OS是可以运行安卓软件的,是因为系统中有安卓兼容层,所以可以简单这么理解:
    的头像 发表于 01-30 15:44 352次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b>和开源<b class='flag-5'>鸿蒙</b>什么关系?

    arduino能用pwm播放音乐吗?

    arduino能用pwm播放音乐吗,歌曲通过外部的flash存储
    发表于 11-08 08:19

    何用手机推送音乐给单片机播放

    何用手机推送音乐给单片机播放?有几种方案 各有什么特点?
    发表于 10-26 06:22

    何用Java播放声音

    在本篇文章中,我们将学习如何用Java播放音乐,Java 声音 API 的设计是为了流畅和连续地播放声音,甚至是很长的声音。我们将使用 Java 提供的 Clip 和 SourceDataLine
    的头像 发表于 10-09 10:56 1743次阅读

    在Arduino中播放音

    电子发烧友网站提供《在Arduino中播放音频.zip》资料免费下载
    发表于 06-25 15:16 0次下载
    在Arduino中<b class='flag-5'>播放音</b>频

    如何制作可以播放音乐的步进电机

    电子发烧友网站提供《如何制作可以播放音乐的步进电机.zip》资料免费下载
    发表于 06-07 10:44 0次下载
    如何制作可以<b class='flag-5'>播放音乐</b>的步进电机

    为什么无法使用媒体播放器应用程序通过GUIandroid11中播放音频?

    1. 命令提示符下使用 Tinyplay 命令,我们验证了模块是否正常工作。默认 wm8960 模块正在播放,音频也播放。 2.我们播放
    发表于 05-30 07:11

    Android11中通过GUI的wm8960模块播放音频找不到是为什么?

    , channel: 28 3.1 通过媒体播放器应用程序播放音频需要进行哪些更改? 3.2 audio_policy_configuration.xml 是否需要更改任何配置? 其中添加了一些配置,但它没有像我们预期的那样工作。 我附上了通过不同采样率的
    发表于 05-17 10:00

    基于51单片机的蜂鸣器播放音乐源代码

    基于51单片机的蜂鸣器播放音乐例程源代码
    发表于 05-12 16:16 44次下载

    CH32V103基础教程95-PWM驱动蜂鸣器

    本章教程主要在第九十三章的基础上运行,用以驱动蜂鸣器播放音乐。 1、TIM简介及相关函数介绍关于TIM,在前面章节已经进行过介绍,在此不再赘述。关于PWM驱动蜂鸣器播放音乐原理,通过改
    发表于 05-11 16:15

    CH32V103基础教程-PWM播放音乐(2个TIM)

    。关于PWM播放音乐原理,即将PWM模拟变成一个DAC进行语音信号的输出。大概原理就是:通过改变PWM的占空比,改变PWM每个周期内的电压。通过一连串改变PWM周期电压,可以模拟实现DAC的效果。关于这方
    发表于 05-11 16:11

    CH32V103基础教程93-PWM播放音乐 (1个TIM)

    本章教程主要在第八章PWM输出的基础上进行,主要使用CH32V103的PWM播放音乐,可直接接喇叭使用,但声音较小,可通过功放接喇叭来提高音量。该例程噪音较多,仅供大家参考。 1、TIM简介及相关
    发表于 05-11 16:10

    【正点原子STM32战舰V4开发板免费试用】利用开发板上的蜂鸣器播放音乐

    了,按照每个歌曲的曲调不一样,函数里就可以播放了。 为了营造一点氛围,打造一点动感,还要来一点闪灯的效果。这相对就简单了,用一个定时器中断就能实现了。 文章的最后就是声光并存的音乐播放
    发表于 05-01 19:59

    imx6ul evk播放音乐有噪音怎么解决?

    我使用 imx6ul evk 和 yocto, 当我像这样播放音乐时 # gst-play xxx.mp3 而且听起来有噪音。 怎么解决??
    发表于 04-23 07:25