#include "includes.h"

// 采集次数
#define SAMPLE_COUNT	(20)

// 通过界面请求采集的标志
volatile uint8_t Config_Sample_Request = 0;
volatile uint8_t Config_Vacuum_Request = 0;
// 得到采集数据的通知
volatile uint8_t GPRS_semSampled = 0;

// 通知采集的信号量
SemaphoreHandle_t Sample_Semaphore = NULL;    // 二值信号量句柄
// 通知充装匹配的信号量
SemaphoreHandle_t Match_Semaphore = NULL;    // 二值信号量句柄

// 当前采集阶段
volatile uint8_t Sample_phase = 0;
// 采集是否忙
uint32_t Sample_Busy()
{
	return (Sample_phase != 0);
}

// 通知采集
void Sample_Notify()
{
	if(!Sample_Busy())
	{
		// 发送消息给任务
		xSemaphoreGive(Sample_Semaphore);
	}
}

// 通知采集
void Sample_NotifyFromISR()
{
	BaseType_t xHigherPriorityTaskWoken;

	if(!Sample_Busy())
	{
		// 发送消息给任务
		xSemaphoreGiveFromISR(Sample_Semaphore, &xHigherPriorityTaskWoken);
	}
}

// 处理泄露报警唤醒
void Leak_Handler(void)
{
	if(Wakeup_Sleeping)
	{
		SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);	
		delay_ms(10);
		
		Vcc_Enable();
		delay_ms(40);
		Wakeup_Sleeping = 0;

		printf("\n\nWake up by LEAK.\n\n");
	}

	// 采集数据
	Sample_NotifyFromISR();
}

// 采集一个通道：总共采集20次，取中间10次的平均值
uint32_t Sample_ChannelOne(uint32_t channel)
{
	uint32_t i;
	uint32_t adc[SAMPLE_COUNT];
	
	LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, channel);
	for(i = 0; i < SAMPLE_COUNT; i++)
	{
		LL_ADC_REG_StartConversion(ADC1);
		while(LL_ADC_REG_IsConversionOngoing(ADC1));	
		adc[i] = LL_ADC_REG_ReadConversionData12(ADC1);
	}
	
	sort(adc, SAMPLE_COUNT);
	adc[0] = 0;
	for(i = 0; i < (SAMPLE_COUNT / 2); i++)
		adc[0] += adc[SAMPLE_COUNT / 4 + i];
	
	i = adc[0] / (SAMPLE_COUNT / 2);
	printf("\nchannel %d adc: %d, volt: %dmV\n", channel, i, i * 3000 / 4095);
	return i;
}

void Sample_Init()
{
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  LL_EXTI_InitTypeDef EXTI_InitStruct = {0};

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
  /**ADC1 GPIO Configuration  
  PA0   ------> ADC1_IN5（AD5） 
  PA1   ------> ADC1_IN6 (AD6)
  PA5   ------> ADC1_IN10 (AD10)
  PA6   ------> ADC1_IN11 (AD11)
  PA7   ------> ADC1_IN12 (AD12)
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1
						|LL_GPIO_PIN_5|LL_GPIO_PIN_6|LL_GPIO_PIN_7;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
  /**ADC1 GPIO Configuration  
  PB0   ------> ADC1_IN15（AD_BAT)
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
  /**ADC1 GPIO Configuration  
  PC0   ------> ADC1_IN1（AD1)
  PC1   ------> ADC1_IN2（AD2)
  PC2   ------> ADC1_IN3（AD3)
  PC3   ------> ADC1_IN4（AD4)
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_3;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  // 泄露报警引脚
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);

  /**/
  LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTE, LL_SYSCFG_EXTI_LINE8);

  // 创建信号量
  if(Sample_Semaphore == NULL)
	Sample_Semaphore = xSemaphoreCreateBinary();
  if(Match_Semaphore == NULL)
	Match_Semaphore = xSemaphoreCreateBinary();

  /**/
  EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_8;
  EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
  EXTI_InitStruct.LineCommand = ENABLE;
  EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
  EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
  LL_EXTI_Init(&EXTI_InitStruct);

  /**/
  LL_GPIO_SetPinPull(GPIOE, LL_GPIO_PIN_8, LL_GPIO_PULL_DOWN);

  /**/
  LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_8, LL_GPIO_MODE_INPUT);
}

void Sample_Open()
{
	uint32_t vrefint_cal = *((volatile uint16_t *)(0x1fff75aa));
	
  LL_ADC_InitTypeDef ADC_InitStruct = {0};
  LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
  LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};

	// 设置传感器状态
	dcBuff.sampleData.vacuum[0].staVacuum = VACUUM_STATUS_COMM_FAULT;
	dcBuff.sampleData.leak.staLeak = LEAK_STATUS_COMM_FAULT;
  
  NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
  NVIC_EnableIRQ(EXTI9_5_IRQn);
  
  /* Peripheral clock enable */
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);
  
  /** Common config 
  */
  ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
  ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
  ADC_InitStruct.LowPowerMode = LL_ADC_LP_AUTOWAIT;
  LL_ADC_Init(ADC1, &ADC_InitStruct);
  ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
  ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
  ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
  ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
  ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
  ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
  LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
  LL_ADC_ConfigOverSamplingRatioShift(ADC1, LL_ADC_OVS_RATIO_16, LL_ADC_OVS_SHIFT_RIGHT_4);
  LL_ADC_SetOverSamplingDiscont(ADC1, LL_ADC_OVS_REG_CONT);
  LL_ADC_DisableIT_EOC(ADC1);
  LL_ADC_DisableIT_EOS(ADC1);
  LL_ADC_DisableDeepPowerDown(ADC1);
  LL_ADC_EnableInternalRegulator(ADC1);
  ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;
  LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
  /** Configure Regular Channel 
  */
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_2, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_2, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_3, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_4, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_4, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_5, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_5, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_11, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_11, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SINGLE_ENDED);	
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SAMPLINGTIME_24CYCLES_5);
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SINGLE_ENDED);	
  
  Sample_ReOpen();
}

// 休眠唤醒以后需重新执行该函数
void Sample_ReOpen()
{
	// ADC硬件校验
	VCC_SENSOR_5V_ON();
	delay_ms(50);
	LL_ADC_StartCalibration(ADC1, LL_ADC_SINGLE_ENDED);
	while(LL_ADC_IsCalibrationOnGoing(ADC1));
	VCC_SENSOR_5V_OFF();
}

