安信可VC-01/02二次开发篇: PWM输出

描述

安信可


安信可离线语音VC-01/02:硬件规格书、开发资料、烧录工具、应用开发

安信可离线语音模组 VC-01、VC-02 系列教程 【基础认知篇】
安信可离线语音模组 VC-01、VC-02 系列教程 【快速上手篇】
安信可离线语音模组 VC-01、VC-02 系列教程 【中级入门篇】
安信可离线语音模组 VC-01、VC-02 系列教程 【高级进阶篇】
安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】虚拟开发环境搭建和分享
安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】事件和GPIO控制
安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】PWM输出
安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】串口输出
安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】SDK音频替换失败记录过程
安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】自定义音频播放控制
 

安信可离线语音模组 VC-01、VC-02 系列教程 【二次开发篇】PWM输出

简介

上一篇文章中我们对SDK的GPIO输出进行了控制, 我们将在本章节对PWM的输出进行控制(如果没有看过上一篇文章的,建议先去看对组件和设计的库函数的介绍),本篇SDK文件还是使用的上一章节的SDK(如无特殊说明,SDK不变)。

默认PWM DEMO输出现象

首先,在user_config.h 文件中开启对PWMLED的宏, 使其用户代码默认烧录USER_DEMO_PWM_LED的例程。
 

安信可

根据对应的hb_pwm_led.c 得知, 其线程启动后,主要是控制PWM_NUM_1_A27进行输出。

 

#define PWM_LED_GPIO_NUM  PWM_NUM_1_A27   // "MOSI" on HB-M demo board

 

首先对默认的Demo进行编译,并且下载到VC-02中。

将示波器连接到开发板背部的GPIOA27上, 那么此时示波器的波形如下所示:
 

安信可


占空比缓慢变化
 

安信可

此时默认的出厂PWM demo已经测试完毕。

如果想控制对应的PWM输出,可以参考user_pwm.h 中的函数定义。函数声明如下所示:

 

#ifndef USER_INC_USER_PWM_H_
#define USER_INC_USER_PWM_H_
#ifdef __cplusplus
  extern "C" {
#endif
#include "unione.h"
/** @ingroup uni_pwm_def
* PWM管脚号
*/
typedef enum {
  PWM_NUM_1_A27 = 0,
  PWM_NUM_1_B0,
  PWM_NUM_1_B2,      ///< PWM 1 only 1 pin work a time
  PWM_NUM_2_A28,     ///< used for PA enable, don't use it on HB-M demo board
  PWM_NUM_2_B1,
  PWM_NUM_2_B3,      ///< PWM 2 only 1 pin work a time
  PWM_NUM_MAX
}USER_PWM_NUM;
/** @addtogroup uni_pwm_inf
@{*/
/**
*@brief PWM初始化
*@param num PWM管脚号
*@param hz 频率
*@param is_high_duty a TRUE :占空比用高电平持续时间计算; a FALSE :占空比用低电平持续时间计算
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_init(USER_PWM_NUM num, uni_u32 hz, uni_bool is_high_duty);
/**
*@brief PWM反初始化
*@param num PWM管脚号
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_final(USER_PWM_NUM num);
/**
*@brief 开使PWM输出
*@param num PWM管脚号
*@param duty 占空比
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_start(USER_PWM_NUM num, uni_u8 duty);
/**
*@brief 停止PWM输出
*@param num PWM管脚号
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_stop(USER_PWM_NUM num);
/**
*@brief 暂停PWM输出
*@param num PWM管脚号
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_pause(USER_PWM_NUM num);
/**
*@brief 恢复PWM输出
*@param num PWM管脚号
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_resume(USER_PWM_NUM num);
/**
*@brief PWM占空比切换
*@param num PWM管脚号
*@param duty 占空比
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_change_duty(USER_PWM_NUM num, uni_u8 duty);
/**
*@brief PWM占空比增加
*@param num PWM管脚号
*@param ch_duty 增加的占空比
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_duty_inc(USER_PWM_NUM num, uni_u8 ch_duty);
/**
*@brief PWM占空比减小
*@param num PWM管脚号
*@param ch_duty 减小的占空比
*@retval 0  操作成功
*@retval -1 操作失败
*/
int user_pwm_duty_dec(USER_PWM_NUM num, uni_u8 ch_duty);
/** @}*/
#ifdef __cplusplus
}
#endif
#endif

 

