Files
CHJ/user/Core/DP2006_VM1000.c
2026-03-20 21:19:53 +08:00

582 lines
17 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.

#include "../main/SystemInclude.h"
/**************************************************************************************/
/**
* @brief 低功耗定时器初始化函数
* @note 需要定义与硬件相关的函数和IO
*/
//##############################################################################
#if(DP2006_VM1000)
//##############################################################################
//__SAMPLE_STATUS_BIT_TypeDef sampleState;
TypeSample sampleProcess;
u16 processNextTime, processIndex;
// 当前显示单位
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;
static uint32_t led_timer = 0;
static uint32_t shutdown_timer = 0;
/******采集部分***************************************************************************************************************************************************************************************************************/
void FlowRateDealAndOuputSub(void)
{
ComputeFlowRateIndexAndFlowRate();//计算内码 转换成流量
}
void ComputeFlowRateIndexAndFlowRate(void)
{
voltageDetected[NIDX ]=(u16)sampleProcess.IRHResult; // 强转只保留低16位数据//IRH 0X8303
voltageDetected[VRHX ]= (u16)sampleProcess.RHypeResult; // 强转只保留低16位数据//IRR 0X8304
voltageDetected[IVHDX]=(u16) sampleProcess.RDResult; // 强转只保留低16位数据//URU 0X8305
voltageDetected[RHVOL]= (u16)sampleProcess.BLypeResult; // 强转只保留低16位数据//URH 0X8306 电池电压/3
voltageDetected[VRHX]=voltageDetected[VRHX]-32768;
pressure_value=GetFlowRate(voltageDetected[VRHX],CURVE_1ST);
display_update_flag = 1;
if( voltageDetected[RHVOL]>50000)
{
typecflag=1;
}
}
u16 GetAdcGain(u16 gianX)
{
switch(gianX)
{
case 1: return GAIN1;
case 2: return GAIN2;
case 4: return GAIN4;
case 8: return GAIN8;
case 16: return GAIN16;
case 32: return GAIN32;
case 64: return GAIN64;
case 128: return GAIN128;
default:
return GetAdcGain(ADC_GAIN_DEFAULT);
}
}
/******采集部分***************************************************************************************************************************************************************************************************************/
void AnalogCircuitInit(void)
{
sampleProcess.CTypeGain = GetAdcGain(adcGain); //默认采样系数
SampingADCInit();
DisableSamplingInterrupt();
}
//void ProcessTimerInterruptCallBack(void)
//{
// FlowProcessManagement();
//
//}
//采样进程中断
void ProcessTimerInterruptCallBack(void)
{
DisableProcessTimerInterrupt();
HWState.ProcessTimerOut = 1;
}
//void StartNormolFlowMeasurement(void)//每125ms调用一次
//{
// AnalogCircuitInit();//初始化ADC
// HWState.SampledOver = 0;//采样结束标志重置
// StartProcessTimer(32768); //启动比较定时器,开始从0递增计数
// Timer_register_irq_callback(ProcessTimer,ProcessTimerIT, ProcessTimerInterruptCallBack );//注册中断回调函数
// processIndex = 0; //
// processNextTime = 0;
// FlowProcessManagement();//每个周期运行,开启采样过程
//}
void StartNormolFlowMeasurement(void)//开始常规流量测量
{
AnalogCircuitInit();
HWState.SampledOver = 0;//采样结束标志重置
StartProcessTimer(64000); // 启动比较定时器,开始从0递增计数
Timer_register_irq_callback(ProcessTimer,ProcessTimerIT, ProcessTimerInterruptCallBack );//注册中断回调函数
sampleProcess.NextRun = 0;
sampleProcess.NextTime= 0;
FlowProcessManagement();//每个周期运行,开启采样过程
}
//static void SetNextProcess(void)//设置采样定时器的下一个进程
//{
// if(processIndex == 0){
// StopProcessTimer();//关闭采集时钟
// return;
// }
// u32 currentTAR = pTIM1->CNT;//定时器当前计数值
// if(currentTAR > processNextTime) processNextTime = currentTAR + 5;
// ResetProcessTimer(processNextTime);
//}
void SetNextProcess(void)//设置采样定时器的下一个进程
{
if(sampleProcess.NextRun == 0){
StopProcessTimer();//关闭采集时钟
return;
}
// u32 currentTAR = ProcessTimer->CNT;//定时器当前计数值
// if(currentTAR > sampleProcess.NextTime) sampleProcess.NextTime = currentTAR + 5;
// ResetProcessTimer(sampleProcess.NextTime);
StartProcessTimer(sampleProcess.NextTime);
}
void SetSystemForADCSample(u16 sampleNum)
{
sampleProcess.Counter = 0;
sampleProcess.CounterMax = sampleNum;
StartSamplingADC();
}
void ComputeSampleData(u16 sampleNum, u16 sampleShift)
{
u32 I;
sampleProcess.ADC0Result = 0;
sampleProcess.ADC1Result = 0;
for(I = 0; I<sampleNum; I++)
{
sampleProcess.ADC0Result += ((sampleProcess.ADC0Buffer[I] >> 8) + 32768) & 0xFFFF;
sampleProcess.ADC1Result += ((sampleProcess.ADC1Buffer[I] >> 8) + 32768) & 0xFFFF;
}
sampleProcess.ADC0Result >>= sampleShift;
sampleProcess.ADC1Result >>= sampleShift;
}
/******************************************************************************/
void TurnOffAnalogCircuit(void)
{
StopSamplingADC();
DisableSamplingInterrupt();
}
//void FlowProcessManagement(void)//采样过程管理状态机
//{
// switch(processIndex)
// {
// case 0:
// {
// HWState.SampledOver = 0;//采样开始
// SetupRHChannle();
// SetupIRHypeChannle();
// SetSystemForADCSample(16); //开启ADC
// processNextTime += 20 * COUNT_VALUE_PER_MS; //20ms 计数值=65535/4000*t =
// processIndex=1;
// }break;
// case 1:
// {
// TurnOffAnalogCircuit();
// ComputeSampleData(16, 4);//计算样本数据
// sampleProcess.RHypeResult = sampleProcess.ADC0Result;//放入缓存
// sampleProcess.IRHResult = sampleProcess.ADC1Result;//放入缓存
// SetupBLChannle();//设置SIGNAL1
// SetupRDChannle();
// SetSystemForADCSample(16);
// processNextTime += 20 * COUNT_VALUE_PER_MS;//20ms
// processIndex=2;
// }break;
// case 2:
// {
// TurnOffAnalogCircuit();
// ComputeSampleData(16, 4);//计算样本数据; //计算样本数据
// sampleProcess.BLypeResult = sampleProcess.ADC0Result;//放入缓存
// sampleProcess.RDResult = sampleProcess.ADC1Result;//放入缓存
//
// HWState.SampledOver = 1; //采样结束
// StopProcessTimer();
// processIndex=3;
// }break;
// default : processIndex = 0; break;
// }
// SetNextProcess();
//}
void FlowProcessManagement(void)//采样过程管理状态机
{
switch(sampleProcess.NextRun)
{
case 0:
{
HWState.SampledOver = 0;//采样开始
SetupBLChannle();
SetupRDChannle();
SetSystemForADCSample(SAMPLING_TIMES_IN_DETECT_STAGE);//设置采样个数并开始采样
sampleProcess.NextTime = 20*COUNT_VALUE_PER_MS;
sampleProcess.NextRun = 1;
}break;
case 1:
{
TurnOffAnalogCircuit();
ComputeSampleData(SAMPLING_TIMES_IN_DETECT_STAGE, SHIFT_IN_DETECT_STAGE);
sampleProcess.BLypeResult = sampleProcess.ADC0Result;//放入缓存
sampleProcess.RDResult = sampleProcess.ADC1Result;//放入缓存
// SetupVRHChannle();//设置SIGNAL1
// SetSystemForADCSample(PRESAMPLING_TIMES_IN_1ST_STAGE);//设置采样个数并开始采样
// sampleProcess.NextTime = 20*COUNT_VALUE_PER_MS;//20ms
sampleProcess.NextRun = 3;
}break;
case 2:
{
TurnOffAnalogCircuit();
ComputeSampleData(PRESAMPLING_TIMES_IN_1ST_STAGE, SHIFT_IN_PRESAMPLING_1ST_STAGE);
}break;
case 3:
{
}break;
case 4:
{
}break;
case 5:
{
}break;
case 6:
{
}break;
default : sampleProcess.NextRun = 0; break;
}
SetNextProcess();
}
//******************************************************************************/
void CoreInit(void)
{
SystemGPIOInit();
// ExternCalibratinInput();
TurnOffAnalogCircuit();
}
//主程序中断------------------------------------------------------------
//void PrimaryTimer_IRQ_Callback()
//{
//// HWState.MainTimerOut = 1;
// StartNormolFlowMeasurement();
//}
void PrimaryTimer_IRQ_Callback()
{
HWState.MainTimerOut = 1;
// StartNormolFlowMeasurement();
}
/******显示部分***************************************************************************************************************************************************************************************************************/
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[RHVOL];
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闪烁计时的
void My_Timer2_Callback(void)//每10ms进一次中断
{
// LED 逻辑
led_timer++;
if(led_timer >= 10)
{
led_timer = 0;
TOGGLE_PIN(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;
if(HWState.MainTimerOut == 1 ) {
ManagePrimaryTimeInterval(); // 判断下阶段的工作模式
ModeExitCount(); // 判断各种模式退出
Clear_WDT();
StartNormolFlowMeasurement();
HWState.MainTimerOut = 0;
}
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
/****************************************************************************/