484 lines
15 KiB
C
Executable File
484 lines
15 KiB
C
Executable File
#include "../main/SystemInclude.h"
|
||
|
||
|
||
#if(DP2006V1000)
|
||
|
||
__SAMPLE_STATUS_BIT_TypeDef sampleState;
|
||
u16 offsetRType, offsetGCFX;
|
||
|
||
|
||
u16 processNextTime, processIndex;
|
||
|
||
u16 voltageDetected[ANX], adcGain;
|
||
|
||
// 当前显示单位
|
||
static PressureUnitType current_unit = PRESSURE_UNIT_PA; // 默认显示Pa
|
||
float pressure_value;
|
||
extern volatile uint8_t display_update_flag; // 显示更新标志
|
||
|
||
extern volatile uint8_t key_press_flag;//单位按键按下标志
|
||
volatile uint8_t display_update_flag = 0; // 显示更新标志
|
||
extern volatile Device_StateTypeDef g_device_state; // 初始状态:关机
|
||
u8 typecflag=0;
|
||
extern uint8_t g_auto_shutdown_flag;
|
||
// 全局变量,用于标记蓝牙是否已经初始化
|
||
static uint8_t g_ble_init_done = 0;
|
||
|
||
/******数据处理部分***************************************************************************************************************************************************************************************************************/
|
||
void FlowRateDealAndOuputSub(void)
|
||
{
|
||
ComputeFlowRateIndexAndFlowRate();//计算内码 转换成流量
|
||
}
|
||
|
||
void ComputeFlowRateIndexAndFlowRate(void)
|
||
{
|
||
voltageDetected[NIDX ]= (u16)sampleData.TCode[IRHCode]; // 强转,只保留低16位数据//IRH 0X8303
|
||
voltageDetected[VRHX ]= (u16)sampleData.TCode[IRRCode]; // 强转,只保留低16位数据//IRR 0X8304
|
||
voltageDetected[IVHDX]= (u16)sampleData.TCode[URUCode]; // 强转,只保留低16位数据//URU 0X8305
|
||
voltageDetected[RHVOL]= (u16)sampleData.TCode[URHCode]; // 强转,只保留低16位数据//URH 0X8306
|
||
voltageDetected[VDUGX]= (u16)sampleData.TCode[BASCode]; // 强转,只保留低16位数据//URU 0X8307 ADC基准电压/2
|
||
voltageDetected[TPCB]= (u16)sampleData.TCode[BATCode]; // 强转,只保留低16位数据//URH 0X8308 电池电压/3
|
||
|
||
voltageDetected[RHVOL]=voltageDetected[RHVOL]-32768;
|
||
pressure_value=GetFlowRate(voltageDetected[RHVOL],CURVE_1ST);
|
||
display_update_flag = 1;
|
||
if( voltageDetected[TPCB]>50000)
|
||
{
|
||
typecflag=1;
|
||
}
|
||
}
|
||
u16 WordSubFunction(u16 minuend, u16 subtractor)
|
||
{
|
||
u16 subResult;
|
||
|
||
subResult = minuend - subtractor;
|
||
if(minuend >= subtractor)
|
||
{
|
||
if(subResult < 32768) subResult += 32768;
|
||
else subResult = 65535;
|
||
}
|
||
else
|
||
{
|
||
if(subResult < 32768) subResult = 0;
|
||
else subResult -= 32768;
|
||
}
|
||
|
||
return subResult;
|
||
}
|
||
|
||
|
||
|
||
/******采集部分***************************************************************************************************************************************************************************************************************/
|
||
void SamplingTimer_IRQ_Callback(void)
|
||
{
|
||
FlowProcessManagement();
|
||
}
|
||
|
||
|
||
void StartNormolFlowMeasurement(void)//每125ms调用一次
|
||
{
|
||
|
||
HWState.SampledOver = 0;//采样结束标志重置
|
||
StartSamplingTimerInterval(32768); //启动比较定时器,开始从0递增计数
|
||
Timer_register_irq_callback(SamplingTimer,SamplingTimer_IRQ_Callback );//注册中断回调函数
|
||
|
||
processIndex = 0; //
|
||
processNextTime = 0;
|
||
FlowProcessManagement();//每个周期运行,开启采样过程
|
||
}
|
||
|
||
|
||
static void SetSystemForADCSample(u16 SampleSiagnl)//设置采样通道与采样次数
|
||
{
|
||
switch(SampleSiagnl)
|
||
{
|
||
case SIGNAL0:{
|
||
sampleData.adcConfig.Gain0 = ADC_PGA_GAIN_1;
|
||
sampleData.adcConfig.PChan0 = ADC0_AINP_AIN0;
|
||
sampleData.adcConfig.NChan0 = ADC0_AINM_AVSS;//IRH
|
||
sampleData.adcConfig.Gain1 = ADC_PGA_GAIN_1;
|
||
sampleData.adcConfig.PChan1 = ADC1_AINP_AIN2;
|
||
sampleData.adcConfig.NChan1 = ADC1_AINM_AVSS;//URU
|
||
sampleData.adcConfig.SPS=SPS_488;
|
||
|
||
}break;
|
||
case SIGNAL1: {
|
||
sampleData.adcConfig.Gain0 = ADC_PGA_GAIN_1;
|
||
sampleData.adcConfig.PChan0 = ADC0_AINP_AIN1;
|
||
sampleData.adcConfig.NChan0 = ADC0_AINM_AVSS;//IRR
|
||
sampleData.adcConfig.Gain1 = ADC_PGA_GAIN_1;
|
||
sampleData.adcConfig.PChan1 = ADC1_AINP_AIN3;
|
||
sampleData.adcConfig.NChan1 = ADC1_AINM_AVSS;//URH
|
||
sampleData.adcConfig.SPS=SPS_488;
|
||
}break;
|
||
case SIGNAL2: {
|
||
sampleData.adcConfig.Gain0 = ADC_PGA_GAIN_1;
|
||
sampleData.adcConfig.PChan0 = ADC0_AINP_AIN4;
|
||
sampleData.adcConfig.NChan0 = ADC0_AINM_AVSS;
|
||
sampleData.adcConfig.Gain1 = ADC_PGA_GAIN_1;
|
||
sampleData.adcConfig.PChan1 = ADC1_AINP_AIN7;
|
||
sampleData.adcConfig.NChan1 = ADC1_AINM_AVSS;//电池电压/3.2
|
||
sampleData.adcConfig.SPS=SPS_488;
|
||
}break;
|
||
}
|
||
}
|
||
|
||
static void SetNextProcess(void)//设置采样定时器的下一个进程
|
||
{
|
||
if(processIndex == 0){
|
||
StopSamplingTimerInterval();//关闭采集时钟
|
||
return;
|
||
}
|
||
u32 currentTAR = pTIM1->CNT;//定时器当前计数值
|
||
if(currentTAR > processNextTime) processNextTime = currentTAR + 5;
|
||
ResetSamplingTimerInterval(processNextTime);
|
||
}
|
||
|
||
void FlowProcessManagement(void)//采样过程管理状态机
|
||
{
|
||
switch(processIndex)
|
||
{
|
||
case 0:
|
||
{
|
||
HWState.SampledOver = 0;//采样开始
|
||
SetSystemForADCSample(SIGNAL0);//设置SIGNAL0
|
||
StartADCSyncSampingData();//开始采集
|
||
processNextTime += 327; //20ms 计数值=65535/4000*t =
|
||
processIndex=1;
|
||
}break;
|
||
case 1:
|
||
{
|
||
ComputeSampleData(); //计算样本数据
|
||
sampleData.TCode[IRHCode] = sampleData.ADCBuffer[0];//放入缓存
|
||
sampleData.TCode[URUCode] = sampleData.ADCBuffer[1];//放入缓存
|
||
SetSystemForADCSample(SIGNAL1);//设置SIGNAL1
|
||
StartADCSyncSampingData();//开始采集
|
||
processNextTime += 327;//20ms
|
||
processIndex=2;
|
||
}break;
|
||
case 2:
|
||
{
|
||
ComputeSampleData(); //计算样本数据
|
||
sampleData.TCode[IRRCode] = sampleData.ADCBuffer[0];//放入缓存
|
||
sampleData.TCode[URHCode] = sampleData.ADCBuffer[1];//放入缓存
|
||
SetSystemForADCSample(SIGNAL2);//设置SIGNAL1
|
||
StartADCSyncSampingData();//开始采集
|
||
processNextTime += 327;//20ms
|
||
processIndex=3;
|
||
}break;
|
||
case 3:
|
||
{
|
||
ComputeSampleData(); //计算样本数据
|
||
sampleData.TCode[BASCode] = sampleData.ADCBuffer[0];//放入缓存
|
||
sampleData.TCode[BATCode] = sampleData.ADCBuffer[1];//放入缓存
|
||
HWState.SampledOver = 1; //采样结束
|
||
StopSamplingTimerInterval();//关闭采集时钟
|
||
processIndex=4;
|
||
}break;
|
||
default : processIndex = 0; break;
|
||
}
|
||
SetNextProcess();
|
||
}
|
||
/******显示部分***************************************************************************************************************************************************************************************************************/
|
||
void SwitchPressureUnit(void)
|
||
{
|
||
// 1. 计算下一个单位 (循环切换)
|
||
current_unit = (PressureUnitType)((int)current_unit + 1);
|
||
if (current_unit > PRESSURE_UNIT_MBAR) { // 【修改】更新为新的最大单位
|
||
current_unit = PRESSURE_UNIT_PA;
|
||
}
|
||
// 2. 不再需要转换pressure_value,因为它永远是Pa单位
|
||
}
|
||
|
||
double ConvertPressure(double value, PressureUnitType targetUnit, PressureUnitType originalUnit)
|
||
{
|
||
double valueInPa;
|
||
|
||
if (targetUnit == originalUnit) return value;
|
||
// --- 第一步:将原始单位转换为标准单位 Pa ---
|
||
switch (originalUnit)
|
||
{
|
||
case PRESSURE_UNIT_MBAR:
|
||
valueInPa = value * ONE_MBAR_TO_PA;
|
||
break;
|
||
case PRESSURE_UNIT_TORR:
|
||
valueInPa = value * ONE_TORR_TO_PA;
|
||
break;
|
||
case PRESSURE_UNIT_MICRONS:
|
||
valueInPa = value * ONE_MICRONS_TO_PA;
|
||
break;
|
||
case PRESSURE_UNIT_PA:
|
||
valueInPa = value;
|
||
break;
|
||
default:
|
||
return value; // 未知单位,返回原值
|
||
}
|
||
|
||
// --- 第二步:将标准单位 Pa 转换为目标单位 ---
|
||
switch (targetUnit)
|
||
{
|
||
case PRESSURE_UNIT_MBAR:
|
||
return valueInPa * ONE_PA_TO_MBAR;
|
||
case PRESSURE_UNIT_TORR:
|
||
return valueInPa * ONE_PA_TO_TORR;
|
||
case PRESSURE_UNIT_MICRONS:
|
||
return valueInPa * ONE_PA_TO_MICRONS;
|
||
case PRESSURE_UNIT_PA:
|
||
return valueInPa;
|
||
default:
|
||
return valueInPa; // 未知目标单位,返回Pa值
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 计算一个32位无符号整数的位数
|
||
* @param num: 要计算的数字
|
||
* @retval 数字的位数
|
||
*/
|
||
static u8 GetDigitCount(u32 num)
|
||
{
|
||
u8 count = 0;
|
||
if (num == 0) return 1; // 0 是1位数
|
||
while (num != 0)
|
||
{
|
||
num /= 10;
|
||
count++;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
void OLED_DrawRect_Cache(u8 x, u8 y, u8 w, u8 h);
|
||
|
||
void Update_Pressure_Display(void)
|
||
{
|
||
// --- 1. 定义显示常量和变量 ---
|
||
#define FONT_WIDTH 12
|
||
#define FONT_HEIGHT 24
|
||
#define SCREEN_WIDTH 128
|
||
#define RIGHT_ALIGN_MARGIN 2
|
||
|
||
u8 unit_str_len = 0;
|
||
const char* unit_str = "";
|
||
u32 int_part = 0;
|
||
u32 decimal_part = 0;
|
||
u8 num_len = 0;
|
||
u8 has_decimal = 0;
|
||
u8 decimal_places = 0;
|
||
|
||
double display_val;
|
||
u8 current_x;
|
||
u8 total_num_width;
|
||
u8 display_x;
|
||
|
||
u8 fixed_erase_start_x;
|
||
u8 fixed_erase_end_x;
|
||
|
||
// --- 电量显示相关变量 ---
|
||
u16 battery_adc = 0;
|
||
u8 battery_level = 0;
|
||
u8 i = 0;
|
||
u8 bat_x = 0;
|
||
u8 bat_y = 0;
|
||
|
||
// 【设置】宽度 22,高度 12
|
||
u8 bat_w = 22;
|
||
u8 bat_h = 12;
|
||
|
||
// --- 2. 换算压力值 ---
|
||
display_val = ConvertPressure((double)pressure_value / 1000.0, current_unit, PRESSURE_UNIT_PA);
|
||
|
||
// --- 3. 格式化数据 ---
|
||
has_decimal = 1;
|
||
switch (current_unit)
|
||
{
|
||
case PRESSURE_UNIT_PA:
|
||
decimal_places = 1; int_part = (u32)(display_val + 0.05f);
|
||
decimal_part = (u32)(display_val * 10 + 0.5f) % 10;
|
||
unit_str = "pa"; unit_str_len = 2; break;
|
||
case PRESSURE_UNIT_MICRONS:
|
||
decimal_places = 1; int_part = (u32)(display_val + 0.05f);
|
||
decimal_part = (u32)(display_val * 10 + 0.5f) % 10;
|
||
unit_str = "mcm"; unit_str_len = 3; break;
|
||
case PRESSURE_UNIT_TORR:
|
||
decimal_places = 3; int_part = (u32)(display_val + 0.0005f);
|
||
decimal_part = (u32)(display_val * 1000 + 0.5f) % 1000;
|
||
unit_str = "torr"; unit_str_len = 4; break;
|
||
case PRESSURE_UNIT_MBAR:
|
||
decimal_places = 2; int_part = (u32)(display_val + 0.0005f);
|
||
decimal_part = (u32)(display_val * 100 + 0.5f) % 100;
|
||
unit_str = "mbar"; unit_str_len = 4; break;
|
||
}
|
||
|
||
num_len = GetDigitCount(int_part);
|
||
|
||
// --- 4. 压力区域刷新逻辑 ---
|
||
fixed_erase_start_x = 0;
|
||
fixed_erase_end_x = SCREEN_WIDTH - RIGHT_ALIGN_MARGIN;
|
||
OLED_FillArea(fixed_erase_start_x, 20, fixed_erase_end_x, 20 + FONT_HEIGHT);
|
||
|
||
// 绘制压力数值...
|
||
current_x = SCREEN_WIDTH - RIGHT_ALIGN_MARGIN;
|
||
current_x -= unit_str_len * FONT_WIDTH;
|
||
OLED_ShowString(current_x, 20, (u8*)unit_str, FONT_HEIGHT, 1);
|
||
|
||
total_num_width = num_len * FONT_WIDTH;
|
||
if (has_decimal) {
|
||
total_num_width += FONT_WIDTH;
|
||
total_num_width += decimal_places * FONT_WIDTH;
|
||
}
|
||
current_x -= total_num_width;
|
||
display_x = current_x;
|
||
OLED_ShowNum(display_x, 20, int_part, num_len, FONT_HEIGHT, 1);
|
||
display_x += num_len * FONT_WIDTH;
|
||
if (has_decimal) {
|
||
OLED_ShowChar(display_x, 20, '.', FONT_HEIGHT, 1);
|
||
display_x += FONT_WIDTH;
|
||
OLED_ShowNum(display_x, 20, decimal_part, decimal_places, FONT_HEIGHT, 1);
|
||
}
|
||
|
||
// --- 5. 电量显示逻辑---
|
||
battery_adc = voltageDetected[TPCB];
|
||
|
||
if(battery_adc >= 44761) battery_level = 4;
|
||
else if(battery_adc >= 43646) battery_level = 3;
|
||
else if(battery_adc >= 42532) battery_level = 2;
|
||
else if(battery_adc >= 41418) battery_level = 1;
|
||
else battery_level = 0;
|
||
|
||
// 2. 确定电池位置
|
||
bat_x = 128 - bat_w - 2;
|
||
bat_y = 0;
|
||
|
||
// 3. 绘制背景和边框 (先清空,再画框)
|
||
// 画一个大白色实心矩形
|
||
OLED_FillRect_White(bat_x, bat_y, bat_x + 22, bat_y + 12);
|
||
// 中间挖掉一个黑色矩形 (形成空心边框)
|
||
OLED_FillRect(bat_x + 1, bat_y + 1, bat_x + 21, bat_y + 11);
|
||
|
||
// 4. 根据电量等级绘制电量格
|
||
switch(battery_level)
|
||
{
|
||
case 4: // 满电:画第4格
|
||
OLED_FillRect_White(bat_x + 17, bat_y + 2, bat_x + 20, bat_y + 10);
|
||
// 注意:这里没有 break,是为了实现“穿透”效果
|
||
// 即:如果是4格电,它会继续往下执行画出第3、2、1格
|
||
case 3: // 3格电:画第3格
|
||
OLED_FillRect_White(bat_x + 12, bat_y + 2, bat_x + 15, bat_y + 10);
|
||
case 2: // 2格电:画第2格
|
||
OLED_FillRect_White(bat_x + 7, bat_y + 2, bat_x + 10, bat_y + 10);
|
||
case 1: // 1格电:画第1格
|
||
OLED_FillRect_White(bat_x + 2, bat_y + 2, bat_x + 5, bat_y + 10);
|
||
break; // 结束
|
||
case 0: // 0格电:只显示空框,不画内部
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// 5. 画凸起 (在最右侧紧贴)
|
||
OLED_FillRect_White(bat_x + 22, bat_y + 3, bat_x + 24, bat_y + 9);
|
||
|
||
|
||
// --- 6. 差异刷新 ---
|
||
OLED_Refresh_Line_Diff(0);
|
||
OLED_Refresh_Line_Diff(1);
|
||
|
||
// 压力区域刷新
|
||
OLED_Refresh_Line_Diff(2);
|
||
OLED_Refresh_Line_Diff(3);
|
||
OLED_Refresh_Line_Diff(4);
|
||
OLED_Refresh_Line_Diff(5);
|
||
}
|
||
|
||
// 辅助函数:绘制矩形边框(不填充)
|
||
void OLED_DrawRect_Cache(u8 x, u8 y, u8 w, u8 h)
|
||
{
|
||
// 上边
|
||
OLED_DrawLine(x, y, x + w - 1, y, 1);
|
||
// 下边
|
||
OLED_DrawLine(x, y + h - 1, x + w - 1, y + h - 1, 1);
|
||
// 左边
|
||
OLED_DrawLine(x, y, x, y + h - 1, 1);
|
||
// 右边
|
||
OLED_DrawLine(x + w - 1, y, x + w - 1, y + h - 1, 1);
|
||
}
|
||
// 定义一个你自己的函数,比如用来给LED闪烁计时的
|
||
static uint32_t led_timer = 0;
|
||
static uint32_t shutdown_timer = 0;
|
||
|
||
void My_Timer2_Callback(void)
|
||
{
|
||
// LED 逻辑
|
||
led_timer++;
|
||
if(led_timer >= 10) // 500ms
|
||
{
|
||
led_timer = 0;
|
||
LHL_GPIO_TogglePin(LED_PIN_GPIO, LED_PIN);
|
||
}
|
||
|
||
// 关机逻辑 (独立计数)
|
||
shutdown_timer++;
|
||
if(shutdown_timer > 72000)
|
||
{
|
||
g_auto_shutdown_flag = 1;
|
||
}
|
||
|
||
Key_Scan_Task();
|
||
Unit_key();
|
||
}
|
||
|
||
|
||
void SystemPolling(void)
|
||
{
|
||
static uint8_t power_off_screen_cleared = 0;
|
||
/* 1. 处理数据接收与存储 (优先级最高,与显示逻辑分离) */
|
||
if(mucSaveParams == PARAMS_READY)
|
||
{
|
||
SaveSysParams(); // 参数保存通常涉及Flash擦写,耗时较长,确认这里不会阻塞太久
|
||
}
|
||
if(HWState.SampledOver)
|
||
{
|
||
FlowRateDealAndOuputSub(); // 计算流量
|
||
}
|
||
if(comState.state.ReceivedData)
|
||
{
|
||
ReceivedDataProcessing();
|
||
}
|
||
/* 2. 处理界面显示 (根据设备状态分流) */
|
||
if(g_device_state == DEVICE_STATE_ON || typecflag == 1)
|
||
{
|
||
/* --- 开机/供电状态 --- */
|
||
// Update_Pressure_Display(); // 按键是低频事件,立即刷新没问题
|
||
// 按键处理:单次触发
|
||
if(key_press_flag)
|
||
{
|
||
key_press_flag = 0;
|
||
SwitchPressureUnit();
|
||
Update_Pressure_Display(); // 按键是低频事件,立即刷新没问题
|
||
}
|
||
|
||
// 数据刷新处理:单次触发
|
||
if(display_update_flag)
|
||
{
|
||
display_update_flag = 0; // 【关键】立即清除
|
||
Update_Pressure_Display();
|
||
if(g_ble_init_done==0)//蓝牙未初始化标志位
|
||
{
|
||
BLE_Application_Init();//第一次采集完成后进行蓝牙初始化
|
||
g_ble_init_done=1;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(!power_off_screen_cleared)
|
||
{
|
||
OLED_Clear();
|
||
OLED_Refresh();
|
||
power_off_screen_cleared = 1; // 标记已清屏,下次不再执行
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
#endif |