本帖最后由 WangChong 于 2025-5-23 03:43 编辑
简介
在上两篇文章中, 我们实现了GPIO输出, 和PWM输出(组件介绍在前文中已经介绍过, 可以从安信可离线语音模组 VC-01、VC-02 系列教程 【总览】进行跳转
), 在本章节我们将继续进行使用语音指令控制串口输出。
配置Example默认串口数据输出
1- 首先修改/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/inc/user_config.h 中的USER_RUN_DEMO_SELECT 为 USER_DEMO_UART
这样的话默认运行的程序就是 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/examples/hb_uart.c
代码如下所示
- #include "user_uart.h"
- #include "user_event.h"
- #include "user_player.h"
- #include "user_config.h"
- #define TAG "hb_uart_voice"
- static uni_pthread_t g_uart_thread_id = 0;
- static bool g_uart_thread_running = false;
- // 串口发送线程函数
- static void _uart_send_task(void *args) {
- char buf[6] = {1, 2, 3, 4, 5, 6};
- int ret;
- g_uart_thread_running = true;
- while (g_uart_thread_running) {
- LOGT(TAG, "UART send done, ret=%d", ret);
- uni_msleep(2000); // 每隔2秒发送一次
- }
- }
- // 创建发送线程
- static Result _create_uart_thread(void) {
- if (g_uart_thread_running) {
- return E_OK;
- }
- thread_param param;
- uni_memset(¶m, 0, sizeof(param));
- param.stack_size = STACK_SMALL_SIZE;
- param.priority = OS_PRIORITY_LOW;
- uni_strncpy(param.task_name, "uart_voice", sizeof(param.task_name) - 1);
- if (0 != uni_pthread_create(&g_uart_thread_id, ¶m, _uart_send_task, NULL)) {
- return E_FAILED;
- }
- uni_pthread_detach(g_uart_thread_id); // 自动资源回收
- return E_OK;
- }
- // 停止发送线程
- static void _stop_uart_thread(void) {
- if (!g_uart_thread_running) return;
- g_uart_thread_running = false;
- if (g_uart_thread_id != 0) {
- uni_pthread_destroy(g_uart_thread_id);
- g_uart_thread_id = 0;
- }
- }
- // 语音唤醒命令回调
- static void _on_wakeup_cmd_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
- if (context == NULL) return;
- event_goto_awakend_t *awake = &context->goto_awakend;
- if (strcmp(awake->cmd, "wakeup_uni") == 0) {
- _create_uart_thread(); // 启动串口线程
- user_player_reply_list_random(awake->reply_files); // 播放语音回复
- }
- }
- // 自定义设置命令回调
- static void _custom_setting_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
- if (context == NULL) return;
- event_custom_setting_t *setting = &context->custom_setting;
- if (strcmp(setting->cmd, "TurnOn") == 0) {
- _stop_uart_thread(); // 停止串口线程
- user_player_reply_list_random(setting->reply_files); // 播放语音回复
- }
- }
- // 注册语音事件回调
- static void _register_event_callback(void) {
- user_event_subscribe_event(USER_GOTO_AWAKENED, _on_wakeup_cmd_cb);
- user_event_subscribe_event(USER_CUSTOM_SETTING, _custom_setting_cb);
- }
- // 主入口
- int hb_user_uart_voice_control(void) {
- if (0 != user_uart_init(NULL)) {
- LOGE(TAG, "UART init failed");
- return -1;
- }
- _register_event_callback();
- return 0;
- }
复制代码
其默认行为为创建线程定时发送数据, 然后使用LOG打印。但是它没办法调试。 因此我们做一点简单的修改, 当接受的数据的时候再发送出去。
- // 串口发送线程函数
- static void _uart_send_task(void *args) {
- char buf[6] = {1, 2, 3, 4, 5, 6};
- int ret;
- g_uart_thread_running = true;
- while (g_uart_thread_running) {
- LOGT(TAG, "Voice triggered UART send [1, 2, 3, 4, 5, 6]");
- ret = user_uart_send(buf, sizeof(buf));
- LOGT(TAG, "UART send done, ret=%d", ret);
- uni_msleep(2000); // 每隔2秒发送一次
- }
- }
复制代码
2- 编译和烧录
实验现象
串口以9600的波特率持续接受到数据 01,02,03,04,05,06 和程序中的数据对应。 正确无误
发送测试
之后我们尝试向其发送数据, 查看VC02是否能正常转发回来。 (关闭HEX显示, 发送的数据和接受的一致)
使用语音命令控制串口发送数据
1- 创建文件hb_user_uart_testing.c 在 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/examples 下
- #include "user_uart.h"
- #include "user_event.h"
- #include "user_player.h"
- #include "user_config.h"
- #define TAG "hb_uart_voice"
- static uni_pthread_t g_uart_thread_id = 0;
- static bool g_uart_thread_running = false;
- // 串口发送线程函数
- static void _uart_send_task(void *args) {
- char buf[6] = {1, 2, 3, 4, 5, 6};
- int ret;
- g_uart_thread_running = true;
- while (g_uart_thread_running) {
- LOGT(TAG, "Voice triggered UART send [1, 2, 3, 4, 5, 6]");
- ret = user_uart_send(buf, sizeof(buf));
- LOGT(TAG, "UART send done, ret=%d", ret);
- uni_msleep(2000); // 每隔2秒发送一次
- }
- }
- // 创建发送线程
- static Result _create_uart_thread(void) {
- if (g_uart_thread_running) {
- return E_OK;
- }
- thread_param param;
- uni_memset(¶m, 0, sizeof(param));
- param.stack_size = STACK_SMALL_SIZE;
- param.priority = OS_PRIORITY_LOW;
- uni_strncpy(param.task_name, "uart_voice", sizeof(param.task_name) - 1);
- if (0 != uni_pthread_create(&g_uart_thread_id, ¶m, _uart_send_task, NULL)) {
- return E_FAILED;
- }
- uni_pthread_detach(g_uart_thread_id); // 自动资源回收
- return E_OK;
- }
- // 停止发送线程
- static void _stop_uart_thread(void) {
- if (!g_uart_thread_running) return;
- g_uart_thread_running = false;
- if (g_uart_thread_id != 0) {
- uni_pthread_destroy(g_uart_thread_id);
- g_uart_thread_id = 0;
- }
- }
- // 语音唤醒命令回调
- static void _on_wakeup_cmd_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
- if (context == NULL) return;
- event_goto_awakend_t *awake = &context->goto_awakend;
- if (strcmp(awake->cmd, "wakeup_uni") == 0) {
- _create_uart_thread(); // 启动串口线程
- user_player_reply_list_random(awake->reply_files); // 播放语音回复
- }
- }
- // 自定义设置命令回调
- static void _custom_setting_cb(USER_EVENT_TYPE event, user_event_context_t *context) {
- if (context == NULL) return;
- event_custom_setting_t *setting = &context->custom_setting;
- if (strcmp(setting->cmd, "TurnOn") == 0) {
- _stop_uart_thread(); // 停止串口线程
- user_player_reply_list_random(setting->reply_files); // 播放语音回复
- }
- }
- // 注册语音事件回调
- static void _register_event_callback(void) {
- user_event_subscribe_event(USER_GOTO_AWAKENED, _on_wakeup_cmd_cb);
- user_event_subscribe_event(USER_CUSTOM_SETTING, _custom_setting_cb);
- }
- // 主入口
- int hb_user_uart_voice_control(void) {
- if (0 != user_uart_init(NULL)) {
- LOGE(TAG, "UART init failed");
- return -1;
- }
- _register_event_callback();
- return 0;
- }
复制代码
输入上述代码, 其主要的业务逻辑就是通过唤醒命令来触发串口的定时输出,然后通过TrunOn的命令来关闭串口输出的线程
2- 添加编译支持 在 /home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/build/user/src/examples 下的 subdir.mk 添加对当前编译文件的引用。
3- 修改/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/inc/user_config.h 文件, 增加对应的demo宏支持
4 - 修改/home/vc02/Downloads/uni_hb_m_solution/unione_lite_app_hb_m/user/src/user_main.c 增加对上述自定义宏的支持
5- 编译并且烧录固件
实验现象
烧录完成之后, 串口默认不输出任何数据
当识别到语音命令“你好小美” 之后将开始打印 01, 02, 03, 04, 05
当识别到语音命令“打开灯光” 的时候将删除串口发送进程, 串口停止输出
如上图所示, 此时的串口处于打开状态,但是没有输出数据。
附件:
|