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


         今天主要和大家聊一聊,如何使用鸿蒙系统中的脉冲宽度调制,利用微处理器的数字输出来对模拟电路进行控制的一种方法​。

    第一​:pwm的基本简介

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

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

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

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

    单位: % (0%-100%)

    表示方式:20%

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

    脉宽时间: 高电平时间

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

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

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

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

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

    我们换更详细点的图

    上图中,周期为T

    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

    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度;

    ​第三:鸿蒙中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);

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

    ​第四:效果实现

    VID_20220705_210103

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

  • 相关阅读:
    MVC、MVVM、MVP的区别
    Metabase学习教程:系统管理-4
    十八、redis6从入门到高级
    QT使用MSVC编译时报错C2001: 常量中有换行符
    秋招面试问题总结
    【稳定性】揭秘团队快速排查问题的三字经,你学会了吗?
    香港空间在http重定向https出现400状态码
    数学建模——确定性时间序列分析方法
    25.1 MySQL SELECT语句
    LeetCode-160. Intersection of Two Linked Lists [C++][Java]
  • 原文地址:https://blog.csdn.net/weixin_41114301/article/details/125628262