我正在完成一个OpenHarmony的嵌入式设计项目,功能要求
1.能够使用交通灯板上的蜂蜜器播放选定的曲谱,
PWM原理、音符--频率对应关系、音符频率选择、曲谱电子化(转程序数组)、程序逻辑、BUILD.gn出国文件修改、代码编译、固件烧录、串口调试、运行测试等都能在报告中清晰说明、项目答辩阐述清楚、答辩提问回答基本正确。
2. 能够使用交通灯板上的按键切换播放的曲谱,
至少有两首或以上曲谱可以切换(曲谱越多得分越高)、播放出的曲谱音律基本准确。
3. 能够应用OLED显示屏显示当前播放曲谱的相关信息,
能够显示当前播放曲谱的名气、歌词等相关信息。
要求使用vscode中的海思环境和虚拟机Linux系统,硬件设备润和鸿蒙系统的满天星智能家居开发套件。
现在我已经完成了播放音乐,OLED显示歌名,播放音乐时交通板红绿灯闪烁的功能。
实现的代码如下:
\applications\sample\wifi-iot\app\pwm_demo\display.c:
#include <stdio.h> // 标准输入输出
#include <unistd.h> // POSIX标准接口
#include "ohos_init.h" // 用于初始化服务(services)和功能(features)
#include "cmsis_os2.h" // CMSIS-RTOS API V2
#include "iot_gpio.h" // OpenHarmony HAL:IoT硬件设备操作接口-GPIO
#include "hi_io.h" // 海思 Pegasus SDK:IoT硬件设备操作接口-IO
#include "hi_adc.h" // 海思 Pegasus SDK:IoT硬件设备操作接口-ADC
#include "oled_ssd1306.h" // OLED显示屏简化版驱动接口文件
// 定义一个宏,用于标识ADC2通道
#define ANALOG_KEY_CHAN_NAME HI_ADC_CHANNEL_2
// 使用PCtoLCD建立字库
// 字符集:铃铛
// 字符轮廓:16 X 16,新宋体
// 每个字32个字节(16*16/8=32)
// 根据取模方式,每个字的前16字节是汉字的上半部分,后16字节是汉字的下半部分
// 使用二维数组
uint8_t fonts1[][32] = {
{0x40,0x30,0xEF,0x24,0x24,0x40,0x20,0x10,0x0C,0x23,0xCC,0x10,0x20,0x40,0x40,0x00,0x01,0x01,0x7F,0x21,0x11,0x00,0x01,0x09,0x11,0x21,0xD1,0x0D,0x03,0x00,0x00,0x00},/*"铃",0*/
{0x20,0x10,0x2C,0xE7,0x24,0x24,0x40,0x42,0x5C,0x40,0x7F,0x40,0x50,0xCE,0x00,0x00,0x01,0x01,0x01,0x7F,0x21,0x11,0x40,0x44,0x44,0x44,0x44,0x44,0x44,0xFF,0x00,0x00},/*"铛",1*/
};
/// @brief 显示一个汉字(使用PCtoLCD建立的字库)
/// @param x x坐标,1像素为单位
/// @param y y坐标,8像素为单位。即页面起始地址
/// @param idx 汉字在字库中的索引
void OledShowChinese1(uint8_t x, uint8_t y, uint8_t idx)
{
// 控制循环
uint8_t t;
// 显示汉字的上半部分
OledSetPosition(x, y);
for (t = 0; t < 16; t++)
{
WriteData(fonts1[idx][t]);
}
// 显示汉字的下半部分
OledSetPosition(x, y + 1);
for (t = 16; t < 32; t++)
{
WriteData(fonts1[idx][t]);
}
}
// 主线程函数
static void OledTask(void *arg)
{
(void)arg;
// 初始化SSD1306显示屏驱动芯片
OledInit();
// 全屏填充黑色
OledFillScreen(0x00);
// 显示"铃铛"
// 起始x坐标 = (屏幕宽度128 - (汉字间距18*(字数-1) + 每个汉字的宽度16 - 第一个汉字的坐标0))/2 = 29
OledShowChinese1(29 + 0, 3, 0); //铃
OledShowChinese1(29 + 18, 3, 1); //铛
// 居中显示"OpenHarmony"
// 起始x坐标 = (屏幕宽度128 - 字符间距8 * 字母个数11)/2 = 20
OledShowString(20, 5, "OpenHarmony", FONT8x16);
// 左上角显示倒计时
char digits[] = "8 7 6 5 4 3 2 1";
for (int i = 0; i < 15; i++)
{
OledShowChar(0, 0, digits[i], FONT6x8);
sleep(1);
}
// 中英文混杂显示
OledFillScreen(0x00); // 全屏填充黑色
// 工作循环
while (1)
{
// 要显示的字符串
static char text[128] = {0};
// 用于存放ADC2通道的值
unsigned short data = 0;
// 读取ADC2通道的值
hi_adc_read(ANALOG_KEY_CHAN_NAME, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0);
OledShowString(36, 0, text, FONT8x16);
// 等待30ms
usleep(30 * 1000);
}
}
// 入口函数
static void OledDemo(void)
{
// 定义线程属性
osThreadAttr_t attr;
attr.name = "OledTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 4096;
attr.priority = osPriorityNormal;
// 创建线程
if (osThreadNew(OledTask, NULL, &attr) == NULL)
{
printf("[OledDemo] Falied to create OledTask!\n");
}
}
// 运行入口函数
APP_FEATURE_INIT(OledDemo);
\applications\sample\wifi-iot\app\pwm_demo\music2.c:
#include <stdio.h> // 标准输入输出头文件
#include <string.h> // 字符串处理头文件
#include "ohos_init.h" // 用于初始化服务(service)和功能(feature)的头文件
#include "cmsis_os2.h" // CMSIS-RTOS2头文件
#include "iot_gpio.h" // OpenHarmony API:IoT硬件设备操作接口中的GPIO接口头文件
#include "hi_io.h" // 海思 Pegasus SDK:IoT硬件设备操作接口中的IO接口头文件
#include "hi_pwm.h" // 海思 Pegasus SDK:IoT硬件设备操作接口中的PWM接口头文件
#include "ssd1306.h" // OLED显示屏驱动头文件
// 分频倍数数组
// 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)低八度
};
// 曲谱音符数组:《铃儿响叮当》
static const uint8_t g_scoreNotes[] = {
// 第一句:
3, 3, 3, 3, 3, 3, 3, 5, 1, 2, 3,
// 第二句:
4, 4, 4, 4, 3, 3, 3, 2, 2, 1, 2, 5,
// 第三句(重复第一句):
3, 3, 3, 3, 3, 3, 3, 5, 1, 2, 3,
// 第四句:
4, 4, 4, 4, 3, 3, 5, 5, 4, 2, 1
};
// 曲谱时值数组:(单位:1/4拍,4=1拍,8=2拍)
static const uint8_t g_scoreDurations[] = {
// 第一句:三连音用短时值,结尾音稍长
2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 4,
// 第二句:
2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 2, 4,
// 第三句:
2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 4,
// 第四句:
2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4
};
// 主线程函数
static void BeeperMusicTask(void *arg)
{
(void)arg;
printf("BeeperMusicTask start!\r\n"); // 日志输出
// 初始化OLED显示屏
ssd1306_Init();
ssd1306_Fill(Black); // 清屏
ssd1306_SetCursor(20, 2); // 设置光标位置
ssd1306_PrintString("送别", Font_11x18, White); // 显示歌曲名称
ssd1306_UpdateScreen(); // 更新显示
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);
if (tune != 0) { // 0表示休息
// 开始输出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);
}
// 播放完成后显示结束信息
ssd1306_Fill(Black); // 清屏
ssd1306_SetCursor(10, 2);
ssd1306_UpdateScreen();
}
// 入口函数
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\oled_ssd1306.h:
// OLED显示屏简化版驱动接口文件
// 定义条件编译宏,防止头文件的重复包含和编译
#ifndef OLED_SSD1306_H
#define OLED_SSD1306_H
#include <stdint.h> // 定义了几种扩展的整数类型和宏
// 声明接口函数
uint32_t OledInit(void);
void OledSetPosition(uint8_t x, uint8_t y);
void OledFillScreen(uint8_t fillData);
uint32_t WriteData(uint8_t data);
// 定义字库类型
enum Font {
FONT6x8 = 1,
FONT8x16
};
typedef enum Font Font;
// 声明接口函数
void OledShowChar(uint8_t x, uint8_t y, uint8_t ch, Font font);
void OledShowString(uint8_t x, uint8_t y, const char* str, Font font);
// 条件编译结束
#endif // OLED_SSD1306_H
\applications\sample\wifi-iot\app\pwm_demo\oled_ssd1306.c:
// OLED显示屏简化版驱动源文件
#include <stdio.h> // 标准输入输出
#include <stddef.h> // 标准类型定义
#include "iot_gpio.h" // OpenHarmony HAL:IoT硬件设备操作接口-GPIO
#include "iot_i2c.h" // OpenHarmony HAL:IoT硬件设备操作接口-I2C
#include "iot_errno.h" // OpenHarmony HAL:IoT硬件设备操作接口-错误代码定义
#include "hi_io.h" // 海思 Pegasus SDK:IoT硬件设备操作接口-IO
// 字库头文件
#include "oled_fonts.h"
// OLED显示屏简化版驱动接口文件
#include "oled_ssd1306.h"
// 定义一个宏,用于计算数组的长度
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
// 定义一个宏,用于标识I2C0
#define OLED_I2C_IDX 0
// 定义一个宏,用于标识I2C0的波特率(传输速率)
#define OLED_I2C_BAUDRATE (400 * 1000) // 400KHz
// 定义一个宏,用于标识OLED的宽度
#define OLED_WIDTH (128)
// 定义一个宏,用于标识SSD1306显示屏驱动芯片的设备地址
#define OLED_I2C_ADDR 0x78
// 定义一个宏,用于标识写命令操作
#define OLED_I2C_CMD 0x00 // 0000 0000 写命令
// 定义一个宏,用于标识写数据操作
#define OLED_I2C_DATA 0x40 // 0100 0000(0x40) 写数据
// 定义一个宏,用于标识100ms的延时
#define DELAY_100_MS (100 * 1000)
// 定义一个结构体,表示要发送或接收的数据
typedef struct
{
// 要发送的数据的指针
unsigned char *sendBuf;
// 要发送的数据长度
unsigned int sendLen;
// 要接收的数据的指针
unsigned char *receiveBuf;
// 要接收的数据长度
unsigned int receiveLen;
} IotI2cData;
/// @brief 向OLED写一个字节
/// @param regAddr 写入命令还是数据 OLED_I2C_CMD / OLED_I2C_DATA
/// @param byte 写入的内容
/// @retval 成功返回IOT_SUCCESS,失败返回IOT_FAILURE
static uint32_t I2cWiteByte(uint8_t regAddr, uint8_t byte)
{
// 定义字节流
uint8_t buffer[] = {regAddr, byte};
IotI2cData i2cData = {0};
i2cData.sendBuf = buffer;
i2cData.sendLen = sizeof(buffer) / sizeof(buffer[0]);
// 发送字节流
return IoTI2cWrite(OLED_I2C_IDX, OLED_I2C_ADDR, i2cData.sendBuf, i2cData.sendLen);
}
/// @brief 向OLED写一个命令字节
/// @param cmd 写入的命令字节
/// @return 成功返回IOT_SUCCESS,失败返回IOT_FAILURE
static uint32_t WriteCmd(uint8_t cmd)
{
return I2cWiteByte(OLED_I2C_CMD, cmd);
}
/// @brief 向OLED写一个数据字节
/// @param cmd 写入的数据字节
/// @return 成功返回IOT_SUCCESS,失败返回IOT_FAILURE
uint32_t WriteData(uint8_t data)
{
return I2cWiteByte(OLED_I2C_DATA, data);
}
/// @brief 初始化SSD1306显示屏驱动芯片
uint32_t OledInit(void)
{
// 构造初始化代码
static const uint8_t initCmds[] = {
0xAE, // 显示关闭
0x00, // 页寻址模式时,设置列地址的低4位为0000
0x10, // 页寻址模式时,设置列地址的高4位为0000
0x40, // 设置起始行地址为第0行
0xB0, // 页寻址模式时,设置页面起始地址为PAGE0
0x81, // 设置对比度
0xFF, // 对比度数值
0xA1, // set segment remap
0xA6, // 设置正常显示。0对应像素熄灭,1对应像素亮起
0xA8, // --set multiplex ratio(1 to 64)
0x3F, // --1/32 duty
0xC8, // Com scan direction
0xD3, // -set display offset
0x00, //
0xD5, // set osc division
0x80, //
0xD8, // set area color mode off
0x05, //
0xD9, // Set Pre-Charge Period
0xF1, //
0xDA, // set com pin configuartion
0x12, //
0xDB, // set Vcomh
0x30, //
0x8D, // set charge pump enable
0x14, //
0xAF, // 显示开启
};
// 初始化GPIO-13
IoTGpioInit(HI_IO_NAME_GPIO_13);
// 设置GPIO-13引脚功能为I2C0_SDA
hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
// 初始化GPIO-14
IoTGpioInit(HI_IO_NAME_GPIO_14);
// 设置GPIO-14引脚功能为I2C0_SCL
hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
// 用指定的波特速率初始化I2C0
IoTI2cInit(OLED_I2C_IDX, OLED_I2C_BAUDRATE);
// 发送初始化代码,初始化SSD1306显示屏驱动芯片
for (size_t i = 0; i < ARRAY_SIZE(initCmds); i++)
{
// 发送一个命令字节
uint32_t status = WriteCmd(initCmds[i]);
if (status != IOT_SUCCESS)
{
return status;
}
}
// OLED初始化完成,返回成功
return IOT_SUCCESS;
}
/// @brief 设置显示位置
/// @param x x坐标,1像素为单位
/// @param y y坐标,8像素为单位。即页面起始地址
/// @return 无
void OledSetPosition(uint8_t x, uint8_t y)
{
//设置页面起始地址
WriteCmd(0xb0 + y);
// 列:0~127
// 第0列:0x00列,二进制00000000。低地址0000,即0x00。高地址0000(需要|0x10),0000|0x10=0x10。
// 第127列:0x7f列,二进制01111111。低地址1111,即0x0F。高地址0111(需要|0x10),0111|0x10=0x17。
// 设置显示位置:列地址的低4位
// 直接取出列地址低4位作为命令代码的低4位,命令代码的高4位为0000
WriteCmd(x & 0x0f);
// 设置显示位置:列地址的高4位
// 取出列地址高4位作为命令代码的低4位,命令代码的高4位必须为0001
// 实际编程时,列地址的高4位和0x10(二进制00010000)进行按位或即得到命令代码
WriteCmd(((x & 0xf0) >> 4) | 0x10);
}
/// @brief 全屏填充
/// @param fillData 填充的数据,1字节
/// @return 无
void OledFillScreen(uint8_t fillData)
{
// 相关变量,用于遍历page和列
uint8_t m = 0;
uint8_t n = 0;
// 写入所有页的数据
for (m = 0; m < 8; m++)
{
//设置页地址:0~7
WriteCmd(0xb0 + m);
// 设置显示位置为第0列
WriteCmd(0x00); //设置显示位置:列低地址(0000)
WriteCmd(0x10); //设置显示位置:列高地址(0000)
// 写入128列数据
// 在一个页中,数据按列写入,一次一列,对应发送过来的1字节数据
for (n = 0; n < 128; n++)
{
// 写入一个字节数据
WriteData(fillData);
}
}
}
/// @brief 显示一个字符
/// @param x: x坐标,1像素为单位
/// @param y: y坐标,8像素为单位
/// @param ch: 要显示的字符
/// @param font: 字库
void OledShowChar(uint8_t x, uint8_t y, uint8_t ch, Font font)
{
// 数组下标
uint8_t c = 0;
// 循环控制
uint8_t i = 0;
// 得到数组下标
// 空格的ASCII码32,在字库中的下标是0。字库中的字符-空格即相应的数组下标
c = ch - ' ';
// 显示字符
if (font == FONT8x16) // 8*16的点阵,一个page放不下
{
// 显示字符的上半部分
// 设置显示位置
OledSetPosition(x, y);
// 逐个字节写入(16个数组元素的前8个)
for (i = 0; i < 8; i++)
{
WriteData(F8X16[c * 16 + i]);
}
// 显示字符的下半部分
// 设置显示位置为下一个PAGE
OledSetPosition(x, y + 1);
// 逐个字节写入(16个数组元素的后8个)
for (i = 0; i < 8; i++)
{
WriteData(F8X16[c * 16 + 8 + i]);
}
}
else // 6*8的点阵,在一个page中
{
// 设置显示位置
OledSetPosition(x, y);
// 逐个字节写入(数组第二维的6个数组元素)
for (i = 0; i < 6; i++)
{
WriteData(F6x8[c][i]);
}
}
}
/// @brief 显示一个字符串
/// @param x: x坐标,1像素为单位
/// @param y: y坐标,8像素为单位
/// @param str: 要显示的字符串
/// @param font: 字库
void OledShowString(uint8_t x, uint8_t y, const char *str, Font font)
{
// 字符数组(字符串)下标
uint8_t j = 0;
// 检查字符串是否为空
if (str == NULL)
{
printf("param is NULL,Please check!!!\r\n");
return;
}
// 遍历字符串,显示每个字符
while (str[j])
{
// 显示一个字符
OledShowChar(x, y, str[j], font);
// 设置字符间距
x += 8;
// 如果下一个要显示的字符超出了OLED显示的范围,则换行
if (x > 120)
{
x = 0;
y += 2;
}
// 下一个字符
j++;
}
}
\applications\sample\wifi-iot\app\pwm_demo\traffic_light.c:
// Pegasus交通灯板三色灯与主控芯片引脚的对应关系
// GPIO_10 连接红色LED灯,输出高电平点亮
// GPIO_11 连接绿色LED灯,输出高电平点亮
// GPIO_12 连接黄色LED灯,输出高电平点亮
#include <stdio.h> // 标准输入输出头文件
#include <unistd.h> // POSIX头文件
#include "ohos_init.h" // 用于初始化服务(service)和功能(feature)的头文件
#include "cmsis_os2.h" // CMSIS-RTOS2头文件
#include "iot_gpio.h" // OpenHarmony HAL:IoT硬件设备操作接口中的GPIO接口头文件
#include "hi_io.h" // 海思 Pegasus SDK:IoT硬件设备操作接口中的IO接口头文件
#include "hi_pwm.h" // 海思 Pegasus SDK:IoT硬件设备操作接口中的PWM接口头文件
// 定义GPIO引脚,尽量避免直接用数值
#define BUTTON_GPIO 8 // 按钮
#define RED_GPIO 10 // 红色LED灯
#define GREEN_GPIO 11 // 绿色LED灯
#define YELLOW_GPIO 12 // 黄色LED灯
// 定义三色LED灯的状态
static int g_ledStates[3] = {0, 0, 0};
// 当前点亮的灯
static int g_currentBright = 0;
// 主线程函数
static void *TrafficLightTask(const char *arg)
{
(void)arg;
// 输出提示信息
printf("TrafficLightTask start!\r\n");
// 将三色灯的GPIO引脚放入数组,以便使用循环进行控制
unsigned int pins[] = {RED_GPIO, GREEN_GPIO, YELLOW_GPIO};
// 开始输出PWM信号
hi_pwm_start(HI_PWM_PORT_PWM0, 20 * 1000, 40 * 1000);
// 停止输出PWM信号
hi_pwm_stop(HI_PWM_PORT_PWM0);
// 让三色灯循环亮灭16轮
for (int i = 0; i < 16; i++)
{
// 每一轮按顺序亮灭三色灯
for (unsigned int j = 0; j < 3; j++)
{
// 点亮
IoTGpioSetOutputVal(pins[j], IOT_GPIO_VALUE1);
// 等待200ms
usleep(200 * 1000);
// 熄灭
IoTGpioSetOutputVal(pins[j], IOT_GPIO_VALUE0);
// 等待100ms
usleep(100 * 1000);
}
}
// 工作循环
while (1)
{
// 设置每个灯的点亮或熄灭状态
for (unsigned int j = 0; j < 3; j++)
{
IoTGpioSetOutputVal(pins[j], g_ledStates[j]);
}
// 等待100ms
usleep(100 * 1000);
}
return NULL;
}
// 按钮(GPIO-08)的中断处理函数
static void OnButtonPressed(char *arg)
{
(void)arg;
// 设置三色LED灯的状态
for (int i = 0; i < 3; i++)
{
// 根据g_currentBright设置当前点亮的灯
if (i == g_currentBright)
{
g_ledStates[i] = 1;
}
// 其他灯熄灭
else
{
g_ledStates[i] = 0;
}
}
// 实现按键切灯
g_currentBright++;
// 循环点亮三色LED灯
if (g_currentBright == 3)
g_currentBright = 0;
}
// 入口函数
static void StartTrafficLightTask(void)
{
// 定义线程属性
osThreadAttr_t attr;
attr.name = "TrafficLightTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024;
attr.priority = osPriorityNormal;
// 初始化GPIO模块
IoTGpioInit(RED_GPIO); // 红色LED灯
IoTGpioInit(GREEN_GPIO); // 绿色LED灯
IoTGpioInit(YELLOW_GPIO); // 黄色LED灯
IoTGpioInit(BUTTON_GPIO); // 按钮
// 设置GPIO-10的功能为GPIO
hi_io_set_func(RED_GPIO, HI_IO_FUNC_GPIO_10_GPIO);
// 设置GPIO-10的模式为输出模式(引脚方向为输出)
IoTGpioSetDir(RED_GPIO, IOT_GPIO_DIR_OUT);
// 设置GPIO-11的功能为GPIO
hi_io_set_func(GREEN_GPIO, HI_IO_FUNC_GPIO_11_GPIO);
// 设置GPIO-11的模式为输出模式(引脚方向为输出)
IoTGpioSetDir(GREEN_GPIO, IOT_GPIO_DIR_OUT);
// 设置GPIO-12的功能为GPIO
hi_io_set_func(YELLOW_GPIO, HI_IO_FUNC_GPIO_12_GPIO);
// 设置GPIO-12的模式为输出模式(引脚方向为输出)
IoTGpioSetDir(YELLOW_GPIO, IOT_GPIO_DIR_OUT);
// 设置GPIO-08的功能为GPIO
hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_8_GPIO);
// 设置GPIO-08的模式为输入模式(引脚方向为输入)
IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);
// 设置GPIO-08的模式为上拉模式(引脚上拉)
hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);
// 注册GPIO-08中断处理函数
IoTGpioRegisterIsrFunc(BUTTON_GPIO, //GPIO-08引脚
IOT_INT_TYPE_EDGE, //边沿触发
IOT_GPIO_EDGE_FALL_LEVEL_LOW, //下降沿触发
OnButtonPressed, //中断处理函数
NULL); //中断处理函数的参数
// 设置GPIO-09的功能为PWM0输出
hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_PWM0_OUT);
// 设置GPIO-09的模式为输出模式(引脚方向为输出)
IoTGpioSetDir(HI_IO_NAME_GPIO_9, IOT_GPIO_DIR_OUT);
// 初始化PWM模块
IoTPwmInit(HI_PWM_PORT_PWM0);
// 创建线程
if (osThreadNew((osThreadFunc_t)TrafficLightTask, NULL, &attr) == NULL)
{
printf("Falied to create TrafficLightTask!\n");
}
}
// 运行入口函数
APP_FEATURE_INIT(StartTrafficLightTask);
\applications\sample\wifi-iot\app\pwm_demo\BUILD.gn:
# 静态库
static_library("pwm_demo") {
sources = [
# "pwm_buz.c"
# "pwm_music.c"
# "pwm_volume.c"
# "traffic_light.c"
# "pwm_led.c"
"music2.c","traffic_light.c","display.c","oled_ssd1306.c"
]
include_dirs = [
"//utils/native/lite/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//foundation/communication/wifi_lite/interfaces/wifiservice",
"//device/hisilicon/hispark_pegasus/sdk_liteos/include",
"//device/hisilicon/hispark_pegasus/sdk_liteos/platform/include",
"//base/iot_hardware/peripheral/interfaces/kits",
"//applications/sample/wifi-iot/app/ssd1306_3rd_driver/ssd1306",
]
}
\applications\sample\wifi-iot\app\BUILD.gn:
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
"pwm_demo",
]
}
现在我要加入两首曲子并且实现切歌功能,请为我提供一份可行的代码方案,并告诉我如何添加或修改哪个路径下的哪个文件的详细步骤。