利用鸿蒙系统硬件实现音乐播放功能之优秀

简介: 利用鸿蒙系统硬件实现音乐播放功能之优秀 今天主要和大家聊一聊,如何使用鸿蒙系统中的脉冲宽度调制,利用微处理器的数字输出来对模拟电路进行控制的一种方法​。

第一:pwm的基本简介


首先来了解一下,pwm的频率是什么?


定义:是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期),也就是说一秒钟PWM有多少个周期。单位:HZ。


pwm的周期:T=1/f      可以认为50Hz=20ms 一个周期。


pwm的占空比:是一个脉冲周期内,高电平的时间与整个周期时间的比例。


单位: % (0%-100%)

表示方式:20%

d8123aa38fa5a7c78136aa74a1e27d5b.png周期: 一个脉冲信号的时间        1s内测周期次数等于频率


脉宽时间: 高电平时间


上图中 脉宽时间占总周期时间的比例,就是占空比


比方说周期的时间是10ms,脉宽时间是8ms 那么低电平时间就是2ms 总的占空比 8/(8+2)= 80%


这就是占空比为80%的脉冲信号


而我们知道PWM就是脉冲宽度调制 通过调节占空比,就可以调节脉冲宽度(脉宽时间) 而频率 就是单位时间内脉冲信号的次数,频率越大


以20Hz 占空比为80% 举例 就是1秒钟之内输出了20次脉冲信号 每次的高电平时间为40ms


我们换更详细点的图

7eb671fe6f09730718948271989d09fb.png

T1为高电平时间


T2 为低电平时间


假设周期T为 1s 那么频率就是 1Hz 那么高电平时间0.5s ,低电平时间0.5s 总的占空比就是 0.5 /1 =50%


PWM原理

以单片机为例,我们知道,单片机的IO口输出的是数字信号,IO口只能输出高电平和低电平。


假设高电平为5V 低电平则为0V 那么我们要输出不同的模拟电压,就要用到PWM,通过改变IO口输出的方波的占空比从而获得使用数字信号模拟成的模拟电压信号


我们知道,电压是以一种连接1或断开0的重复脉冲序列被夹到模拟负载上去的(例如LED灯,直流电机等),连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值(即0~5V之间任意大小)的模拟电压


比方说 占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V

f47f22bd38b4b6ac765ebdf9f6437060.png

pwm的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降


也就是,在一定的频率下,通过不同的占空比 即可得到不同的输出模拟电压。


pwm就是通过这种原理实现D/A转换的。


PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压。


第二:PWM对电机的控制方法

PWM对舵机的控制

舵机的控制就是通过一个固定的频率,给其不同的占空比的,来控制舵机不同的转角


舵机的频率一般为频率为50HZ,也就是一个20ms左右的时基脉冲,而脉冲的高电平部分一般为0.5ms-2.5ms范围。来控制舵机不同的转角




500-2500us的PWM高电平部分对应控制180度舵机的0-180度


以180度角度伺服为例,那么对应的控制关系是这样的:


0.5ms--------------0度;


1.0ms------------45度;


1.5ms------------90度;


2.0ms-----------135度;


2.5ms-----------180度;


46a0f9da884e33882ae3bd842c241e5d.gif

114d43b05442b8a27a3eff45fa238d2e.png

第三:鸿蒙中PWM的实现方式


   利用板子上的GPIO口模拟输出PWM来控制蜂鸣器发出声音。具体代码实现如下所示。

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_watchdog.h"
#include "wifiiot_pwm.h"
#include "hi_pwm.h"
static volatile int g_buttonPressed = 0;
static const uint16_t g_tuneFreqs[] = {
    0, // 40M Hz 对应的分频系数:
    38223, // 1046.5
    34052, // 1174.7
    30338, // 1318.5
    28635, // 1396.9
    25511, // 1568
    22728, // 1760
    20249, // 1975.5
    51021 // 5_ 783.99 // 第一个八度的 5
};
// 曲谱音符
static const uint8_t g_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 应该是低八度的,链接图片中的曲谱不对,声音到最后听起来不太对劲
};
// 曲谱时值
static const uint8_t g_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,
};
static void *BeeperMusicTask(const char *arg)
{
    (void)arg;
    printf("BeeperMusicTask start!\r\n");
    hi_pwm_set_clock(PWM_CLK_XTAL); // 设置时钟源为晶体时钟(40MHz,默认时钟源160MHz)
    for (size_t i = 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;
}
static void StartBeepMusicTask(void)
{
    osThreadAttr_t attr;
    GpioInit();
    // 蜂鸣器引脚 设置为 PWM功能
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT);
    PwmInit(WIFI_IOT_PWM_PORT_PWM0);
    WatchDogDisable();
    attr.name = "BeeperMusicTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = osPriorityNormal;
    if (osThreadNew((osThreadFunc_t)BeeperMusicTask, NULL, &attr) == NULL) {
        printf("[LedExample] Falied to create BeeperMusicTask!\n");
    }
}
SYS_RUN(StartBeepMusicTask);

   行百里者半九十,接下来的配置和编译过程,如下。

