Files
tc264smart/code/user_menu_device.c
32343 843447835d Initial commit: TC264 smart car project with IPS200 menu system
- 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
2026-05-10 21:38:49 +08:00

196 lines
7.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*============================================================
* 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;
}
}