#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