自定义控制命令

尝试使用唤醒命令 “你好小美” 来启动PWM进程, 使用 “打开台灯” 命令来删除这个进程,从而控制PWM进行输出。

由于官方的SDK写的非常规范, 所以建议凡是个人相关的代码都可以写在example目录下。

1、首先在example 目录下创建hb_user_pwm_testing.c 文件,代码如下所示:

 

#include "user_gpio.h"
#include "user_pwm_led.h"
#include "user_event.h"
#include "user_player.h"
#include "user_config.h"
#define PWM_LED_GPIO_NUM  PWM_NUM_1_A27   // "MOSI" on HB-M demo board
static uni_pthread_t g_pwm_thread_id = 0;
static bool g_pwm_thread_running = false;
// Thread function to update LED brightness levels
static void _pwm_led_process(void *args) {
  LED_BRIGHT_LEVEL level = BRIGHT_LEVEL_0;
  g_pwm_thread_running = true;
  while (g_pwm_thread_running) {
    user_pwm_led_set_brightness(PWM_LED_GPIO_NUM, level);
    level += 1;
    if (level >= BRIGHT_LEVEL_MAX) {
      level = BRIGHT_LEVEL_0;
    }
    // uni_sleep(1); // Optional: slow down effect
  }
}
// Create PWM LED thread
static Result _create_pwm_led_thread(void) {
  if (g_pwm_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, "pwm_led", sizeof(param.task_name) - 1);
  if (0 != uni_pthread_create(&g_pwm_thread_id, ¶m, _pwm_led_process, NULL)) {
    return E_FAILED;
  }
  uni_pthread_detach(g_pwm_thread_id);  // Auto cleanup
  return E_OK;
}
// Stop PWM thread
static void _stop_pwm_led_thread(void) {
  if (!g_pwm_thread_running) {
    return;
  }
  g_pwm_thread_running = false;
  // Destroy thread if supported (may be platform-specific)
  if (g_pwm_thread_id != 0) {
    uni_pthread_destroy(g_pwm_thread_id);  // Hard stop
    g_pwm_thread_id = 0;
  }
  user_pwm_led_set_brightness(PWM_LED_GPIO_NUM, BRIGHT_LEVEL_0);  // Turn off LED
}
// Callback on voice command
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_pwm_led_thread();
    user_player_reply_list_random(awake- >reply_files);
  }
}
static void _custom_setting_cb(USER_EVENT_TYPE event,
                               user_event_context_t *context) {
  event_custom_setting_t *setting = NULL;
  if (context) {
    setting = &context- >custom_setting;
    if (strcmp(setting- >cmd, "TurnOn") == 0) {
       _stop_pwm_led_thread();
       user_player_reply_list_random(setting- >reply_files);
    }
  }
}
// Register event callback
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);
}
// Main entry
int hb_user_pwm_testing(void) {
  if (0 != user_pwm_led_init(PWM_LED_GPIO_NUM)) {
    return -1;
  }
  _register_event_callback();
  return 0;
}

 

上述代码的主要功能是定义两个用户事件 :

第一个为自定义设置的事件。

另一个则是唤醒事件 (上一篇文章中有介绍)。在识别到 “你好小美” 和 “打开灯光” 的时候控制对应的PWM行为。 如果当前PWM输出的线程没有被创建, 那么当识别到“你好小美”的时候将启动线程。当识别到“打开灯光”的时候则根据上述创建线程时的线程号删除线程。

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、编译并且烧录固件。

安信可

实验现象

默认上电波形如下(不清楚为什么会有毛刺)

安信可

使用“你好小美” 唤醒,波形如下:

安信可

安信可

使用“你好小美”唤醒 + “打开灯光” 关闭PWM,输出如下:

安信可

附件

uni_app_release_update.zip(882.62 KB, 下载次数: 0)

总结

在上文中主要结合IO和PWM的example进行了二次开发。其实可以发现,无论什么自定义功能,都是首先找到对应的库函数或者example进行引用。

在明白原理之后定义创建自己的.c 文件,然再将当前文件添加到编译的上下文中,在对应的h文件中开启对自定义C文件的宏定义,即可完成自定义的功能的二次开发。

实际上这个SDK的完整度非常高, 代码也非常规范!相信通过这几篇文章你能很快上手安信可的离线语音产品,下期再见~

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分