我正在完成一个OpenHarmony的嵌入式设计项目,功能要求
1.能够使用交通灯板上的蜂蜜器播放选定的曲谱,
PWM原理、音符--频率对应关系、音符频率选择、曲谱电子化(转程序数组)、程序逻辑、BUILD.gn出国文件修改、代码编译、固件烧录、串口调试、运行测试等。
2.能够使用交通灯板上的按键切换播放的曲谱,
至少有两首或以上曲谱可以切换(曲谱越多得分越高)、播放出的曲谱音律基本准确。
3.使用vscode和虚拟机Linux系统,硬件设备润和鸿蒙系统的满天星智能家居开发套件。
现在有三段原有代码,
applications\sample\wifi-iot\app\pwm_demo\pwm_music.c内容为:
#include <stdio.h> // 标准输入输出
#include "ohos_init.h" // 用于初始化服务(services)和功能(features)
#include "cmsis_os2.h" // CMSIS-RTOS API V2
#include "iot_gpio.h" // OpenHarmony API:IoT硬件设备操作接口-GPIO
#include "hi_io.h" // 海思 Pegasus SDK:IoT硬件设备操作接口-IO
#include "hi_pwm.h" // 海思 Pegasus SDK:IoT硬件设备操作接口-PWM
// 分频倍数数组
// 40MHz 对应的分频倍数:
static const uint16_t g_tuneFreqs[] = {
0, // 不使用
38223, // 1046.5Hz C6(do)
34052, // 1174.7Hz D6(re)
30338, // 1318.5Hz E6(mi)
28635, // 1396.9Hz F6(fa)
25511, // 1568Hz G6(so)
22728, // 1760Hz A6(la)
20249, // 1975.5Hz B6(si)
51020 // 784Hz G5(so)低八度
};
// 曲谱音符数组:《两只老虎》。
// 简谱:http://www.jianpu.cn/pu/33/33945.htm
static const uint8_t g_scoreNotes[] = {
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_scoreNotes[] = {
// 3, 5, 5, 6, 5, 3, 1, 1, 2, 3, 3, 2, 1, 2,
// 3, 5, 5, 6, 5, 3, 1, 1, 2, 3, 3, 2, 2, 1,
// 4, 4, 4, 6, 5, 5, 3, 2,
// 3, 5, 5, 6, 5, 3, 1, 1, 2, 3, 3, 2, 2, 1
// };
// 曲谱时值数组:《两只老虎》。
// 根据简谱记谱方法转写。
// 4/4拍中下面划一条线是半拍,划两条线是四分之一拍,点是顺延半拍
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 const uint8_t g_scoreDurations[] = {
// 2, 2, 3, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 8,
// 2, 2, 3, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 8,
// 4, 4, 2, 6, 4, 3, 1, 8,
// 2, 2, 3, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 8
// };
// 主线程函数
static void BeeperMusicTask(void *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];
// 获取音符时间
// 适当拉长时间,四分之一拍用时125ms,每小节2s
uint32_t tuneInterval = g_scoreDurations[i] * (125*1000);
// 日志输出
printf("%d %d %d %d\r\n", tune, (40*1000*1000) / freqDivisor, freqDivisor, tuneInterval);
// 开始输出PWM信号,占空比50%
hi_pwm_start(HI_PWM_PORT_PWM0, freqDivisor/2, freqDivisor);
// 等待音符时间,参数的单位是微秒(千分之一毫秒)
usleep(tuneInterval);
// 停止输出PWM信号
hi_pwm_stop(HI_PWM_PORT_PWM0);
// 停止一个音符后,等待20ms,让两次发音有个间隔,听起来更自然一些
usleep(20*1000);
}
}
// 入口函数
static void StartBeepMusicTask(void)
{
// 定义线程属性
osThreadAttr_t attr;
attr.name = "BeeperMusicTask";
attr.stack_size = 4096;
attr.priority = osPriorityNormal;
// 蜂鸣器引脚 设置为 PWM功能
IoTGpioInit(HI_IO_NAME_GPIO_9);
hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_PWM0_OUT);
IoTGpioSetDir(HI_IO_NAME_GPIO_9, IOT_GPIO_DIR_OUT);
IoTPwmInit(HI_PWM_PORT_PWM0);
// 创建线程
if (osThreadNew(BeeperMusicTask, NULL, &attr) == NULL) {
printf("[BeeperMusicExample] Falied to create BeeperMusicTask!\n");
}
}
// 运行入口函数
SYS_RUN(StartBeepMusicTask);
applications\sample\wifi-iot\app\pwm_demo\BUILD.gn内容为:
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
"//applications/sample/wifi-iot/app/music_player:music_player_app",
]
}
在applications\sample\wifi-iot\app\ BUILD.gn内容为:
lite_component("app") {
# features字段指定业务模块,使目标模块参与编译。
features = [
# 在features字段中增加索引,包括路径和目标。
# 路径"startup":"applications\sample\wifi-iot\app\startup"目录
# 目标"hello_world":"applications\sample\wifi-iot\app\startup\BUILD.gn"中的静态库名称
"startup:hello_world",
# 如果"applications\sample\wifi-iot\app\startup\BUILD.gn"中的静态库名称与所在目录"startup"同名,
# 即目标与路径同名,可以简写为:
# "startup",
]
}
现在请根据原有代码进行修改个添加,使其能够实现项目所需功能,并按照在何处(文件夹位置)添加一个文件(文件名),输入代码内容如下(代码)的格式整理一份含代码的操作步骤。