- IPS200 display menu with real-time status and parameter settings - Camera image processing and line tracking - IMU attitude solution and PID control - WiFi SPI oscilloscope data transmission
196 lines
7.3 KiB
C
196 lines
7.3 KiB
C
/*============================================================
|
||
* TC264 智能车 - 菜单设备层模块 (user_menu_device.c)
|
||
*
|
||
* 功能说明:
|
||
* 提供菜单系统所需的设备数据采集与计算功能。
|
||
* 包括电池电压监测、CPU 占用率统计等底层支持。
|
||
*
|
||
* 主要功能:
|
||
* 1. battery_voltage_gather() - 采集电池电压并计算剩余电量百分比
|
||
* 2. cpu_usage_check() - 统计 CPU 占用率
|
||
*============================================================*/
|
||
|
||
#include "zf_common_function.h" /* 通用函数(数学运算等) */
|
||
#include "zf_driver_timer.h" /* 定时器驱动(system_start等) */
|
||
#include "zf_driver_delay.h" /* 延时函数 */
|
||
#include "zf_driver_gpio.h" /* GPIO 驱动 (蜂鸣器) */
|
||
#include "user_menu.h" /* 菜单头文件 */
|
||
#include "user_menu_device.h" /* 设备层头文件 */
|
||
|
||
/*============================================================
|
||
* 电池电压相关变量
|
||
*============================================================*/
|
||
float battery_voltage; /* 电池电压值 (V) */
|
||
float battery_percentage; /* 电池剩余百分比 (0-100) */
|
||
float battery_percentage_filter; /* 电池百分比(经低通滤波平滑后) */
|
||
|
||
/*============================================================
|
||
* CPU占用率相关变量
|
||
*============================================================*/
|
||
float cpu_usage_percentage; /* CPU占用率 (0-100) */
|
||
float cpu_usage_percentage_filter; /* CPU占用率(经低通滤波平滑后) */
|
||
|
||
/*============================================================
|
||
* 电池电压采集与电量计算
|
||
*
|
||
* 计算原理:
|
||
* 1. ADC 读取电压值 (0-4095)
|
||
* 2. 根据分压电阻比例换算为实际电池电压
|
||
* V_bat = adc_val / 4096 * 36.3 * 校正系数
|
||
* 3. 根据锂电池特性估算剩余电量
|
||
* 单节锂电池电压范围:3.7V (空) ~ 4.23V (满)
|
||
* 根据总电压判断串联锂电池节数
|
||
* 线性映射到 0-100%
|
||
* 4. 低通滤波 (一阶惯性滤波) 平滑输出
|
||
*
|
||
* 输入参数:
|
||
* adc_get_data: ADC 采集的原始值 (0-4095)
|
||
*
|
||
* 输出 (全局变量):
|
||
* battery_voltage - 当前电压值 (V)
|
||
* battery_percentage - 当前电量百分比
|
||
* battery_percentage_filter - 滤波后的电量百分比
|
||
*============================================================*/
|
||
void battery_voltage_gather(uint16 adc_get_data)
|
||
{
|
||
uint8 cell_num = 0; /* 锂电池串联节数 */
|
||
float effective_voltage = 0; /* 有效电压范围 */
|
||
|
||
/* 计算实际电池电压
|
||
* 36.3 = 参考电压分压比 (需根据实际硬件电路调整)
|
||
* VOLTAGE_RECTIFY_COEFFICIENT = 电压校正系数 */
|
||
battery_voltage = (float)adc_get_data / 4096.0f * 36.3f * VOLTAGE_RECTIFY_COEFFICIENT;
|
||
|
||
/* 判断锂电池串联节数 (区间阈值法,避免 ceil 在临界值误判)
|
||
* 1S: < 5.5V, 2S: 5.5~10.5V, 3S: 10.5~15.0V, 4S: > 15.0V */
|
||
if(battery_voltage < 5.5f)
|
||
cell_num = 1;
|
||
else if(battery_voltage < 10.5f)
|
||
cell_num = 2;
|
||
else if(battery_voltage < 15.0f)
|
||
cell_num = 3;
|
||
else
|
||
cell_num = 4;
|
||
|
||
/* 有效电压范围 = 0.5V * 节数 (留出余量) */
|
||
effective_voltage = 0.5f * (float)cell_num;
|
||
|
||
/* 将电压线性映射到 0-100%
|
||
* 基准电压 = 3.7V * 串联节数 (空电截止电压) */
|
||
battery_percentage = (func_limit_ab(
|
||
(battery_voltage - 3.7f * (float)cell_num),
|
||
0.0f, effective_voltage) / effective_voltage * 100.0f);
|
||
|
||
/* 一阶低通滤波:新值 = 旧值 * (49/50) + 当前值 * (1/50)
|
||
* 用于平滑电量显示,避免显示值跳变 */
|
||
battery_percentage_filter = (battery_percentage_filter * 49.0f + battery_percentage) / 50.0f;
|
||
}
|
||
|
||
/*============================================================
|
||
* CPU 占用率统计
|
||
*
|
||
* 实现原理:
|
||
* 每帧处理完成后调用本函数,传入该帧的耗时(us)。
|
||
* 累积所有帧的耗时,每 1000ms 计算占比:
|
||
* CPU占用率 = (累积耗时 / 总时长) * 100%
|
||
* 使用一阶低通滤波平滑显示。
|
||
*
|
||
* 示例:
|
||
* 50fps 摄像头,每帧 20ms 周期,处理耗时 8ms
|
||
* 在 1 秒内累积 50 * 8000us = 400000us
|
||
* 占用率 = 400000 / (1000*1000) * 100 = 40%
|
||
*============================================================*/
|
||
void cpu_usage_record_frame(uint32 frame_busy_us)
|
||
{
|
||
static uint32 cpu_busy_us = 0; /* 累积忙碌时间 (us) */
|
||
static uint32 cpu_last_ms = 0; /* 上次统计时刻 (ms) */
|
||
static uint8 cpu_timer_ok = 0; /* 系统定时器是否已启动 */
|
||
uint32 now;
|
||
|
||
if(!cpu_timer_ok)
|
||
{
|
||
system_start();
|
||
cpu_timer_ok = 1;
|
||
}
|
||
|
||
cpu_busy_us += frame_busy_us;
|
||
now = system_getval_ms();
|
||
|
||
/* 每 1000ms 统计一次 */
|
||
if(now - cpu_last_ms >= 1000)
|
||
{
|
||
uint32 elapsed_ms = now - cpu_last_ms;
|
||
|
||
/* 占用率 = 忙时间 / 总时间 * 100 */
|
||
/* busy_us / (elapsed_ms * 1000us) * 100 = busy_us / (elapsed_ms * 10) */
|
||
cpu_usage_percentage = (float)cpu_busy_us / (float)(elapsed_ms * 10);
|
||
|
||
if(cpu_usage_percentage > 100.0f)
|
||
cpu_usage_percentage = 100.0f;
|
||
|
||
cpu_busy_us = 0;
|
||
cpu_last_ms = now;
|
||
}
|
||
|
||
/* 一阶低通滤波平滑显示 */
|
||
cpu_usage_percentage_filter = (cpu_usage_percentage_filter * 49.0f + cpu_usage_percentage) / 50.0f;
|
||
}
|
||
|
||
/*============================================================
|
||
* 低电量蜂鸣报警
|
||
*
|
||
* 功能说明:
|
||
* 当滤波后电量 <= 30% 时,蜂鸣器"滴滴滴"连响3声后停止。
|
||
* 电量回升到 35% 以上后重置,可再次触发。
|
||
* 使用 system_getval_ms() 非阻塞计时,不影响其他功能。
|
||
*============================================================*/
|
||
void low_battery_alarm_check(void)
|
||
{
|
||
static uint8 state = 0; /* 0=待机, 1=鸣响, 2=间歇, 3=冷却 */
|
||
static uint8 cnt = 0; /* 已响次数 */
|
||
static uint32 t0 = 0; /* 状态进入时刻 (ms) */
|
||
uint32 now = system_getval_ms();
|
||
|
||
switch(state)
|
||
{
|
||
case 0: /* 待机:电量过低且电池真实存在时触发 */
|
||
if(battery_voltage > 5.0f
|
||
&& battery_percentage_filter > 0.1f
|
||
&& battery_percentage_filter <= BATT_ALARM_THRESHOLD)
|
||
{
|
||
state = 1;
|
||
cnt = 0;
|
||
gpio_high(BEEP_PIN);
|
||
t0 = now;
|
||
}
|
||
break;
|
||
|
||
case 1: /* 鸣响中:持续 200ms 后关闭 */
|
||
if(now - t0 >= 200)
|
||
{
|
||
gpio_low(BEEP_PIN);
|
||
cnt++;
|
||
if(cnt >= 3)
|
||
state = 3; /* 响完3声进入冷却 */
|
||
else
|
||
state = 2; /* 进入间歇 */
|
||
t0 = now;
|
||
}
|
||
break;
|
||
|
||
case 2: /* 间歇中:静音 200ms 后再次鸣响 */
|
||
if(now - t0 >= 200)
|
||
{
|
||
gpio_high(BEEP_PIN);
|
||
state = 1;
|
||
t0 = now;
|
||
}
|
||
break;
|
||
|
||
case 3: /* 冷却:等待电量回升到 35% 以上,避免重复报警 */
|
||
if(battery_percentage_filter > BATT_ALARM_THRESHOLD + 5.0f)
|
||
state = 0;
|
||
break;
|
||
}
|
||
}
|