MS-DTU/MS-DTU-V1/User/adc_sample.c

499 lines
17 KiB
C
Raw 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 "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_IN5AD5
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_IN15AD_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_IN1AD1)
PC1 ------> ADC1_IN2AD2)
PC2 ------> ADC1_IN3AD3)
PC3 ------> ADC1_IN4AD4)
*/
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())
{
VCC_SENSOR_5V_ON();
osDelay(2000);
}
printf("\n***\n***\n*** send data ***\n***\n***\n");
modbus_read_data();
osDelay(2000);
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();
// 记录上次采集的值
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;
// 记录判断时间
last_SampleTime = totalSeconds;
}
if(sample.warnning)
printf("\n*** Level warnning ***\n");
// 读取电池电压
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;
}
}
}