第四:效果实现

微信图片_20221208130004.png

总结:鸿蒙系统的使用需要动手实践,在实践的过程中,发现问题并解决问题。

目录
相关文章
|
11天前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
本篇将带你实现一个虚拟音乐控制台。用户可以通过界面控制音乐的播放、暂停、切换歌曲,并查看当前播放的歌曲信息。页面还支持调整音量和动态显示播放进度,是音乐播放器界面开发的基础功能示例。
172 80
|
2天前
「Mac畅玩鸿蒙与硬件51」UI互动应用篇28 - 模拟记账应用
本篇教程将介绍如何创建一个模拟记账应用,通过账单输入、动态列表展示和实时统计功能,学习接口定义和组件间的数据交互。
102 68
|
5天前
|
流计算 UED
「Mac畅玩鸿蒙与硬件48」UI互动应用篇25 - 简易购物车功能实现
本篇教程将带你实现一个简易购物车功能。通过使用接口定义商品结构,我们将创建一个动态购物车,支持商品的添加、移除以及实时总价计算。
94 69
|
10天前
|
编解码 API 数据安全/隐私保护
一个鸿蒙开发者的探索:实现相册访问功能
最近我决定开发一个鸿蒙App,旨在提供更好的照片管理体验。通过使用PhotoAccessHelper API,我实现了访问、显示和管理设备相册中的照片。过程中遇到了权限不足的问题,通过在config.json中添加权限声明并编写权限检查代码得以解决。此外,我还实现了分页加载和展示照片详细信息等功能,提升了用户体验。这次开发不仅让我掌握了API的使用,也深刻体会到鸿蒙系统对用户隐私和数据安全的重视。 总结这次开发,我不仅学到了技术知识,还明白了开发者保护用户数据安全的责任。未来将继续探索更多功能,欢迎关注和收藏!
105 70
|
5天前
|
前端开发
「Mac畅玩鸿蒙与硬件49」UI互动应用篇26 - 数字填色游戏
本篇教程将带你实现一个数字填色小游戏,通过简单的交互逻辑,学习如何使用鸿蒙开发组件创建趣味性强的应用。
43 20
|
4天前
|
前端开发 UED
「Mac畅玩鸿蒙与硬件50」UI互动应用篇27 - 水果掉落小游戏
本篇教程将带你实现一个水果掉落小游戏,掌握基本的动态交互逻辑和鸿蒙组件的使用,进一步了解事件处理与状态管理。
29 14
|
7天前
|
Android开发 iOS开发
鸿蒙开发:适配系统深浅色模式
无论是Android还是iOS,在系统设置中,都有着深色和浅色两种外观模式,同样,鸿蒙系统中也存在这样的外观切换,如何让自己的应用,跟随着系统的模式进行动态切换呢?目前系统给我们提供了两种方式可以实现,一种是资源形式,一种是动态的代码形式。
58 15
鸿蒙开发:适配系统深浅色模式
|
1天前
|
UED
「Mac畅玩鸿蒙与硬件52」UI互动应用篇29 - 模拟火车票查询系统
本篇教程将实现一个模拟火车票查询系统,通过输入条件筛选车次信息,并展示动态筛选结果,学习事件处理、状态管理和界面展示的综合开发技巧。
32 13
|
5天前
|
存储 API
鸿蒙元服务项目实战:终结篇之备忘录搜索功能实现
开发元服务,有很多的限制性因素,比如包的大小限制,相关API限制,所以,我们在实际开发的时候,具体Api能否使用,还需要去官网查看一下,目前,针对当前这个小项目,总结了几个小问题,大家在开发的过程中可以作为参考。
鸿蒙元服务项目实战:终结篇之备忘录搜索功能实现
|
9天前
|
安全 API 数据安全/隐私保护
自学记录HarmonyOS Next DRM API 13:构建安全的数字内容保护系统
在完成HarmonyOS Camera API开发后,我深入研究了数字版权管理(DRM)技术。最新DRM API 13提供了强大的工具,用于保护数字内容的安全传输和使用。通过学习该API的核心功能,如获取许可证、解密内容和管理权限,我实现了一个简单的数字视频保护系统。该系统包括初始化DRM模块、获取许可证、解密视频并播放。此外,我还配置了开发环境并实现了界面布局。未来,随着数字版权保护需求的增加,DRM技术将更加重要。如果你对这一领域感兴趣,欢迎一起探索和进步。
65 18

热门文章

最新文章