💌 所属专栏:【BES2500x系列】
😀 作 者:我是夜阑的狗🐶
🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!
💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘
您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩
文章目录
前言
大家好,又见面了,我是夜阑的狗🐶,本文是专栏【BES2500x系列】专栏的第18篇文章;
今天开始学习BES2500x系列的一天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。
专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。
如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。
1 出入盒中断响应流程
在TWS(真无线立体声)耳机设计中,耳机与充电盒的出入状态检测是用户体验与功耗优化的核心功能之一。基于BES芯片的嵌入式系统通过硬件中断触发+软件状态机处理的机制,能够高效、稳定地实现耳机入盒休眠、出盒唤醒等功能。本文将围绕BES芯片的中断响应流程,从初始化到事件处理的全链路进行深度剖析,让我们原文再续,书接上回吧。
1.1 关于入盒出盒的初始化
出入盒检测的初始化分为硬件初始化与软件状态初始化两部分:
1.1.1 硬件配置
-
霍尔传感器(HALL Sensor):BES芯片通过霍尔传感器检测磁场变化(充电盒盖的开闭),配置对应的GPIO引脚为中断输入模式。
-
中断触发方式:设置为双边沿触发(
GPIO_INT_TRIG_BOTH
),即耳机入盒(磁场增强)和出盒(磁场减弱)均触发中断。 -
去抖动配置:通过
hal_gpio_debounce_enable()
使能硬件去抖动(典型值5~10ms),避免机械抖动导致误触发。
1.1.2 软件初始化
-
初始化全局状态变量(如
g_headphone_in_box
),记录耳机当前状态。 -
注册中断服务函数(ISR):将
hall_sensor_irq_handler()
绑定到对应GPIO,并在中断触发时调用app_battery_event_process()
进入事件处理流程。
1.2 app_battery_event_process()
static void app_battery_event_process(enum APP_BATTERY_STATUS_T status, APP_BATTERY_MV_T volt)
{
uint32_t app_battevt;
APP_MESSAGE_BLOCK msg;
APP_BATTERY_TRACE(3,"%s %d,%d",__func__, status, volt);
msg.mod_id = APP_MODUAL_BATTERY; // 设置消息结构体中的模块 ID 为 APP_MODUAL_BATTERY,表示这条消息与电池模块相关。
APP_BATTERY_SET_MESSAGE(app_battevt, status, volt); // 这个宏或函数调用用于设置 app_battevt 变量的值,将电池状态和电压值存储到其中,以便后续构建消息。
msg.msg_body.message_id = app_battevt;
msg.msg_body.message_ptr = (uint32_t)NULL;
app_mailbox_put(&msg); // 将构建好的消息 msg 放入邮箱中,等待其他模块或线程处理。
}
可以看下这些宏具体作用吧,前面文章也有具体介绍过,但这里还是要说一下。
文件头部这里定义了两个宏,分别是 APP_BATTERY_SET_MESSAGE
和 APP_BATTERY_GET_PRAMS
,它们的功能如下:
#define APP_BATTERY_SET_MESSAGE(appevt, status, volt) (appevt = (((uint32_t)status&0xffff)<<16)|(volt&0xffff))
......
#define APP_BATTERY_GET_PRAMS(appevt, prams) ((prams) = appevt&0xffff)
这两个宏定义看起来是用于在应用事件中设置和获取电池状态和电压的函数。
APP_BATTERY_SET_MESSAGE
宏用于设置应用事件中的电池状态和电压。接受三个参数:appevt
是应用事件,status
是电池状态,volt
是电压。
序号 | 参数 | 说明 |
---|---|---|
1 | ((uint32_t)status&0xffff) | 这部分将 status 转换为 32 位整数,并保留低 16 位的值,确保不超出范围。 |
2 | ((volt)&0xffff) | 同样,将 volt 的低 16 位保留下来。 |
3 | (((uint32_t)status&0xffff)<<16)|(volt&0xffff) | 将 status 的低 16 位左移 16 位,然后与 volt 的低 16 位进行按位或操作,得到一个 32 位的值,表示电池状态和电压。 |
最后将这个值赋给 appevt。
APP_BATTERY_GET_PRAMS
宏用于从应用事件中获取电池参数。接受两个参数:appevt
是应用事件,prams
是要存储参数的变量。
序号 | 参数 | 说明 |
---|---|---|
1 | ((prams) = appevt&0xffff) | 这部分将 appevt 的低 16 位(即电池参数)提取出来,并赋给 prams。 |
这两个宏的作用是方便地在应用事件中设置和获取电池状态和电压。注意:这里比较容易让人忽略,其实我们传输的参数是电池插拔状态和充电器插拔状态,只是与电池状态与电压共用一个消息结构而已。
APP_BATTERY_SET_MESSAGE(app_battevt, status, volt)
;可以知道 app_battevt
的高16位是电池插拔状态 APP_BATTERY_STATUS_PLUGINOUT
, 低16位是充电器插拔状态 APP_BATTERY_CHARGER_PLUGOUT
。
1.3 app_battery_handle_process()
此时邮箱线程根据对应 ID 调用其钩子函数进行处理消息,而邮箱电量ID的钩子函数就是 app_battery_handle_process()
。
static int app_battery_handle_process(APP_MESSAGE_BODY *msg_body)
{
uint8_t status;
union APP_BATTERY_MSG_PRAMS msg_prams;
APP_BATTERY_GET_STATUS(msg_body->message_id, status); // 获取电池状态
APP_BATTERY_GET_PRAMS(msg_body->message_id, msg_prams.prams);
......
// 触发插拔中断上报状态后,根据充电引脚状态进行处理
if (status == APP_BATTERY_STATUS_PLUGINOUT){
// 启动防抖定时器
app_battery_pluginout_debounce_start();
}
else
{
......
}
.......
}
1.4 app_battery_pluginout_debounce_start()
当邮箱线程处理对应消息时,可以看到电池状态为出盒状态时,就启动防抖定时器,
static void app_battery_pluginout_debounce_start(void)
{
TRACE(1,"%s", __func__);
......
osTimerStart(app_battery_pluginout_debounce_timer, CHARGER_PLUGINOUT_DEBOUNCE_MS);
}
1.5 app_battery_pluginout_debounce_handler()
前面我们已经知道该定时器注册的钩子函数是 app_battery_pluginout_debounce_handler()
,
static void app_battery_pluginout_debounce_handler(void const *param)
{
// 出入盒检测定时器的钩子函数
// 获取出入盒状态
enum APP_BATTERY_CHARGER_T status_charger = app_battery_charger_forcegetstatus();
......
if (app_battery_pluginout_debounce_cnt >= CHARGER_PLUGINOUT_DEBOUNCE_CNT){
// 当时长大于设定值后,判定为入盒并将该状态发给线程处理
if (status_charger == APP_BATTERY_CHARGER_PLUGIN)
{
// 入盒状态
......
}
else
{
// 出盒状态,设置 pin 引脚
......
}
// 上报当前充电状态
app_battery_event_process(APP_BATTERY_STATUS_CHARGING, status_charger);
// 设置充电器的中断处理函数
pmu_charger_set_irq_handler(app_battery_charger_handler);
// 停止防抖定时器
osTimerStop(app_battery_pluginout_debounce_timer);
}
}
开启出入盒检测定时器时候,可以看到那电池状态为 APP_BATTERY_STATUS_PLUGINOUT
(出盒)时,设置完 pin 引脚后,然后通过 app_battery_event_process()
将电池充电状态发送到邮箱线程中。
app_battery_event_process()
通过 APP_BATTERY_SET_MESSAGE
这个宏将电池状态和电压值存储到 msg.msg_body.message_id
中,以便后续构建消息。
总结
感谢观看,这里就是 出入盒中断响应流程 的讲解,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹
也欢迎你,关注我。👍 👍 👍
原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉
更多专栏订阅:
订阅更多,你们将会看到更多的优质内容!!