void Sample_Task(void *p_arg)
{
	uint16_t adc1, adc2;
	data_dtu_t dtuSample;
	data_sample_t sample;
	uint32_t sample_time;
	// 每隔8小时测一次真空（上电第一次不测）
	uint32_t vacuum_seconds = 30, vaccuumTick = 0;
	uint8_t lastLeakWarning = 0;
	
	int16_t i;
	uint32_t u32Sample;
	static uint8_t charging = 0;			 // 记录充装状态
	static uint32_t lowest_Sample = 0xFFFFFFFFul; // 记录液位最低点：初值为最大（用于判断充装开始）
	static uint32_t highest_Sample = 0; 		// 记录液位最高点：初值为最小（用于判断充装结束）
	static uint8_t stopGrowCount = 0;	  		// 记录液位停止增长的次数
	static uint32_t last_SampleTime = 0; // 记录充装判别的时间（间隔时间不能过短）
	uint32_t totalSeconds;
	static uint32_t last_volumePct = 0;		 // 记录上次的液位
	static uint16_t	last_Press = 0;
	static int16_t	last_Tempr = -300;
	static uint16_t last_Vacuum = 0;
	S_RTC_TIME_DATA_T sRTC;

	// TTS协议
	static uint32_t last_spanPct[20] = {0};		// 记录上次变化量的百分比基数
	static uint32_t last_spanTime[20] = {0};	// 记录上次变化量的时间基数
	static uint8_t last_spanCount = 0;			// 记录条数
	uint32_t span;
	
	static uint32_t Match_Time = 0;
	
	static uint8_t first = 1;

	uint16_t adDPress_inhibition;			// 4~20mA输入差压采集抑制量
	static uint16_t last_adDPress = 0;		// 记录上一个差压采集值

	// 和远气体：紧急切断阀门的输出: 电磁阀默认打开
	if(dcBuff.powerInfo.hardVer.major == 231)
		KZ_VALUE_ENABLE();
	
	while(1)
	{
		// 等待采集信号
		xSemaphoreTake(Sample_Semaphore, portMAX_DELAY);

		// 4~20mA输入差压采集抑制量：当前采集值和上一个采集值相差满量程的±6‰范围内，用上一个采集值代替当前值
		adDPress_inhibition = (dcBuff.configSensor.sensorDPress.fullValue - dcBuff.configSensor.sensorDPress.zeroValue) / 166;
		
		// 下一阶段：采集传感器数据
		Sample_phase = 1;

		// 获取当前时间
		RTC_GetDateAndTime(&sRTC);
		// 计算自上次gps定位以来的时间
		sample_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
				sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

		// 初始化缓冲区
		memset(&sample, 0, sizeof(sample));
		memset(&dtuSample, 0, sizeof(dtuSample));
		
		// 设置传感器状态
		sample.staExtPress[0].status = SENSOR_STATUS_NOCONNECT;
		sample.staExtPress[1].status = SENSOR_STATUS_NOCONNECT;
		sample.staExtPress[2].status = SENSOR_STATUS_NOCONNECT;
		sample.staExtTempr[0].status = SENSOR_STATUS_NOCONNECT;
		sample.staExtTempr[1].status = SENSOR_STATUS_NOCONNECT;
		sample.staExtTempr[2].status = SENSOR_STATUS_NOCONNECT;
		// Modbus传感器默认为沿用原来的数据
		sample.vacuum[0] = dcBuff.sampleData.vacuum[0];
		sample.leak = dcBuff.sampleData.leak;
		sample.flow = dcBuff.sampleData.flow;
		
		// 计算理论值
		Calculate_Theoretical_Params();

		if(!IS_VCC_SENSOR_5V_ON())
		{
			// 用于采集真空计的延时
			vaccuumTick = GetDelayTick(15000);

			VCC_SENSOR_5V_ON();
			// 延时1s以后进入采集阶段
			osDelay(1000);
			if(dcBuff.configDisplay.op_USE_R0SEMOUNT) // 罗斯蒙特传感器，额外延时
				osDelay(5000);
		}
		
		// 允许ADC
		LL_ADC_Enable(ADC1);
		while(!LL_ADC_IsActiveFlag_ADRDY(ADC1));
		osDelay(10);
		
		// 采集差压通道
		if(!dcBuff.configDisplay.op_DIFF_420MA)
			sample.adDPress = Sample_ChannelOne(LL_ADC_CHANNEL_5);
		else
		{
			sample.adDPress = Sample_ChannelOne(LL_ADC_CHANNEL_10);
			// 非标定采集，抑制跳动
			if(!Config_Sample_Request)
			{
				if(last_adDPress > 0 && 
					(sample.adDPress + adDPress_inhibition >= last_adDPress && sample.adDPress <= last_adDPress + adDPress_inhibition))
				{
					// 用上一个值代替当前值
					sample.adDPress = last_adDPress;
				}
				else
				{
					// 以当前值作为比较基准
					last_adDPress = sample.adDPress;
				}
			}
		}
		if(!dcBuff.configDisplay.op_USE_CAPACITY_SENSOR)
		{
			// 差压值
			sample.staDPress.status = ADC_Validate(sample.adDPress, 
						dcBuff.configSensor.sensorDPress.zeroValue, dcBuff.configSensor.sensorDPress.fullValue);
			if(sample.staDPress.status == SENSOR_STATUS_NORMAL)
			{
				sample.diff = ADC_Calculate(sample.adDPress, 
						dcBuff.configSensor.sensorDPress.zeroValue, dcBuff.configSensor.sensorDPress.fullValue,
						dcBuff.configSensor.sensorDPress.lowRange, dcBuff.configSensor.sensorDPress.highRangeX10)
						* (dcBuff.configSensor.sensorDPress.ishighRangeX10 ? 0.1 : 1);
			}
		}

		// 采集压力通道
		if(!dcBuff.configDisplay.op_PRESS_420MA)
			sample.adPress = Sample_ChannelOne(LL_ADC_CHANNEL_6);
		else
			sample.adPress = Sample_ChannelOne(LL_ADC_CHANNEL_11);
		sample.staPress.status = ADC_Validate(sample.adPress, 
					dcBuff.configSensor.sensorPress.zeroValue, dcBuff.configSensor.sensorPress.fullValue);		
		if(sample.staPress.status == SENSOR_STATUS_NORMAL)
		{
			sample.pressure = ADC_Calculate(sample.adPress, 
					dcBuff.configSensor.sensorPress.zeroValue, dcBuff.configSensor.sensorPress.fullValue,
					dcBuff.configSensor.sensorPress.lowRange, dcBuff.configSensor.sensorPress.highRange);
		}

		// 扩展压力通道
		if(!dcBuff.configDisplay.op_PRESS_420MA)
			sample.adExtPress[0] = Sample_ChannelOne(LL_ADC_CHANNEL_11);
		else
			sample.adExtPress[0] = Sample_ChannelOne(LL_ADC_CHANNEL_6);
		sample.staExtPress[0].status = ADC_Validate(sample.adExtPress[0], 
					dcBuff.configSensor.sensorEPress[0].zeroValue, dcBuff.configSensor.sensorEPress[0].fullValue);		
		if(sample.staExtPress[0].status == SENSOR_STATUS_NORMAL)
		{
			sample.extPressure[0] = ADC_Calculate(sample.adExtPress[0], 
					dcBuff.configSensor.sensorEPress[0].zeroValue, dcBuff.configSensor.sensorEPress[0].fullValue,
					dcBuff.configSensor.sensorEPress[0].lowRange, dcBuff.configSensor.sensorEPress[0].highRange);
		}
		
		if(dcBuff.configDisplay.op_USE_PT100_SENSOR)
		{
			// 采集温度1
			adc1 = Sample_ChannelOne(LL_ADC_CHANNEL_1);
			adc2 = Sample_ChannelOne(LL_ADC_CHANNEL_2);
			sample.adExtTempr[0] = PT100_CalResit(adc1, adc2);
			if(dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY)
				sample.staExtTempr[0].status = SENSOR_STATUS_NOCONNECT;
			else
				sample.staExtTempr[0].status = ADC_Validate(sample.adExtTempr[0], 
						PT100_Resis[0] * dcBuff.configDisplay.op_PT100_MULTI, PT100_Resis[sizeof(PT100_Resis) / sizeof(float) - 1] * dcBuff.configDisplay.op_PT100_MULTI);
			if(sample.staExtTempr[0].status == SENSOR_STATUS_NORMAL)
			{
				sample.extTempr[0] = PT100_CalTempr(adc1, adc2,
					dcBuff.configSensor.sensorPTempr[0].calibrateT, dcBuff.configSensor.sensorPTempr[0].calibrateR);
			}
		}
		else
		{
			// 采集温度1
			sample.adExtTempr[0] = Sample_ChannelOne(LL_ADC_CHANNEL_12);
			sample.staExtTempr[0].status = ADC_Validate(sample.adExtTempr[0], 
						dcBuff.configSensor.sensorMTempr[0].zeroValue, dcBuff.configSensor.sensorMTempr[0].fullValue);		
			if(sample.staExtTempr[0].status == SENSOR_STATUS_NORMAL)
			{
				sample.extTempr[0] = ADC_Calculate(sample.adExtTempr[0], 
						dcBuff.configSensor.sensorMTempr[0].zeroValue, dcBuff.configSensor.sensorMTempr[0].fullValue,
						dcBuff.configSensor.sensorMTempr[0].lowRange, dcBuff.configSensor.sensorMTempr[0].highRange);
			}
		}

		// 采集温度2
		adc1 = Sample_ChannelOne(LL_ADC_CHANNEL_3);
		adc2 = Sample_ChannelOne(LL_ADC_CHANNEL_4);
		sample.adExtTempr[1] = PT100_CalResit(adc1, adc2);
		if(dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY)
			sample.staExtTempr[1].status = SENSOR_STATUS_NOCONNECT;
		else
			sample.staExtTempr[1].status = ADC_Validate(sample.adExtTempr[1], 
					PT100_Resis[0] * dcBuff.configDisplay.op_PT100_MULTI, PT100_Resis[sizeof(PT100_Resis) / sizeof(float) - 1] * dcBuff.configDisplay.op_PT100_MULTI);
		if(sample.staExtTempr[1].status == SENSOR_STATUS_NORMAL)
		{
			sample.extTempr[1] = PT100_CalTempr(adc1, adc2,
				dcBuff.configSensor.sensorPTempr[1].calibrateT, dcBuff.configSensor.sensorPTempr[1].calibrateR);
		}
		
		// 采集电池电压通道
		// 为了避免ADC模块的使用冲突，测量电压和传感器采样在一起执行
		// 因称重传感器未用，故将电池电压的adc值存放在称重传感器的位置
		sample.adWeight = Sample_ChannelOne(LL_ADC_CHANNEL_15);
				
		if(dcBuff.configDisplay.op_USE_O2_LEAK)
		{
			if(VCC_POWER_STATUS())
			{
				// 读取O2浓度传感器
				Sensor_ReadLeakO2(&sample);		
				while(!IsTickOut(modbus_outTick))
					osDelay(1);
			}
		}
		else
		{
			// 读取泄露报警
			sample.leak.typeLeak = LEAK_TYPE_SWITCH;
			if(VCC_LEAK_STATUS())
			{
				sample.leak.staLeak = LEAK_STATUS_A2_ALARM;
				sample.leak.concentrations = 1;
			}
			else
			{
				sample.leak.staLeak = LEAK_STATUS_OK;
				sample.leak.concentrations = 0;
				// 重启泄露报警
				Leak_Alarm_Enabled = 1;			
			}
		}

		if(VCC_POWER_STATUS())
		{
			// Modbus采集流量计
			Sensor_ReadFlow(&sample);		
			while(!IsTickOut(modbus_outTick))
				osDelay(1);
		}
		
		// 是否到采集时间（3秒误差）
		if(Config_Vacuum_Request || sample_time + 3 >= vacuum_seconds)
		{
			if(Config_Vacuum_Request)
			{
				// 强制采集真空计
				Config_Vacuum_Request = 0;
			}
			else
			{
				// 下次上传时再采
				vacuum_seconds = sample_time + dcBuff.configData.intervalTrans;
			}
			
			// 真空计需要额外延时
			while(vaccuumTick > 0 && !IsTickOut(vaccuumTick))
				osDelay(1);
			// 如果不断电，下次采集真空计不用延时
			vaccuumTick = 0;
			
			// 读取真空数据
			Sensor_ReadVacuum(0, &sample);
			while(!IsTickOut(modbus_outTick))
				osDelay(1);
			if(sample.vacuum[0].staVacuum == VACUUM_STATUS_COMM_FAULT)
			{
				Sensor_ReadVacuum(0, &sample);
				while(!IsTickOut(modbus_outTick))
					osDelay(1);
			}
			if(sample.vacuum[0].staVacuum == VACUUM_STATUS_COMM_FAULT)
			{
				Sensor_ReadVacuum(0, &sample);
				while(!IsTickOut(modbus_outTick))
					osDelay(1);
			}
		}
		
		// 无外部供电，或者太阳能电池电压低于4.5v
		if((!dcBuff.configDisplay.op_LOCAL_DISP_1S && !dcBuff.configDisplay.op_USE_R0SEMOUNT) || !VCC_POWER_STATUS() || (dcBuff.configDisplay.op_USE_SOLAR && dcBuff.dtuData.batVoltage <= 4500)) 
			VCC_SENSOR_5V_OFF();
		
		// 电容传感器
		if(dcBuff.configDisplay.op_USE_CAPACITY_SENSOR && sample.staDPress.status != SENSOR_STATUS_NOCONNECT)
		{
			if(sample.adDPress == 0xFFFF) // 短路
				sample.staDPress.status = SENSOR_STATUS_OVERFLOW;
			else
			{
				// 根据底电容、增长电容判断状态
				sample.staDPress.status = ADC_Validate(sample.diff * 10, 
						dcBuff.configSensor.sensorCap.baseC, dcBuff.configSensor.sensorCap.baseC + dcBuff.configSensor.sensorCap.refC);
			}
		}		
			
		// 总容积
		sample.volumeTotal = Theoretical_Param.v;
				
		if(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL)
		{
			if(!dcBuff.configDisplay.op_USE_CAPACITY_SENSOR)
			{					
				// 液位
				if(!dcBuff.configDisplay.op_USE_HEIGHT_LEVEL && !dcBuff.configDisplay.op_USE_PCT_LEVEL)
					sample.height = Diff2Level(sample.diff); // 单位mm
				else if(!dcBuff.configDisplay.op_USE_PCT_LEVEL)
					sample.height = sample.diff;			   // 直接测量液位高度，单位mm
				else
					sample.height = sample.diff * 100;	  // 直接测量液位百分比：单位0.01%
			}
			else
			{
				// 根据底电容、增长电容计算液位高度
				sample.height = Cap_Calculate(sample.diff * 10, 
						dcBuff.configSensor.sensorCap.baseC, dcBuff.configSensor.sensorCap.refC);
			}

			if(!dcBuff.configDisplay.op_USE_PCT_LEVEL && dcBuff.configSensor.levelOutMMWC == 0)
			{
				// 体积
				sample.volume = Level2Vol(sample.height);
				// 质量
				sample.weight = Vol2Quantity(sample.volume);
				// 充装比
				if(sample.volume >= Theoretical_Param.ve)
					sample.volumePct = dcBuff.configBottle.chargePct * 100;
				else
					sample.volumePct = (float) sample.volume / sample.volumeTotal * 10000;
			}
			else
			{
				if(dcBuff.configSensor.levelOutMMWC > 0)
				{
					// 充装比
					if(KPa2mmH2O(sample.diff) >= dcBuff.configSensor.levelOutMMWC)
						sample.volumePct = dcBuff.configBottle.chargePct * 100;
					else
						sample.volumePct = KPa2mmH2O(sample.diff) / dcBuff.configSensor.levelOutMMWC * 10000;
				}
				else
				{
					// 充装比
					if(sample.diff >= dcBuff.configBottle.chargePct)
						sample.volumePct = dcBuff.configBottle.chargePct * 100;
					else
						sample.volumePct = sample.diff * 100;
				}
				// 体积
				sample.volume = Theoretical_Param.ve * (sample.volumePct / 10000.0);
				// 质量
				sample.weight = Vol2Quantity(sample.volume);
			}
		}
		
		// 防过充输出
		if(dcBuff.configDisplay.op_ANTI_OVERFILL)
		{
			if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
				(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
			{
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct >= dcBuff.configBottle.fullPct)
					Charge_Enabled = 0;

				// 任何情况下，防过充始终有效
				if(Charge_Enabled != last_Charge_Enabled)
				{
					Charge_Pulse_Time = GetDelayTick(1000);
					if(Charge_Enabled)
						KZ_CHARGE_ENABLE_HIGH();
					else
					{
						if(dcBuff.configDisplay.op_ANTI_SINGLE_CTRL)
							KZ_CHARGE_ENABLE_LOW();
						else
							KZ_CHARGE_DISABLE_HIGH();
					}
				}
				// 保存当前充装允许状态
				last_Charge_Enabled = Charge_Enabled;
			}
		}
		
		// 常开电磁阀防过充输出（气动关闭）
		if(dcBuff.configDisplay.op_ANTI_NORM_OPEN)
		{
			if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
				(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
			{
				// 当液位降到满液位之下10%，重启防过充检测
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct < dcBuff.configBottle.fullPct - 10 * 100)
					Anti_Enabled = 1;
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct >= dcBuff.configBottle.fullPct)
				{
					if(Anti_Enabled)
					{
						// 气动泵关闭300秒
						KZ_NORM_OPEN_DISABLE();
						Anti_Pulse_Time = GetDelayTick(300000ul);
						// 不再重复检测
						Anti_Enabled = 0;
					}
				}
			}
		}
		
		// 声光报警输出
		if(dcBuff.configDisplay.op_ALARM_OUTPUT)
		{
			if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
				(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
			{
				// 当液位降到满液位之下10%，重启声光报警检测
				// 当液位高于满液位之下10%，声光报警状态不变（一直报警状态 或 手动关闭状态）
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct < dcBuff.configBottle.fullPct - 10 * 100)
					Alarm_Enabled = 1;
				// 当液位高于满液位，且未手动关闭，则打开报警
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct >= dcBuff.configBottle.fullPct)
				{
					if(Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
					{
						KZ_ALARM_ON();
						ALARM_ON();
						sample.warnning = 1;
						Alarm_Output = 1;
						Alarm_Enabled = 0;
					}
				}
			}
		}

		// 泄露报警的输出
		if(dcBuff.configDisplay.op_LEAK_ALARM_OUTPUT)
		{
			if(VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500)
				&& sample.leak.staLeak == LEAK_STATUS_A2_ALARM)
			{
				if(Leak_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
				{
					KZ_ALARM_ON();ALARM_ON();
					sample.warnning = 1;
					Leak_Alarm_Output = 1;
				}
			}
		}
		
		// 强制低液位报警输出
		if(dcBuff.configDisplay.op_LOW_ALARM_OUTPUT)
		{
			if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
					(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
			{
				// 当液位升到空液位之上10%，重启低液位输出指示
				// 当液位低于空液位之上10%，低液位指示状态不变（一直报警状态 或 手动关闭状态）
				if(dcBuff.configBottle.emptyPct > 0 && sample.volumePct >= dcBuff.configBottle.emptyPct + 10 * 100)
					Low_Alarm_Enabled = 1;

				// 当液位低于空液位，且未手动关闭，则打开报警
				if(dcBuff.configBottle.emptyPct > 0 && sample.volumePct <= dcBuff.configBottle.emptyPct)
				{
					if(Low_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
					{
						KZ_ALARM_ON();ALARM_ON();
						sample.warnning = 1;
						Low_Alarm_Output = 1;
						Low_Alarm_Enabled = 0;
					}
				}
			}
		}
		
		// 默认低液位报警输出
		if(!dcBuff.configDisplay.op_ALARM_OUTPUT && !dcBuff.configDisplay.op_LEAK_ALARM_OUTPUT && !dcBuff.configDisplay.op_LOW_ALARM_OUTPUT)
		{
			// 检查是否满足输出条件: 有外供电且测量值正常
			if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
					(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
			{
				// 当液位升到空液位之上10%，重启低液位输出指示
				// 当液位低于空液位之上10%，低液位指示状态不变
				if(dcBuff.configBottle.emptyPct > 0 && sample.volumePct >= dcBuff.configBottle.emptyPct + 10 * 100)
					KZ_LOW_ALARM_OFF();
				if(dcBuff.configBottle.emptyPct > 0 && sample.volumePct <= dcBuff.configBottle.emptyPct)
				{
					if(VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
						KZ_LOW_ALARM_ON();
					sample.warnning = 1;
				}
			}
		}

		// 高压力报警
		if(dcBuff.configDisplay.op_PRESS_ALARM_OUTPUT)
		{
			if(sample.staPress.status == SENSOR_STATUS_NORMAL)
			{
				// 当压力降到报警值之下0.05Mpa，重启高压力输出指示
				// 当压力高于报警值之下0.05Mpa，高压力指示状态不变（一直报警状态 或 手动关闭状态）
				if(dcBuff.configBottle.warnPressH > 0 && sample.pressure + 50 <= dcBuff.configBottle.warnPressH)
					Press_Alarm_Enabled = 1;
		
				// 当压力高于报警值，且未手动关闭，则打开报警
				if(dcBuff.configBottle.warnPressH > 0 && sample.pressure >= dcBuff.configBottle.warnPressH)
				{
					if(Press_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
					{
						KZ_ALARM_ON();ALARM_ON();
						sample.warnning = 1;
						Press_Alarm_Output = 1;
						Press_Alarm_Enabled = 0;
					}
				}	
			}
			
			if(sample.staExtPress[0].status == SENSOR_STATUS_NORMAL)
			{
				// 当压力降到报警值之下0.05Mpa，重启高压力输出指示
				// 当压力高于报警值之下0.05Mpa，高压力指示状态不变（一直报警状态 或 手动关闭状态）
				if(dcBuff.configBottle.warnPressH2 > 0 && sample.extPressure[0] + 50 <= dcBuff.configBottle.warnPressH2)
					ExtPress_Alarm_Enabled = 1;
			
				// 当压力高于报警值，且未手动关闭，则打开报警
				if(dcBuff.configBottle.warnPressH2 > 0 && sample.extPressure[0] >= dcBuff.configBottle.warnPressH2)
				{
					if(ExtPress_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
					{
						KZ_ALARM_ON();ALARM_ON();
						sample.warnning = 1;
						ExtPress_Alarm_Output = 1;
						ExtPress_Alarm_Enabled = 0;
					}
				}	
			}
			
		}

		// 低压力报警
		if(dcBuff.configDisplay.op_LOW_PRESS_ALARM_OUTPUT)
		{
			if(sample.staPress.status == SENSOR_STATUS_NORMAL)
			{
				// 当压力升到报警值之上0.05Mpa，重启低压力输出指示
				// 当压力低于报警值之上0.05Mpa，低压力指示状态不变（一直报警状态 或 手动关闭状态）
				if(dcBuff.configBottle.warnPress > 0 && sample.pressure >= dcBuff.configBottle.warnPress + 50)
					Low_Press_Alarm_Enabled = 1;		

				// 当压力低于报警值，且未手动关闭，则打开报警
				if(dcBuff.configBottle.warnPress > 0 && sample.pressure <= dcBuff.configBottle.warnPress)
				{
					if(Low_Press_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
					{
						KZ_ALARM_ON();ALARM_ON();
						sample.warnning = 1;
						Low_Press_Alarm_Output = 1;
						Low_Press_Alarm_Enabled = 0;
					}
				}
			}
			if(sample.staExtPress[0].status == SENSOR_STATUS_NORMAL)
			{
				// 当压力升到报警值之上0.05Mpa，重启低压力输出指示
				// 当压力低于报警值之上0.05Mpa，低压力指示状态不变（一直报警状态 或 手动关闭状态）
				if(dcBuff.configBottle.warnPress2 > 0 && sample.extPressure[0] >= dcBuff.configBottle.warnPress2 + 50)
					Low_ExtPress_Alarm_Enabled = 1;
	

				// 当压力低于报警值，且未手动关闭，则打开报警
				if(dcBuff.configBottle.warnPress2 > 0 && sample.extPressure[0] <= dcBuff.configBottle.warnPress2)
				{
					if(Low_ExtPress_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
					{
						KZ_ALARM_ON();ALARM_ON();
						sample.warnning = 1;
						Low_ExtPress_Alarm_Output = 1;
						Low_ExtPress_Alarm_Enabled= 0;
					}
				}
			}
		}

		
			uint8_t out=0;
			if((Press_Alarm_Output == 1)&&(Press_Alarm_Enabled == 0)) out++;
      if((ExtPress_Alarm_Output == 1)&&(ExtPress_Alarm_Enabled == 0)) out++;
			if((Low_Press_Alarm_Output == 1)&&(Low_Press_Alarm_Enabled == 0)) out++;
			if((Low_ExtPress_Alarm_Output == 1)&&(Low_ExtPress_Alarm_Enabled == 0)) out++;	
			if((Low_Alarm_Output == 1)&&(Low_Alarm_Enabled == 0)) out++;
			if((Alarm_Output == 1)&&(Alarm_Enabled == 0)) out++;	
		
		if(0==out)
		{
			KZ_ALARM_OFF();
			KZ_LOW_ALARM_OFF();ALARM_OFF();
			sample.warnning = 0;
		
		}
	
//		// 双压力报警版本
//		//if(dcBuff.powerInfo.hardVer.major == 232)
//		{
//			if(sample.staExtPress[0].status == SENSOR_STATUS_NORMAL)
//			{
//				// 当压力降到报警值之下0.05Mpa，重启高压力输出指示
//				// 当压力高于报警值之下0.05Mpa，高压力指示状态不变（一直报警状态 或 手动关闭状态）
//				if(sample.extPressure[0] + 50 <= 2500)
//					ExtPress_Alarm_Enabled = 1;

//				// 当压力高于报警值，且未手动关闭，则打开报警
//				if(sample.extPressure[0] >= 2500)
//				{
//					if(ExtPress_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
//					{
//						KZ_ALARM_ON();
//						ExtPress_Alarm_Output = 1;
//					}
//				}

//				// 当压力升到报警值之上0.05Mpa，重启低压力输出指示
//				// 当压力低于报警值之上0.05Mpa，低压力指示状态不变（一直报警状态 或 手动关闭状态）
//				if(sample.extPressure[0] >= 100 + 50)
//					Low_ExtPress_Alarm_Enabled = 1;

//				// 当压力低于报警值，且未手动关闭，则打开报警
//				if(sample.extPressure[0] <= 100)
//				{
//					if(Low_ExtPress_Alarm_Enabled && VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
//					{
//						KZ_ALARM_ON();
//						Low_ExtPress_Alarm_Output = 1;
//					}
//				}
//			}
//		}

		// 无外供电，不输出声光报警，恢复到初始状态
		if(!VCC_POWER_STATUS() && (dcBuff.configDisplay.op_USE_SOLAR && dcBuff.dtuData.batVoltage <= 4500))
		{
			KZ_ALARM_OFF();ALARM_OFF();
			KZ_LOW_ALARM_OFF();
			
			Alarm_Output = 0;
			Low_Alarm_Output = 0;
			Leak_Alarm_Output = 0;
			
			Press_Alarm_Output = 0;
			Low_Press_Alarm_Output = 0;
			ExtPress_Alarm_Output = 0;
			Low_ExtPress_Alarm_Output = 0;
		
			Alarm_Enabled = 1;
			Low_Alarm_Enabled = 1;
			Leak_Alarm_Enabled = 1;
			Press_Alarm_Enabled = 1;
			Low_Press_Alarm_Enabled = 1;
			ExtPress_Alarm_Enabled = 1;
			Low_ExtPress_Alarm_Enabled = 1;
		}
			
//		// 低液位指示输出
//		// 检查是否满足输出条件: 有外供电且测量值正常
//		if(VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500)
//			&& dcBuff.configBottle.emptyPct > 0
//			&& ((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
//				(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL)))
//		{
//			// 当液位升到空液位之上10%，重启低液位输出指示
//			// 当液位低于空液位之上10%，低液位指示状态不变
//			if(sample.volumePct >= dcBuff.configBottle.emptyPct + 10 * 100)
//				KZ_LOW_LEVEL_OFF();
//			if(sample.volumePct <= dcBuff.configBottle.emptyPct)
//				KZ_LOW_LEVEL_ON();
//		}
//		else  // 不能输出指示，恢复到初始状态
//			KZ_LOW_LEVEL_OFF();

//		// 高液位指示输出
//		// 检查是否满足输出条件: 有外供电且测量值正常
//		if(VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500)
//			&& dcBuff.configBottle.fullPct > 0
//			&& ((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
//				(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL)))
//		{
//			// 当液位降到满液位之下10%，重启高液位输出指示
//			// 当液位高于满液位之下10%，高液位指示状态不变
//			if(sample.volumePct <= dcBuff.configBottle.fullPct - 10 * 100)
//				KZ_LEVEL_OFF();
//			if(sample.volumePct >= dcBuff.configBottle.fullPct)
//				KZ_LEVEL_ON();
//		}
//		else  // 不能输出指示，恢复到初始状态
//			KZ_LEVEL_OFF();
		
		// 和远气体：紧急切断阀门的输出
		if(dcBuff.powerInfo.hardVer.major == 231)
		{
			if(VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500)
				&& sample.leak.staLeak != LEAK_STATUS_COMM_FAULT && sample.leak.staLeak != LEAK_STATUS_FAULT
				&& sample.staExtTempr[0].status == SENSOR_STATUS_NORMAL)
			{
				if(sample.leak.staLeak == LEAK_STATUS_A2_ALARM || sample.extTempr[0] <= -35)
					KZ_VALUE_DISABLE();
				else if(sample.leak.staLeak == LEAK_STATUS_OK && sample.extTempr[0] >= -30)
					KZ_VALUE_ENABLE();
			}
			else if(!VCC_POWER_STATUS() || (dcBuff.configDisplay.op_USE_SOLAR && dcBuff.dtuData.batVoltage <= 4500))
				KZ_VALUE_DISABLE();
		}
		
		if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL)
			|| (dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
		{
			// 不设置储罐参数：以mmWC作为报警门限的单位
			if(dcBuff.configDisplay.op_DISP_MMWC_ONLY && !dcBuff.configDisplay.op_USE_PCT_LEVEL)
			{
				if(!dcBuff.configDisplay.op_USE_CAPACITY_SENSOR && !dcBuff.configDisplay.op_USE_HEIGHT_LEVEL)
					u32Sample = (uint32_t) KPa2mmH2O(sample.diff);
				else
					u32Sample = (uint32_t) sample.height;
			}
			else  // 以液量百分比作为报警门限的单位
				u32Sample = sample.volumePct;

				// 判别液位报警点
			if(dcBuff.configBottle.fullPct > 0 && 
				last_volumePct < dcBuff.configBottle.fullPct && u32Sample >= dcBuff.configBottle.fullPct)
				sample.warnning = 1;
			if(dcBuff.configBottle.priPct > 0 && 
				last_volumePct > dcBuff.configBottle.priPct && u32Sample <= dcBuff.configBottle.priPct)
				sample.warnning = 1;
			if(dcBuff.configBottle.orderPct > 0 && 
				last_volumePct > dcBuff.configBottle.orderPct && u32Sample <= dcBuff.configBottle.orderPct)
				sample.warnning = 1;
			if(dcBuff.configBottle.emptyPct > 0 && 
				last_volumePct > dcBuff.configBottle.emptyPct && u32Sample <= dcBuff.configBottle.emptyPct)
				sample.warnning = 1;

//			// TTS, 判别液位低点
//			if(dcBuff.configBottle.serverVer == 3)
//			{
//				// 液位低点
//				if(dcBuff.configBottle.floorLevel > 0 && 
//					last_volumePct > dcBuff.configBottle.floorLevel && u32Sample <= dcBuff.configBottle.floorLevel)
//					sample.warnning = 1;
//			}
			
			// 记录上次采集的值
			last_volumePct = u32Sample;

			// 判别充装状态
			RTC_GetDateAndTime(&sRTC);
			totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, 
						sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

			if(last_SampleTime == 0 || totalSeconds + 3 >= last_SampleTime + 300)
			{
				if(dcBuff.configBottle.measureType == MEASURE_WEIGHT)
					u32Sample = sample.weight;
				else if(!dcBuff.configDisplay.op_USE_CAPACITY_SENSOR && !dcBuff.configDisplay.op_USE_HEIGHT_LEVEL && !dcBuff.configDisplay.op_USE_PCT_LEVEL)
					u32Sample = (uint32_t) KPa2mmH2O(sample.diff);
				else
					u32Sample = (uint32_t) sample.height;
				
				if(!dcBuff.configDisplay.op_BOX_VER)
				{
					// 如果液位高于历史最低点+60mmWC/kg，开始充装并计时
					if(!charging)
					{
						// 记录液位最低点
						if(u32Sample < lowest_Sample)
							lowest_Sample = u32Sample;
						if(u32Sample >= lowest_Sample + 120)
						{
							charging = 1;
							Wakeup_SetAlarm(1);
							sample.warnning = 1;
							stopGrowCount = 0;
							highest_Sample = u32Sample;	// 重置液位最高点初值

							printf("\n*** Charging warnning ***\n");
						}
					}
					else
					{
						// 记录液位最高点
						if(u32Sample > highest_Sample)
						{
							stopGrowCount = 0;
							highest_Sample = u32Sample;
						}
						// 如果液位不高于最高液位
						if(u32Sample <= highest_Sample)
						{
							stopGrowCount++;
							if(stopGrowCount >= 3)
							{
								charging = 0;
								sample.warnning = 1;
								lowest_Sample = u32Sample;	// 重置液位最低点初值

								printf("\n*** Stop charging warnning ***\n");
							}
						}
					}
				}
				
				// TTS, 判别变化量报警
				if(dcBuff.configBottle.serverVer == 3)
				{
					// 一段时间内的变化量
					if(dcBuff.configBottle.span > 0)	// 变化量参数有效
					{
						for(i = 0; i < last_spanCount; i++)
						{
							if(totalSeconds <= last_spanTime[i] + dcBuff.configBottle.spanPeriod)
							{
								if(sample.volumePct >= last_spanPct[i])
									span = sample.volumePct - last_spanPct[i];
								else
									span = last_spanPct[i] - sample.volumePct;
								if(span >= dcBuff.configBottle.span * 100)
								{
									sample.warnning = 1;
									break;
								}
							}						
						}
					}
					if(last_spanCount >= 20)
					{
						for(i = 0; i < last_spanCount - 1; i++)
						{
							last_spanPct[i] = last_spanPct[i + 1];
							last_spanTime[i] = last_spanTime[i + 1];
						}
						last_spanCount--;
					}
					last_spanPct[last_spanCount] = sample.volumePct;
					last_spanTime[last_spanCount] = totalSeconds;
					last_spanCount++;
				}
						
				// 记录判断时间
				last_SampleTime = totalSeconds;
			}

			if(sample.warnning)
				printf("\n*** Level warnning ***\n");
			
			// 设置充装标志
			sample.charging = charging;
		}

//		// 判断是否压力报警
//		if(!dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY)
//		{
//			if(sample.staPress.status == SENSOR_STATUS_NORMAL)
//			{
//				if(dcBuff.configBottle.warnPress > 0 && last_Press > dcBuff.configBottle.warnPress && sample.pressure <= dcBuff.configBottle.warnPress)
//					sample.warnning = 1;
//				if(dcBuff.configBottle.warnPressH > 0 && last_Press < dcBuff.configBottle.warnPressH && sample.pressure >= dcBuff.configBottle.warnPressH)
//					sample.warnning = 1;

//				// 记录采集值
//				last_Press = sample.pressure;
//			}
//		}

//		// 判断是否温度报警
//		if(dcBuff.configBottle.serverVer != 3 && !dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY)
//		{
//			if(sample.staExtTempr[0].status == SENSOR_STATUS_NORMAL)
//			{
//				if(dcBuff.configBottle.warnTempr > -300 && last_Tempr > dcBuff.configBottle.warnTempr && sample.extTempr[0] <= dcBuff.configBottle.warnTempr)
//					sample.warnning = 1;
//				if(dcBuff.configBottle.warnTemprH > -300 && last_Tempr < dcBuff.configBottle.warnTemprH && sample.extTempr[0] >= dcBuff.configBottle.warnTemprH)
//					sample.warnning = 1;
//				
//				// 记录采集值
//				last_Tempr = sample.extTempr[0];
//			}
//		}

//		// 判断是否真空度报警
//		if(dcBuff.configBottle.serverVer != 3 && sample.vacuum[0].staVacuum == VACUUM_STATUS_OK)
//		{
//			if(dcBuff.configBottle.warnVacuumH > 0 && last_Vacuum < dcBuff.configBottle.warnVacuumH * 0.01 && sample.vacuum[0].vacuum >= dcBuff.configBottle.warnVacuumH * 0.01)
//				sample.warnning = 1;
//			
//			// 记录采集值
//			last_Vacuum = sample.vacuum[0].vacuum;
//		}

		// 槽车防过充匹配
		if(!dcBuff.configDisplay.op_SEND_GPS_DATA && !dcBuff.configDisplay.op_BOX_VER && RF_initStatus && (charging || Manual_Charing))
		{
			if((dcBuff.configBottle.measureType == MEASURE_WEIGHT && sample.staWeight.status == SENSOR_STATUS_NORMAL) ||
				(dcBuff.configBottle.measureType == MEASURE_DPRESS && sample.staDPress.status == SENSOR_STATUS_NORMAL))
			{
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct >= dcBuff.configBottle.fullPct)
					Match_Charging = 0;
				if(dcBuff.configBottle.fullPct > 0 && sample.volumePct < dcBuff.configBottle.fullPct - 10 * 100)
					Match_Charging = 1;

				if((Match_Charging == 0 && (!Truck_Matched || Truck_Charging))			// 充满，立即发送，然后不再发送
					|| (Match_Charging == 1 && totalSeconds + 3 >= Match_Time + 60))	// 充装中，或1分钟发送一次
				{
					Match_Time = totalSeconds;
					// 发送消息到任务，进行充装匹配
					xSemaphoreGive(Match_Semaphore);
				}
			}
		}	
		// 如果非充装状态，匹配复位
		if(!dcBuff.configDisplay.op_SEND_GPS_DATA && !dcBuff.configDisplay.op_BOX_VER && RF_initStatus && (!charging && !Manual_Charing))
		{
			Match_Charging = 1;	// 回持区间，未充满
			Match_Time = 0;
			Truck_Matched = 0;
			Truck_Charging = 0;
		}
		
		// 写入全局缓冲（保持报警标志，直到发送任务处理）
		if(dcBuff.sampleData.warnning)
			sample.warnning = 1;
		dcBuff.sampleData = sample;
		//if((dcBuff.sampleData.leak.staLeak == LEAK_STATUS_A2_ALARM) != lastLeakWarning)
		if(	sample.warnning == 1)
		{
			//printf("\n*** Leak warnning: %d ***\n", (dcBuff.sampleData.leak.staLeak == LEAK_STATUS_A2_ALARM));
			dcBuff.sampleData.warnning = 1;
			// 首次检测到泄露或停止泄露，立即发送数据
			DTU_semGPRS = 1;
		}
		lastLeakWarning = (dcBuff.sampleData.leak.staLeak == LEAK_STATUS_A2_ALARM);

		// 如果没有扩展温度，且有真空计温度，用真空计温度代替扩展温度（显示和上传）
		if(dcBuff.sampleData.staExtTempr[0].status == SENSOR_STATUS_NOCONNECT)
		{
			if(dcBuff.sampleData.vacuum[0].staVacuum != VACUUM_STATUS_COMM_FAULT && dcBuff.sampleData.vacuum[0].staVacuum != VACUUM_STATUS_FAULT)
			{
				dcBuff.sampleData.extTempr[0] = dcBuff.sampleData.vacuum[0].tempr;
				dcBuff.sampleData.staExtTempr[0].status = SENSOR_STATUS_NORMAL;
			}
		}
		
		// 读取电池电压
		if(DS2788_ReadBattery(&dtuSample))
		{
			dcBuff.dtuData.batLow = dtuSample.batLow;
			dcBuff.dtuData.batCurrent = dtuSample.batCurrent;
			dcBuff.dtuData.batPct = dtuSample.batPct;
			dcBuff.dtuData.batCapa = dtuSample.batCapa;
			dcBuff.dtuData.batMaxCapa = dtuSample.batMaxCapa;
			dcBuff.dtuData.batTempr = dtuSample.batTempr;
			dcBuff.dtuData.batVoltage = dtuSample.batVoltage;			
		}
		
		// 禁止ADC
		LL_ADC_Disable(ADC1);
		
		// 通知发送任务采集完成
		GPRS_semSampled = 1;
		// 通知显示板采集完成
		Config_Sample_Request = 0;
		// 通知显示屏: 刷新
		xSemaphoreGive(Key_Semaphore); //Form_Refresh(); //这个函数未做互斥，有可能冲突
		// 刷新电流输出
		DAC7311_Refresh();
		
		/* Get the conversion result */
		if(!dcBuff.configDisplay.op_USE_CAPACITY_SENSOR)			
			printf("\nConversion result of diff: \t\t%02X, %.1f kPa", sample.staDPress.status, sample.diff);
		else
			printf("\nConversion result of capa: \t\t%02X, %.1f pF", sample.staDPress.status, sample.diff);			
//		printf("\nConversion result of press: \t\t%02X, %.2f MPa", sample.staPress.status, (float) sample.pressure / 1000);
//		for(i = 0; i < 0; i++)
//			printf("\nConversion result of extPress[%d]: \t%02X, %.2f MPa", i, sample.staExtPress[i].status, (float) sample.extPressure[i] / 1000);
//		for(i = 0; i < 2; i++)
//			printf("\nConversion result of extTempr[%d]: \t%02X, %d ℃", i, sample.staExtTempr[i].status, sample.extTempr[i]);
				
		printf("\nConversion result of height: \t\t%.1f mm", sample.height);
//		printf("\nConversion result of volTol: \t\t%u L", sample.volumeTotal);
//		printf("\nConversion result of volume: \t\t%u L", sample.volume);
		printf("\nConversion result of volPct: \t\t%.2f %%", (float) sample.volumePct / 100);
		printf("\nConversion result of charging: \t\t%d", sample.charging);
		
//		printf("\nConversion result of staVacuum: \t%u", sample.vacuum[0].staVacuum);
//		printf("\nConversion result of lifeVacuum: \t%u Months", sample.vacuum[0].lifeVacuum);
		printf("\nConversion result of vacuum: \t\t%.2f Pa", sample.vacuum[0].vacuum);
//		printf("\nConversion result of rateVacuum: \t%.2f Pa.M3/s", sample.vacuum[0].rateVacuum);
//		printf("\nConversion result of typeLeak: \t\t%u", sample.leak.typeLeak);
//		printf("\nConversion result of staLeak: \t\t%u", sample.leak.staLeak);
		printf("\nConversion result of concentrations: \t%u %%", sample.leak.concentrations);
		printf("\n");

		if(first)
		{
			first = 0;
			
			// 马上采集真空数据
			Config_Vacuum_Request = 1;
			// 发送消息给任务
			xSemaphoreGive(Sample_Semaphore);
		}

		// 采集结束
		Sample_phase = 0;
	}
}

void Match_Task(void *p_arg)
{
	uint8_t fail_count = 0;
	
	while(1)
	{
		// 等待匹配信号
		xSemaphoreTake(Match_Semaphore, portMAX_DELAY);

		RF_PowerOn();
		Truck_Matched = rf_charge_match(Match_Charging);
		if(Truck_Matched)
		{
			fail_count = 0;
			Truck_Charging = Match_Charging;
			if(!Truck_Charging)
				Manual_Charing = 0;
		}
		else
		{
			if(++fail_count >= 3)
			{
				fail_count = 0;
				Manual_Charing = 0;
			}
		}
		RF_PowerOff();

		if(!Manual_Charing)
		{
			printf("********* Manual_Charing = 0 ****\r\n");
			// 恢复初始状态
			Truck_Matched = 0;
			Truck_Charging = 0;
		}
	}
}
