💌 所属专栏:【BES2500x系列】
😀 作 者:我是夜阑的狗🐶
🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!
💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘
您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩
文章目录
- 前言
- [1 真正的 Battery 模块](#1 真正的 Battery 模块)
-
-
- [1.1 app_battery_open()](#1.1 app_battery_open())
- [1.2 APP_BATTERY_MEASURE_T](#1.2 APP_BATTERY_MEASURE_T)
- [1.3 osTimerDef](#1.3 osTimerDef)
-
- 总结
前言
大家好,又见面了,我是夜阑的狗🐶,本文是专栏【BES2500x系列】专栏的第15篇文章;
今天开始学习BES2500x系列的一天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。
专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。
如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。
1 真正的 Battery 模块
从上一篇文章中已经知道邮箱线程中的钩子函数是通过 app_set_threadhandle()
函数注册到静态变量。接下来就让我们来看一下,在应用初始化 app_init()
中 Battery
模块是怎么初始化的。话不多说,那接下来就真正学习 Battery
模块具体是怎么跑的,让我们原文再续,书接上回吧。
1.1 app_battery_open()
这里我们选取一个模块 APP_MODUAL_BATTERY(APP_MODULE_BATTERY)
来进行了解,由前面可知在系统初始化的时候 app_init
会对 Battery
模块进行初始化,也了解到充电检测执行流程如下步骤所示:
Step 1 、充电检测(电池状态,充电状态或是充电使用状态) ;
Step 2 、定时检测电量 ---> 可以通过中断方式检测当前电压值 ;
Step 3、将检测到的电压通过邮箱发送,并进行相应处理 ;
接下来让我们从 app_set_threadhandler()
的调用作为切入点。
- 代码
c
int app_battery_open(void)
{
// 开启电池模块初始化
int nRet = APP_BATTERY_OPEN_MODE_INVALID;
if (app_battery_timer == NULL)
// 创建电池电量检测定时器
app_battery_timer = osTimerCreate (osTimer(APP_BATTERY), osTimerPeriodic, NULL);
if (app_battery_pluginout_debounce_timer == NULL)
// 创建出入盒定时器
app_battery_pluginout_debounce_timer = osTimerCreate (osTimer(APP_BATTERY_PLUGINOUT_DEBOUNCE), osTimerOnce, &app_battery_pluginout_debounce_ctx);
// 标记电池状态
app_battery_measure.status = APP_BATTERY_STATUS_NORMAL;
#ifdef __INTERCONNECTION__
app_battery_measure.currentBatteryInfo = APP_BATTERY_DEFAULT_INFO;
app_battery_measure.lastBatteryInfo = APP_BATTERY_DEFAULT_INFO;
app_battery_measure.isMobileSupportSelfDefinedCommand = 0;
#else
// 设置电流等级
app_battery_measure.currlevel = APP_BATTERY_LEVEL_MAX;
#endif
// 电池状态信息
app_battery_measure.currvolt = APP_BATTERY_MAX_MV;
app_battery_measure.lowvolt = APP_BATTERY_MIN_MV;
app_battery_measure.highvolt = APP_BATTERY_MAX_MV;
app_battery_measure.pdvolt = APP_BATTERY_PD_MV;
app_battery_measure.chargetimeout = APP_BATTERY_CHARGE_TIMEOUT_MIN;
app_battery_measure.periodic = APP_BATTERY_MEASURE_PERIODIC_QTY;
// 指定电池电量钩子函数
app_battery_measure.cb = app_battery_event_process;
app_battery_measure.user_cb = NULL;
app_battery_measure.charger_status.prevolt = 0;
app_battery_measure.charger_status.slope_1000_index = 0;
app_battery_measure.charger_status.cnt = 0;
// 设置处理函数, 注册邮箱线程对应ID的钩子函数
app_set_threadhandle(APP_MODUAL_BATTERY, app_battery_handle_process);
// 注册出入盒钩子函数并根据当前状态设置 pin 引脚
if (app_battery_charger_indication_open() == APP_BATTERY_CHARGER_PLUGIN)
{
......
}
......
return nRet;
}
注意:该函数并不是完整的函数,只截取部分代码
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osTimerCreate(osTimerPeriodic) | 创建电池电量检测定时器 |
2 | osTimerCreate(osTimerOnce) | 创建出入盒定时器,这个定时器一般用于处理电池插拔事件的去抖动,以防止误触发。 |
3 | app_set_threadhandle() | 设置电池模块的线程处理函数。这个函数在电池状态发生变化时被调用,用于处理相关的逻辑。 |
4 | app_battery_event_process | 指定电池电量处理函数 |
5 | app_battery_charger_indication_open() | 函数首先初始化充电器,然后尝试获取充电器状态,如果充电器已插入则立即返回状态。如果外部充电器检测配置有效且检测到外部充电器已插入,则将状态设置为已插入。最后,设置充电器中断处理函数并返回状态。 |
可以看到 app_battery_open() 接口里调用了 app_set_threadhandle() 来添加 battery 模块的钩子函数,其中 app_battery_handle_process() 就是该模块的钩子函数。
1.2 APP_BATTERY_MEASURE_T
我们知道 app_battery_open() 是由 app_init() 调用来初始化 battery 模块的,以下是 battery 模块所用到全局变量。
- 代码
c
struct APP_BATTERY_MEASURE_T
{
uint32_t start_time; // 用于记录电池测量开始的时间
enum APP_BATTERY_STATUS_T status; // 表示当前电池的状态
#ifdef __INTERCONNECTION__
uint8_t currentBatteryInfo; // 存储当前电池信息
uint8_t lastBatteryInfo; // 用于存储上一次电池信息
uint8_t isMobileSupportSelfDefinedCommand; // 用于表示移动设备是否支持自定义命令
#else
uint8_t currlevel; // 表示当前电池的电量级别
#endif
APP_BATTERY_MV_T currvolt; // 表示当前电池的电压值
APP_BATTERY_MV_T lowvolt; // 表示电池的低电压阈值
APP_BATTERY_MV_T highvolt; // 表示电池的高电压阈值
APP_BATTERY_MV_T pdvolt; // 表示电池的充电电压
uint32_t chargetimeout; // 表示充电超时时间
enum APP_BATTERY_MEASURE_PERIODIC_T periodic; // 表示电池测量的周期
HAL_GPADC_MV_T voltage[APP_BATTERY_STABLE_COUNT]; // 用于存储电池的稳定电压值
uint16_t index; // 用于索引电池的稳定电压值
struct APP_BATTERY_MEASURE_CHARGER_STATUS_T charger_status; // 用于存储充电器的状态信息
APP_BATTERY_EVENT_CB_T cb; // 电池事件回调函数
APP_BATTERY_CB_T user_cb; // 用户定义的电池回调函数
};
从变量的初始化可以看到定制化的设置都在tgt_hardware.h 里面,还要其他定制化的设置。
c
//battery info
#define APP_BATTERY_MIN_MV (3200)
#define APP_BATTERY_PD_MV (3100)
#define APP_BATTERY_MAX_MV (4200)
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|
1.3 osTimerDef
在电池初始化 app_battery_open() 函数中,会分别开启电池电量检测定时器和出入盒定时器。接下来了解这两个定时器的创建过程吧,相信会看到一些意想不到的东西。
c
if (app_battery_timer == NULL)
// 创建电池电量检测定时器
app_battery_timer = osTimerCreate (osTimer(APP_BATTERY), osTimerPeriodic, NULL);
if (app_battery_pluginout_debounce_timer == NULL)
// 创建出入盒定时器
app_battery_pluginout_debounce_timer = osTimerCreate (osTimer(APP_BATTERY_PLUGINOUT_DEBOUNCE), osTimerOnce, &app_battery_pluginout_debounce_ctx);
注意:该函数并不是完整的函数,只截取部分代码
当我们滑到文件头部的时候就能看到似成相识的代码: osTimerDef
- 代码
c
// 定义一个静态函数,用于处理电池插拔事件的去抖动
// 该函数接收一个void类型的常量指针参数,通常用于传递需要的参数
static void app_battery_pluginout_debounce_handler(void const *param);
// 定义一个操作系统定时器,关联到app_battery_pluginout_debounce_handler函数
// 这个定时器用于在检测到电池插拔事件后进行延时处理,以过滤掉短暂的噪声信号
osTimerDef(APP_BATTERY_PLUGINOUT_DEBOUNCE, app_battery_pluginout_debounce_handler);
// 定义一个静态的定时器句柄,初始值为NULL
// 这个句柄用于在程序中唯一标识和操作APP_BATTERY_PLUGINOUT_DEBOUNCE定时器
static osTimerId app_battery_pluginout_debounce_timer = NULL;
// 定义一个静态函数app_battery_timer_handler,用于处理电池定时器事件
// 该函数接受一个void类型的常量指针参数,用于传递定时器事件相关的数据
// 由于定时器的处理函数往往需要在特定的时间间隔执行特定任务,因此定义为静态函数可以限制其作用范围,避免影响到其他模块
static void app_battery_timer_handler(void const *param);
// 使用宏osTimerDef定义一个名为APP_BATTERY的定时器结构体
// 该结构体关联到前面定义的app_battery_timer_handler函数
// 这一步是创建定时器的必要步骤,它将定时器和具体的处理函数关联起来
osTimerDef (APP_BATTERY, app_battery_timer_handler);
// 声明一个静态变量app_battery_timer,用于存储创建后的定时器实例的ID
// 在程序的其他部分,可以通过这个ID来操作定时器,例如启动、停止定时器
// 将其初始化为NULL,表示在程序的初始阶段,定时器实例还未被创建
static osTimerId app_battery_timer = NULL;
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osTimerDef(APP_BATTERY,...) | 使用宏osTimerDef定义一个名为APP_BATTERY的定时器结构体,这一步是创建定时器的必要步骤,它将定时器和具体的处理函数关联起来 |
没错,osTimerDef
与 邮箱线程 osThreadDef
创建流程原理是一样,这该死的熟悉感。让我们进去 osTimerDef
该宏在哪吧
- 代码
c
// === 定时器管理函数 ===
/// 定义一个定时器对象。
/// \param name 定时器对象的名称。
/// \param function 定时器回调函数的名称。
/// \note 可以修改: \b osTimerDef 的参数应当保持一致,但在每一个 CMSIS-RTOS 实现中,
/// 宏体是特定于实现的。
#if defined (osObjectsExternal) // 当对象是外部定义的
#define osTimerDef(name, function) \
extern osTimerDef_t os_timer_def_##name // 外部声明定时器定义
#else // 定义对象时
#define osTimerDef(name, function) \
uint32_t os_timer_cb_##name[5]; \ // 定义用于存储回调函数上下文的空间
osTimerDef_t os_timer_def_##name = \
{ (function), (os_timer_cb_##name) } // 初始化定时器定义结构体
#endif
- 参数/函数讲解
此宏定义用于创建定时器对象。功能如下:
1、定义或声明一个定时器对象 os_timer_def_##name
。
2、如果 osObjectsExternal
被定义,则仅声明对象并将其设为外部链接。
3、否则,定义对象并初始化其成员:回调函数为 function
,上下文为数组 os_timer_cb_##name
可以在 osTimerDef
是在 cmsis_os.h
里的定义,到这里可以肯定的说这 osTimerDef
不就跟 osThreadDef
一样嘛,都是将线程函数赋值到结构体中,终于有种大彻大悟的感觉了。
总结
** 感谢观看,这里就是 Battery模块 -- 创建电池检测定时器的讲解,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹**
** 也欢迎你,关注我。👍 👍 👍**
** 原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉**
更多专栏订阅:
订阅更多,你们将会看到更多的优质内容!!