IoT_SCV_CH584M/bsp/src/bsp_bmp390.c

1250 lines
43 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 "bsp_bmp390.h"
#include "bsp_motor.h"
#include "bsp_led.h"
#include "bsp_key.h"
#include "bsp_adc.h"
#include "CONFIG.h"
#include "log.h"
#include "bsp_ml307r.h"
#include "SLEEP.h"
uint8_t flag;
uint8_t keydown_flag = 0;
uint8_t keydown_time = 0;
uint8_t volatile fault_state = 0;
TsValveRawData ValveRawData;
TsValveRawData ValveRawData_buffer[5];
TsValveInfo ValveInfo;
// 安全状态全局变量
TsValveSafetyStatus valve_safety = {0};
extern uint8_t motor_flag;
extern Shell shell;
static tmosTaskID check_task_id = INVALID_TASK_ID;
typedef enum
{
kPressIn = 0,
kPressOut = 1,
kPressAtom = 2,
kPressMaxIndex
} TePressSensorIndex;
static tmosTaskID press_task_id = INVALID_TASK_ID;
#define PRESS_IN_CS_HIGH() GPIOA_SetBits(GPIO_Pin_8)
#define PRESS_IN_CS_LOW() GPIOA_ResetBits(GPIO_Pin_8)
#define PRESS_OUT_CS_HIGH() GPIOA_SetBits(GPIO_Pin_2)
#define PRESS_OUT_CS_LOW() GPIOA_ResetBits(GPIO_Pin_2)
#define PRESS_ATOM_CS_HIGH() GPIOA_SetBits(GPIO_Pin_0)
#define PRESS_ATOM_CS_LOW() GPIOA_ResetBits(GPIO_Pin_0)
uint8_t volatile press_done_flag = 0;
uint8_t SPI0_SendByte(uint8_t data);
void SPI_CsStart(TePressSensorIndex index);
void SPI_CsStop(TePressSensorIndex index);
/* Variable to store the device address */
static uint8_t dev_in_addr;
static uint8_t dev_out_addr;
static uint8_t dev_atom_addr;
uint8_t Bmp_ReadData(uint8_t *reg_data, uint32_t len)
{
while (len--)
{
*reg_data = SPI0_SendByte(0x00);
reg_data++;
}
return BMP3_INTF_RET_SUCCESS;
}
BMP3_INTF_RET_TYPE Bmp_WriteData(const uint8_t *reg_data, uint32_t len)
{
uint8_t i = 0;
for (i = 0; i < len; i++)
{
SPI0_SendByte(reg_data[i]);
}
return BMP3_INTF_RET_SUCCESS;
}
BMP3_INTF_RET_TYPE BMP390_IN_SPI_Read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
BMP3_INTF_RET_TYPE rslt = 0;
uint8_t reg_spi[1] = {(reg_addr & 0x7F) | 0x80};
SPI_CsStart(kPressIn); // 拉低片选
Bmp_WriteData(reg_spi, 1); // 写入控制字节
rslt = Bmp_ReadData(reg_data, len);
SPI_CsStop(kPressIn);
return rslt;
}
/*!
* SPI write function map to COINES platform
*/
BMP3_INTF_RET_TYPE BMP390_IN_SPI_Write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
uint8_t reg_spi[1] = {reg_addr & 0x7f};
BMP3_INTF_RET_TYPE rslt = 0;
SPI_CsStart(kPressIn);
Bmp_WriteData(reg_spi, 1);
rslt = Bmp_WriteData(reg_data, len);
SPI_CsStop(kPressIn);
// printf("BMP390_OUT_SPI_Write: %d" , rslt);
return rslt;
}
/*!
* SPI read function map to COINES platform
*/
BMP3_INTF_RET_TYPE BMP390_OUT_SPI_Read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
BMP3_INTF_RET_TYPE rslt = 0;
uint8_t reg_spi[1] = {(reg_addr & 0x7F) | 0x80};
SPI_CsStart(kPressOut); // 拉低片选
Bmp_WriteData(reg_spi, 1); // 写入控制字节
rslt = Bmp_ReadData(reg_data, len);
SPI_CsStop(kPressOut);
return rslt;
}
/*!
* SPI write function map to COINES platform
*/
BMP3_INTF_RET_TYPE BMP390_OUT_SPI_Write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
uint8_t reg_spi[1] = {reg_addr & 0x7f};
BMP3_INTF_RET_TYPE rslt = 0;
SPI_CsStart(kPressOut);
Bmp_WriteData(reg_spi, 1);
rslt = Bmp_WriteData(reg_data, len);
SPI_CsStop(kPressOut);
// printf("BMP390_OUT_SPI_Write: %d" , rslt);
return rslt;
}
BMP3_INTF_RET_TYPE BMP390_ATOM_SPI_Read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
BMP3_INTF_RET_TYPE rslt = 0;
uint8_t reg_spi[1] = {(reg_addr & 0x7F) | 0x80};
SPI_CsStart(kPressAtom); // 拉低片选
Bmp_WriteData(reg_spi, 1); // 写入控制字节
rslt = Bmp_ReadData(reg_data, len);
SPI_CsStop(kPressAtom);
return rslt;
}
/*!
* SPI write function map to COINES platform
*/
BMP3_INTF_RET_TYPE BMP390_ATOM_SPI_Write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
uint8_t reg_spi[1] = {reg_addr & 0x7f};
BMP3_INTF_RET_TYPE rslt = 0;
SPI_CsStart(kPressAtom);
Bmp_WriteData(reg_spi, 1);
rslt = Bmp_WriteData(reg_data, len);
SPI_CsStop(kPressAtom);
// printf("BMP390_OUT_SPI_Write: %d" , rslt);
return rslt;
}
void bmp3_delay_us(uint32_t period, void *intf_ptr)
{
DelayUs(period);
}
void bmp3_check_rslt(const char api_name[], int8_t rslt)
{
switch (rslt)
{
case BMP3_OK:
/* Do nothing */
break;
case BMP3_E_NULL_PTR:
printf("API [%s] Error [%d] : Null pointer\r\n", api_name, rslt);
break;
case BMP3_E_COMM_FAIL:
printf("API [%s] Error [%d] : Communication failure\r\n", api_name, rslt);
break;
case BMP3_E_INVALID_LEN:
printf("API [%s] Error [%d] : Incorrect length parameter\r\n", api_name, rslt);
break;
case BMP3_E_DEV_NOT_FOUND:
printf("API [%s] Error [%d] : Device not found\r\n", api_name, rslt);
break;
case BMP3_E_CONFIGURATION_ERR:
printf("API [%s] Error [%d] : Configuration Error\r\n", api_name, rslt);
break;
case BMP3_W_SENSOR_NOT_ENABLED:
printf("API [%s] Error [%d] : Warning when Sensor not enabled\r\n", api_name, rslt);
break;
case BMP3_W_INVALID_FIFO_REQ_FRAME_CNT:
printf("API [%s] Error [%d] : Warning when Fifo watermark level is not in limit\r\n", api_name, rslt);
break;
default:
printf("API [%s] Error [%d] : Unknown error code\r\n", api_name, rslt);
break;
}
}
BMP3_INTF_RET_TYPE BMP390_IN_InterfaceInit(struct bmp3_dev *bmp3, uint8_t intf)
{
int8_t rslt = BMP3_OK;
/* Bus configuration : SPI */
if (intf == BMP3_SPI_INTF)
{
printf("SPI Interface\n");
bmp3->read = BMP390_IN_SPI_Read;
bmp3->write = BMP390_IN_SPI_Write;
bmp3->intf = BMP3_SPI_INTF;
printf("spi init ok\r\n");
}
DelayMs(100);
bmp3->delay_us = bmp3_delay_us;
bmp3->intf_ptr = &dev_in_addr;
return rslt;
}
BMP3_INTF_RET_TYPE BMP390_OUT_InterfaceInit(struct bmp3_dev *bmp3, uint8_t intf)
{
int8_t rslt = BMP3_OK;
/* Bus configuration : SPI */
if (intf == BMP3_SPI_INTF)
{
printf("SPI Interface\n");
bmp3->read = BMP390_OUT_SPI_Read;
bmp3->write = BMP390_OUT_SPI_Write;
bmp3->intf = BMP3_SPI_INTF;
printf("spi init ok\r\n");
}
DelayMs(100);
bmp3->delay_us = bmp3_delay_us;
bmp3->intf_ptr = &dev_out_addr;
return rslt;
}
BMP3_INTF_RET_TYPE BMP390_ATOM_InterfaceInit(struct bmp3_dev *bmp3, uint8_t intf)
{
int8_t rslt = BMP3_OK;
/* Bus configuration : SPI */
if (intf == BMP3_SPI_INTF)
{
printf("SPI Interface\n");
bmp3->read = BMP390_ATOM_SPI_Read;
bmp3->write = BMP390_ATOM_SPI_Write;
bmp3->intf = BMP3_SPI_INTF;
printf("spi init ok\r\n");
}
DelayMs(100);
bmp3->delay_us = bmp3_delay_us;
bmp3->intf_ptr = &dev_atom_addr;
return rslt;
}
void SPI_CsStart(TePressSensorIndex index)
{
switch (index)
{
case kPressIn:
PRESS_IN_CS_LOW();
break;
case kPressOut:
PRESS_OUT_CS_LOW();
break;
case kPressAtom:
PRESS_ATOM_CS_LOW();
break;
default:
break;
}
}
void SPI_CsStop(TePressSensorIndex index)
{
switch (index)
{
case kPressIn:
PRESS_IN_CS_HIGH();
break;
case kPressOut:
PRESS_OUT_CS_HIGH();
break;
case kPressAtom:
PRESS_ATOM_CS_HIGH();
break;
default:
break;
}
}
uint8_t SPI0_SendByte(uint8_t data)
{
R8_SPI0_BUFFER = data;
while (!(R8_SPI0_INT_FLAG & RB_SPI_FREE));
return (R8_SPI0_BUFFER);
}
void PRESS_IO_SPI_Init(void)
{
/**
* CSB1: PA3
* CSB2: PA5
* CSB3: PA0
* SCL: PA13
* SDA: PA14
* SDO: PA15
*/
// SDA: MOSI
// SDO: MISO
GPIOA_SetBits(GPIO_Pin_2);
GPIOA_ModeCfg(GPIO_Pin_2, GPIO_ModeOut_PP_5mA);
GPIOA_SetBits(GPIO_Pin_8);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
GPIOA_SetBits(GPIO_Pin_0);
GPIOA_ModeCfg(GPIO_Pin_0, GPIO_ModeOut_PP_5mA);
SPI_CsStop(kPressIn);
SPI_CsStop(kPressOut);
SPI_CsStop(kPressAtom);
// spi初始化模式0
GPIOA_ModeCfg(GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU);
SPI0_MasterDefInit();
}
void PRESS_LowerIO_Init(void)
{
// BMP390默认供电时其他IO都是高电平,INT引脚为低电平
// SPI
GPIOA_SetBits(GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
GPIOA_ModeCfg(GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, GPIO_ModeIN_PU);
// CSB3: PA0
GPIOA_SetBits(GPIO_Pin_2);
GPIOA_ModeCfg(GPIO_Pin_2, GPIO_ModeIN_PU);
// CSB2: PA5
GPIOA_SetBits(GPIO_Pin_8);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
// CSB1: PA3
GPIOA_SetBits(GPIO_Pin_0);
GPIOA_ModeCfg(GPIO_Pin_0, GPIO_ModeIN_PU);
}
void Lower_IO_Deinit(void)
{
// LED
GPIOB_ResetBits(LED_VALVE_R_PIN | LED_VALVE_G_PIN);
GPIOB_ModeCfg(LED_VALVE_R_PIN | LED_VALVE_G_PIN, GPIO_ModeIN_PD);
GPIOA_ResetBits(LED_VBAT_PIN | LED_ALARM_PIN);
GPIOA_ModeCfg(LED_VBAT_PIN | LED_ALARM_PIN, GPIO_ModeIN_PD);
// KEY | RESET KEY | boot KEY
GPIOB_ResetBits(KEY_BPIN);
GPIOB_ModeCfg(KEY_BPIN, GPIO_ModeIN_PU);
// GPIOB_ResetBits(GPIO_Pin_23 | GPIO_Pin_22);
// GPIOB_ModeCfg(GPIO_Pin_23 | GPIO_Pin_22, GPIO_ModeIN_PD);
// ADC
GPIOA_ResetBits(ADC_VBAT_PIN);
GPIOA_ModeCfg(ADC_VBAT_PIN, GPIO_ModeIN_Floating);
ADC_DisablePower();
// BMP390
// INT1: PA2 | INT2: PA6 | INT3: PA12
GPIOA_ModeCfg(GPIO_Pin_6 | GPIO_Pin_9 | GPIO_Pin_3, GPIO_ModeIN_PD);
// spi初始化
GPIOA_ModeCfg(GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeIN_PD);
GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PD);
// 4G
// 关闭3.8V供电
GPIOB_ResetBits(ENABLE_3_8_V);
GPIOB_ModeCfg(ENABLE_3_8_V, GPIO_ModeIN_PD);
// 将控制引脚设为下拉,减少漏电流
GPIOB_ModeCfg(ML307_PWR_PIN | ML307_RST_PIN, GPIO_ModeIN_PD);
// UART引脚
GPIOB_ModeCfg(ML307_UART_TX_PIN, GPIO_ModeIN_PD);
GPIOB_ModeCfg(ML307_UART_RX_PIN, GPIO_ModeIN_PU);
// SIM卡检测引脚配置为下拉输入
GPIOB_ModeCfg(USIM_DECT_PIN, GPIO_ModeIN_PD);
// motor
GPIOA_ResetBits(COIL_ADC);
GPIOA_ModeCfg(COIL_ADC, GPIO_ModeIN_PD);
// IN1 + ; IN2 +
GPIOB_SetBits(COIL_A);
GPIOB_SetBits(COIL_B);
GPIOB_ModeCfg(COIL_A | COIL_B, GPIO_ModeIN_PD);
// UART3
// GPIOB_ModeCfg(GPIO_Pin_21 | GPIO_Pin_20, GPIO_ModeIN_PD);
// // 关闭UART3时钟
// sys_safe_access_enable();
// R8_SLP_CLK_OFF0 |= RB_SLP_CLK_UART3;
// sys_safe_access_disable();
// // 关闭shell和日志系统
// shell.write = NULL; // 禁用shell输出
// 关闭外部低速晶振
// GPIOA_ModeCfg(GPIO_Pin_10 | GPIO_Pin_11, GPIO_ModeIN_PD);
}
void PRESS_LowPower(void)
{
Lower_IO_Deinit();
if (press_done_flag == 1)
{
PRESS_LowerIO_Init();
}
}
int8_t ret = 0;
uint8_t loop = 0;
struct bmp3_dev DevIn;
struct bmp3_dev DevOut;
struct bmp3_dev DevAtom;
uint16_t settings_sel;
struct bmp3_data data = {0};
struct bmp3_settings settings = {0};
struct bmp3_status status = {{0}};
// T,P
int32_t T[3] = {0};
int32_t P[3] = {0};
// 定义滑动窗口函数
void slideValveRawDataBuffer(TsValveRawData *newData)
{
// 将数组元素左移一位
for (int i = 0; i < 4; i++)
{
tmos_memcpy(&ValveRawData_buffer[i], &ValveRawData_buffer[i + 1], sizeof(TsValveRawData));
}
// 将新数据存入数组[4]
tmos_memcpy(&ValveRawData_buffer[4], &newData[0], sizeof(TsValveRawData));
// for (int i = 0; i < 5; i++)
// {
// logDebug("Buffer[%d]: in_press=%d, out_press=%d, diff=%d",
// i,
// ValveRawData_buffer[i].in_press,
// ValveRawData_buffer[i].out_press,
// ValveRawData_buffer[i].in_out_press_diff);
// }
}
__HIGH_CODE
__attribute__((noinline))
uint16_t
BMP390_ProcessEvent(uint8_t task_id, uint16_t events)
{
if (events & BMP390_IN_START)
{
press_done_flag = 0;
PRESS_IO_SPI_Init();
settings.op_mode = BMP3_MODE_FORCED;
ret = bmp3_set_op_mode(&settings, &DevIn);
bmp3_check_rslt("bmp3_set_op_mode", ret);
return (events ^ BMP390_IN_START);
}
else if (events & BMP390_OUT_START)
{
press_done_flag = 0;
PRESS_IO_SPI_Init();
settings.op_mode = BMP3_MODE_FORCED;
ret = bmp3_set_op_mode(&settings, &DevOut);
bmp3_check_rslt("bmp3_set_op_mode", ret);
return (events ^ BMP390_OUT_START);
}
else if (events & BMP390_ATOM_START)
{
press_done_flag = 0;
PRESS_IO_SPI_Init();
settings.op_mode = BMP3_MODE_FORCED;
ret = bmp3_set_op_mode(&settings, &DevAtom);
bmp3_check_rslt("bmp3_set_op_mode", ret);
return (events ^ BMP390_ATOM_START);
}
else if (events & BMP390_EVT_READ)
{
PRESS_IO_SPI_Init();
#if 0
PRESS_IO_SPI_Init();
// IN
ret = bmp3_get_status(&status, &DevIn);
bmp3_check_rslt("bmp3_get_status", ret);
/* Read temperature and pressure data iteratively based on data ready interrupt */
if ((ret == BMP3_OK) && (status.intr.drdy == BMP3_ENABLE))
{
/*
* First parameter indicates the type of data to be read
* BMP3_PRESS_TEMP : To read pressure and temperature data
* BMP3_TEMP : To read only temperature data
* BMP3_PRESS : To read only pressure data
*/
ret = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &DevIn);
bmp3_check_rslt("bmp3_get_sensor_data", ret);
/* NOTE : Read status register again to clear data ready interrupt status */
ret = bmp3_get_status(&status, &DevIn);
bmp3_check_rslt("bmp3_get_status", ret);
#ifdef BMP3_FLOAT_COMPENSATION
printf("IN[%d] T: %.2f deg C, P: %.2f Pa\n", loop, (data.temperature), (data.pressure));
#else
printf("IN[%d] T: %ld deg C, P: %lu Pa\n", loop, (long int)(int32_t)(data.temperature / 100),
(long unsigned int)(uint32_t)(data.pressure / 100));
#endif
}
// OUT
ret = bmp3_get_status(&status, &DevOut);
bmp3_check_rslt("bmp3_get_status", ret);
/* Read temperature and pressure data iteratively based on data ready interrupt */
if ((ret == BMP3_OK) && (status.intr.drdy == BMP3_ENABLE))
{
/*
* First parameter indicates the type of data to be read
* BMP3_PRESS_TEMP : To read pressure and temperature data
* BMP3_TEMP : To read only temperature data
* BMP3_PRESS : To read only pressure data
*/
ret = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &DevOut);
bmp3_check_rslt("bmp3_get_sensor_data", ret);
/* NOTE : Read status register again to clear data ready interrupt status */
ret = bmp3_get_status(&status, &DevOut);
bmp3_check_rslt("bmp3_get_status", ret);
#ifdef BMP3_FLOAT_COMPENSATION
printf("OUT[%d] T: %.2f deg C, P: %.2f Pa\n", loop, (data.temperature), (data.pressure));
#else
printf("OUT[%d] T: %ld deg C, P: %lu Pa\n", loop, (long int)(int32_t)(data.temperature / 100),
(long unsigned int)(uint32_t)(data.pressure / 100));
#endif
loop = loop + 1;
}
tmos_start_task(press_task_id, WF5803_EVT_START, MS1_TO_SYSTEM_TIME(2000));
#endif
if (flag == 1)
{
ret = bmp3_get_status(&status, &DevIn); // 配置中断引脚为锁存模式需要读取int_status.drdy位才能清除中断状态标志
bmp3_check_rslt("bmp3_get_status", ret);
if (status.intr.drdy == BMP3_ENABLE)
{
/*
* First parameter indicates the type of data to be read
* BMP3_PRESS_TEMP : To read pressure and temperature data
* BMP3_TEMP : To read only temperature data
* BMP3_PRESS : To read only pressure data
*/
ret = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &DevIn);
bmp3_check_rslt("bmp3_get_sensor_data", ret);
/* NOTE : Read status register again to clear data ready interrupt status */
ret = bmp3_get_status(&status, &DevIn);
bmp3_check_rslt("bmp3_get_status", ret);
// printf("IN[%d] T: %ld deg C, P: %lu Pa\r\n", loop, (long int)(int32_t)(data.temperature / 100),
// (long unsigned int)(uint32_t)(data.pressure / 100));
T[0] = (int32_t)(data.temperature / 100);
P[0] = (uint32_t)(data.pressure / 100);
}
// tmos_start_task(press_task_id, BMP390_ATOM_START, MS1_TO_SYSTEM_TIME(100));
tmos_start_task(press_task_id, BMP390_OUT_START, MS1_TO_SYSTEM_TIME(500)); // 100
// tmos_start_task(press_task_id, BMP390_IN_START, MS1_TO_SYSTEM_TIME(1000));
}
else if (flag == 2)
{
ret = bmp3_get_status(&status, &DevOut); // 配置中断引脚为锁存模式需要读取int_status.drdy位才能清除中断状态标志
bmp3_check_rslt("bmp3_get_status", ret);
if (status.intr.drdy == BMP3_ENABLE)
{
/*
* First parameter indicates the type of data to be read
* BMP3_PRESS_TEMP : To read pressure and temperature data
* BMP3_TEMP : To read only temperature data
* BMP3_PRESS : To read only pressure data
*/
ret = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &DevOut);
bmp3_check_rslt("bmp3_get_sensor_data", ret);
/* NOTE : Read status register again to clear data ready interrupt status */
ret = bmp3_get_status(&status, &DevOut);
bmp3_check_rslt("bmp3_get_status", ret);
// printf("OUT[%d] T: %ld deg C, P: %lu Pa\r\n", loop, (long int)(int32_t)(data.temperature / 100),
// (long unsigned int)(uint32_t)(data.pressure / 100));
T[1] = (int32_t)(data.temperature / 100);
P[1] = (uint32_t)(data.pressure / 100);
}
tmos_start_task(press_task_id, BMP390_ATOM_START, MS1_TO_SYSTEM_TIME(500)); // 100
// tmos_start_task(press_task_id, BMP390_OUT_START, MS1_TO_SYSTEM_TIME(1000));
}
else if (flag == 3)
{
ret = bmp3_get_status(&status, &DevAtom); // 配置中断引脚为锁存模式需要读取int_status.drdy位才能清除中断状态标志
bmp3_check_rslt("bmp3_get_status", ret);
if (status.intr.drdy == BMP3_ENABLE)
{
/*
* First parameter indicates the type of data to be read
* BMP3_PRESS_TEMP : To read pressure and temperature data
* BMP3_TEMP : To read only temperature data
* BMP3_PRESS : To read only pressure data
*/
ret = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &DevAtom);
bmp3_check_rslt("bmp3_get_sensor_data", ret);
/* NOTE : Read status register again to clear data ready interrupt status */
ret = bmp3_get_status(&status, &DevAtom);
bmp3_check_rslt("bmp3_get_status", ret);
// printf("ATOM[%d] T: %ld deg C, P: %lu Pa\r\n", loop, (long int)(int32_t)(data.temperature / 100),
// (long unsigned int)(uint32_t)(data.pressure / 100));
T[2] = (int32_t)(data.temperature / 100);
P[2] = (uint32_t)(data.pressure / 100);
logDebug("**********************************");
logDebug("%d, %d, %d, %d, %d, %d \r\n", T[0], T[1], T[2], P[0], P[1], P[2]);
logDebug("P1: %d,P2: %d ,^P: %d \r\n", P[0] - P[2], P[1] - P[2], P[0] - P[1]);
logDebug("**********************************");
}
tmos_start_task(press_task_id, BMP390_IN_START, MS1_TO_SYSTEM_TIME(500)); // 100
// tmos_start_task(press_task_id, BMP390_ATOM_START, MS1_TO_SYSTEM_TIME(1000));
}
flag = 0;
press_done_flag = 1;
// TODO:读完三个气压传感器数据后在做计算
ValveRawData.in_press_raw = P[0];
ValveRawData.out_press_raw = P[1];
ValveRawData.atom_press = P[2];
ValveRawData.in_temp = T[0];
ValveRawData.out_temp = T[1];
ValveRawData.atom_temp = T[2];
ValveRawData.in_press = ValveRawData.in_press_raw - ValveRawData.atom_press;
ValveRawData.out_press = ValveRawData.out_press_raw - ValveRawData.atom_press;
ValveRawData.in_out_press_diff = ValveRawData.in_press - ValveRawData.out_press;
logDebug("in_press: %d, out_press: %d, atom_press: %d\r\n", ValveRawData.in_press, ValveRawData.out_press, ValveRawData.atom_press);
logDebug("in_temp: %d, out_temp: %d, atom_temp: %d\r\n", ValveRawData.in_temp, ValveRawData.out_temp, ValveRawData.atom_temp);
logDebug("in_out_press_diff: %d\r\n", ValveRawData.in_out_press_diff);
// 刷新ValveRawData_buffer,把之前的ValveRawData按时间顺序向右滑动
// 最新的ValveRawData 存在数组[4]
slideValveRawDataBuffer(&ValveRawData);
loop = loop + 1;
return (events ^ BMP390_EVT_READ);
}
return 0;
}
void VALVE_SetInfo()
{
ValveInfo.over_press = 6200;
ValveInfo.low_press = 680;
ValveInfo.over_temp = 65;
ValveInfo.delay_close_count = 6;
ValveInfo.over_flow_press_diff_1kpa = 650;
ValveInfo.over_flow_press_diff_2kpa = 650;
ValveInfo.over_flow_press_diff_3kpa = 650;
}
void BSP_PRESS_Init(void)
{
PRESS_IO_SPI_Init();
// 中断引脚的配置
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeIN_PD);
GPIOA_ITModeCfg(GPIO_Pin_9, GPIO_ITMode_RiseEdge);
GPIOA_ModeCfg(GPIO_Pin_3, GPIO_ModeIN_PD);
GPIOA_ITModeCfg(GPIO_Pin_3, GPIO_ITMode_RiseEdge);
GPIOA_ModeCfg(GPIO_Pin_6, GPIO_ModeIN_PD);
GPIOA_ITModeCfg(GPIO_Pin_6, GPIO_ITMode_RiseEdge);
PWR_PeriphWakeUpCfg(ENABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay);
PFIC_EnableIRQ(GPIO_A_IRQn);
// IN
ret = BMP390_IN_InterfaceInit(&DevIn, BMP3_SPI_INTF);
bmp3_check_rslt("BMP390_OUT_InterfaceInit", ret);
ret = bmp3_init(&DevIn);
bmp3_check_rslt("bmp3_init", ret);
settings.int_settings.drdy_en = BMP3_ENABLE;
settings.int_settings.latch = BMP3_INT_PIN_LATCH;
settings.int_settings.level = BMP3_INT_PIN_ACTIVE_HIGH;
settings.int_settings.output_mode = BMP3_INT_PIN_PUSH_PULL;
settings.press_en = BMP3_ENABLE;
settings.temp_en = BMP3_ENABLE;
settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X; // BMP3_OVERSAMPLING_2X
settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X; // BMP3_OVERSAMPLING_2X
settings.odr_filter.odr = BMP3_ODR_0_39_HZ; // BMP3_ODR_1_5_HZ
settings.odr_filter.iir_filter = BMP3_IIR_FILTER_COEFF_1; // BMP3_IIR_FILTER_COEFF_3
settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR | BMP3_SEL_DRDY_EN | BMP3_SEL_IIR_FILTER | BMP3_SEL_OUTPUT_MODE | BMP3_SEL_LEVEL | BMP3_SEL_LATCH;
ret = bmp3_set_sensor_settings(settings_sel, &settings, &DevIn);
bmp3_check_rslt("bmp3_set_sensor_settings", ret);
// OUT
ret = BMP390_OUT_InterfaceInit(&DevOut, BMP3_SPI_INTF);
bmp3_check_rslt("BMP390_OUT_InterfaceInit", ret);
ret = bmp3_init(&DevOut);
bmp3_check_rslt("bmp3_init", ret);
settings.int_settings.drdy_en = BMP3_ENABLE;
settings.int_settings.latch = BMP3_INT_PIN_LATCH;
settings.int_settings.level = BMP3_INT_PIN_ACTIVE_HIGH;
settings.int_settings.output_mode = BMP3_INT_PIN_PUSH_PULL;
settings.press_en = BMP3_ENABLE;
settings.temp_en = BMP3_ENABLE;
settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X;
settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X;
settings.odr_filter.odr = BMP3_ODR_0_39_HZ;
settings.odr_filter.iir_filter = BMP3_IIR_FILTER_COEFF_1;
settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR | BMP3_SEL_DRDY_EN | BMP3_SEL_IIR_FILTER | BMP3_SEL_OUTPUT_MODE | BMP3_SEL_LEVEL | BMP3_SEL_LATCH;
ret = bmp3_set_sensor_settings(settings_sel, &settings, &DevOut);
bmp3_check_rslt("bmp3_set_sensor_settings", ret);
// ATOM
ret = BMP390_ATOM_InterfaceInit(&DevAtom, BMP3_SPI_INTF);
bmp3_check_rslt("BMP390_ATOM_InterfaceInit", ret);
ret = bmp3_init(&DevAtom);
bmp3_check_rslt("bmp3_init", ret);
settings.int_settings.drdy_en = BMP3_ENABLE;
settings.int_settings.latch = BMP3_INT_PIN_LATCH;
settings.int_settings.level = BMP3_INT_PIN_ACTIVE_HIGH;
settings.int_settings.output_mode = BMP3_INT_PIN_PUSH_PULL;
settings.press_en = BMP3_ENABLE;
settings.temp_en = BMP3_ENABLE;
settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X;
settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X;
settings.odr_filter.odr = BMP3_ODR_0_39_HZ;
settings.odr_filter.iir_filter = BMP3_IIR_FILTER_COEFF_1;
settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR | BMP3_SEL_DRDY_EN | BMP3_SEL_IIR_FILTER | BMP3_SEL_OUTPUT_MODE | BMP3_SEL_LEVEL | BMP3_SEL_LATCH;
ret = bmp3_set_sensor_settings(settings_sel, &settings, &DevAtom);
bmp3_check_rslt("bmp3_set_sensor_settings", ret);
press_task_id = TMOS_ProcessEventRegister(BMP390_ProcessEvent);
tmos_set_event(press_task_id, BMP390_IN_START);
// tmos_set_event(press_task_id, BMP390_OUT_START);
// tmos_set_event(press_task_id, BMP390_ATOM_START);
VALVE_SetInfo();
}
/**
* @brief 判断参考值是否在测量值的误差范围内
*
* @param ref_value 参考值
* @param measured_value 测量值
* @param tolerance 误差范围(正负)
*
* @return uint8_t 返回 1 表示在范围内,返回 0 表示不在范围内
*/
uint8_t isWithinTolerance(int32_t ref_value, int32_t measured_value, uint8_t tolerance)
{
if ((measured_value - tolerance <= ref_value) && (ref_value <= measured_value + tolerance))
{
return 1; // 在范围内
}
else
{
return 0; // 不在范围内
}
}
/**
* @brief 检测管道是否无流量状态
*
* @return uint8_t 返回1表示无流量返回0表示有流量
*/
uint8_t isNoFlowDetected(void)
{
// 检测进出口压差是否在无流量阈值范围内 (0±2Pa)
if (ValveRawData.in_out_press_diff >= -AUTO_CLOSE_NO_FLOW_THRESHOLD &&
ValveRawData.in_out_press_diff <= AUTO_CLOSE_NO_FLOW_THRESHOLD)
{
logDebug("No flow detected: pressure diff = %d Pa", ValveRawData.in_out_press_diff);
return 1; // 无流量
}
logDebug("Flow detected: pressure diff = %d Pa", ValveRawData.in_out_press_diff);
return 0; // 有流量
}
/**
* @brief 启动延时关阀功能
*/
void startAutoCloseTimer(void)
{
if (!valve_safety.auto_close_enabled)
{
valve_safety.auto_close_enabled = 1;
valve_safety.auto_close_active = 1;
valve_safety.auto_close_check_count = 0;
valve_safety.auto_close_start_time = BSP_Get_Tick();
logDebug("Auto close timer started");
// 开始第一次检测延时5分钟
tmos_start_task(check_task_id, AUTO_CLOSE_CHECK_EVT, MS1_TO_SYSTEM_TIME(AUTO_CLOSE_CHECK_INTERVAL_MS));
// 设置35分钟超时保护30分钟+5分钟误差容限
tmos_start_task(check_task_id, AUTO_CLOSE_TIMEOUT_EVT, MS1_TO_SYSTEM_TIME(35 * 60 * 1000));
}
}
/**
* @brief 停止延时关阀功能
*/
void stopAutoCloseTimer(void)
{
if (valve_safety.auto_close_enabled)
{
valve_safety.auto_close_enabled = 0;
valve_safety.auto_close_active = 0;
valve_safety.auto_close_check_count = 0;
// 停止定时器
tmos_stop_task(check_task_id, AUTO_CLOSE_CHECK_EVT);
tmos_stop_task(check_task_id, AUTO_CLOSE_TIMEOUT_EVT);
logDebug("Auto close timer stopped");
}
}
/**
* @brief 启动微泄漏检测
*/
void startMicroLeakDetection(void)
{
// 重置微泄漏计数器
valve_safety.micro_leak_count = 0;
// 启动10秒定时检测
tmos_start_task(check_task_id, MICRO_LEAK_CHECK_EVT, MS1_TO_SYSTEM_TIME(MICRO_LEAK_CHECK_INTERVAL_MS));
logDebug("微泄漏检测启动");
}
uint16_t Check_ProcessEvent(uint8_t task_id, uint16_t events)
{
if (events & CHECK_EVT_START)
{
// logDebug("fault_state = %d \r\n",fault_state);
if (!fault_state)
{
// TODO:状态切换不对
if (gValveData.switch_status == kOpened)
{
// 延时关阀功能启动条件检测
// 只在未启动延时关阀时检测无流量状态,一旦启动就交给定时检测处理
if (!valve_safety.auto_close_enabled)
{
if (isNoFlowDetected())
{
startAutoCloseTimer();
logDebug("延时关阀启动:检测到无流量状态");
}
}
// 超压检测
// 后端关阀进气端压力超过阈值6200关阀
// 流量0.45时候进气端压力超过阈值6200关阀
if (ValveRawData.in_press >= ValveInfo.over_press)
{
logError("******************************");
logError("超压关阀并锁定");
logDebug("in_press = %d; over_press = %d", ValveRawData.in_press, ValveInfo.over_press);
BSP_VALVE_Close(kValveCmdOverPressure); // 使用超压关阀原因
BSP_VALVE_Lock(kValveCmdOverPressure); // 锁定阀门,防止再次开启
fault_state = 1;
// 超压关阀时停止延时关阀功能
stopAutoCloseTimer();
}
// 欠压检测
else if (ValveRawData.in_press <= ValveInfo.low_press)
{
BSP_VALVE_Close(kValveCmdUnderPressure); // 使用欠压关阀原因
BSP_VALVE_Lock(kValveCmdUnderPressure); // 锁定阀门,防止再次开启
fault_state = 2;
// 欠压关阀时停止延时关阀功能
stopAutoCloseTimer();
logError("******************************");
logError("欠压关阀");
}
#if 1
// 1、过流自动关闭
// 进气端压力2kpa时额定流量调到0.9
// 进气端压力升到 3kpa左右时阀门不能关流量不超过1.4
// 3、进气端压力 1kpa左右时出气端阀口全开需要关闭(过流自动关闭)
// if (isWithinTolerance(1000, ValveRawData.in_press, 50)
// && ValveRawData.in_out_press_diff)
// {
// /* code */
// }
// 进气端压力2kpa时额定流量调到1.4(切断流量)要关阀
if (ValveRawData.in_out_press_diff >= ValveInfo.over_flow_press_diff_2kpa)
{
if (keydown_flag > 0)
{
logDebug("keydown_time !%d", keydown_time);
keydown_time++;
if (keydown_time > 30)
{
keydown_time = 0;
keydown_flag = 0;
}
}
else
{
keydown_time = 0;
logError("******************************");
logError("过流关阀并锁定");
logDebug("in_out_press_diff = %d; threshold = %d", ValveRawData.in_out_press_diff, ValveInfo.over_flow_press_diff_2kpa);
// 先关阀再锁定
BSP_VALVE_Close(kValveCmdOverCurrent); // 使用过流关阀原因
BSP_VALVE_Lock(kValveCmdOverCurrent); // 锁定阀门,防止再次开启
fault_state = 3;
logDebug("Over current status !");
}
}
#endif
}
else if (gValveData.switch_status == kClosed)
{
// 阀门关闭时停止延时关阀功能
if (valve_safety.auto_close_enabled)
{
stopAutoCloseTimer();
}
// 点火开阀
// 监测ValveRawData_buffer当前最新的压差值大于上一秒的压差
if (isWithinTolerance(ValveRawData_buffer[2].in_press, ValveRawData_buffer[4].in_press, 50)
&& ValveRawData_buffer[4].in_out_press_diff >= 900)
{
logError("******************************");
logError("点火开阀");
for (int i = 2; i < 5; i++)
{
logDebug("[%d]: in_press = %d; out_press = %d; in_out_press_diff = %d", i, ValveRawData_buffer[i].in_press, ValveRawData_buffer[i].out_press, ValveRawData_buffer[i].in_out_press_diff);
}
BSP_VALVE_Open(kValveCmdOpenWithStove); // 使用点火开阀原因
}
// else
// {
// logDebug("点火开阀失败");
// for (int i = 2; i < 5; i++)
// {
// logDebug("[%d]: in_press = %d; out_press = %d; in_out_press_diff = %d", i
// , ValveRawData_buffer[i].in_press, ValveRawData_buffer[i].out_press, ValveRawData_buffer[i].in_out_press_diff);
// }
// }
}
// 超温关阀功能:检测至少两个传感器的温度超过阈值
if (gValveData.switch_status == kOpened)
{
// 计算超过阈值的传感器数量
uint8_t over_temp_count = 0;
// 检查三个传感器的温度是否超过阈值
if (T[0] > ValveInfo.over_temp) over_temp_count++;
if (T[1] > ValveInfo.over_temp) over_temp_count++;
if (T[2] > ValveInfo.over_temp) over_temp_count++;
// 如果至少有两个传感器超过阈值,触发关阀
if (over_temp_count >= 2)
{
logDebug("Over temperature detected! T1=%d, T2=%d, T3=%d", T[0], T[1], T[2]);
BSP_VALVE_Close(kValveCmdOverTemperature);
}
}
}
// 检查阀门是否处于锁定状态,如果是则检查隐患是否已排除
if (gValveData.Lock == 1)
{
// 检查隐患是否已排除(过流除外,过流只能手动解锁)
if (valve_safety.lock_reason != kValveCmdOverCurrent && BSP_VALVE_CheckHazardCleared())
{
// 隐患已排除,自动解锁
BSP_VALVE_Unlock();
}
}
// logDebug("motor_flag_end = %d",motor_flag);
// 手动关阀
if (motor_flag == 1)
{
motor_flag = 0;
BSP_VALVE_Open(kValveCmdManualOpen); // 使用普通开阀命令
keydown_flag = 1;
IotFlag_t.Valve_Open_flag = 1;
fault_state = 0;
logDebug("motor/LED open!!!");
}
else if (motor_flag == 2)
{
motor_flag = 0;
// 直接使用普通关阀命令
BSP_VALVE_Close(kValveCmdManualClose);
// fault_state = 4;
logDebug("motor/LED close!!!");
}
else if (motor_flag == 3)
{
motor_flag = 0;
if (gValveData.switch_status == kOpened)
{
LED_VALVE_OPEN;
}
else
{
LED_VALVE_CLOSE;
}
// DelayMs(500);
}
tmos_start_task(check_task_id, CHECK_EVT_START, MS1_TO_SYSTEM_TIME(200)); // 100
return (events ^ CHECK_EVT_START);
}
// 延时关阀检测事件处理
if (events & AUTO_CLOSE_CHECK_EVT)
{
if (valve_safety.auto_close_enabled && valve_safety.auto_close_active)
{
valve_safety.auto_close_check_count++;
logDebug("延时关阀第%d次检测 (共需6次)", valve_safety.auto_close_check_count);
// 检测当前是否仍为无流量状态
if (isNoFlowDetected())
{
logDebug("第%d次检测确认无流量 (in_out_press_diff=%d Pa)",
valve_safety.auto_close_check_count, ValveRawData.in_out_press_diff);
// 如果已经检测了6次30分钟执行关阀
if (valve_safety.auto_close_check_count >= ValveInfo.delay_close_count)
{
logError("******************************");
logError("延时关阀:30分钟无流量,自动关闭阀门");
logError("6次检测均确认无流量,总耗时: %d ms", BSP_Get_Tick() - valve_safety.auto_close_start_time);
// 执行关阀动作
BSP_VALVE_Close(kValveCmdDelayClose); // 使用延时关阀原因
// 停止延时关阀功能
stopAutoCloseTimer();
}
else
{
// 继续下一次检测再等5分钟
logDebug("第%d次检测完成,5分钟后进行第%d次检测",
valve_safety.auto_close_check_count, valve_safety.auto_close_check_count + 1);
tmos_start_task(check_task_id, AUTO_CLOSE_CHECK_EVT,
MS1_TO_SYSTEM_TIME(AUTO_CLOSE_CHECK_INTERVAL_MS));
}
}
else
{
// 检测到有流量,停止延时关阀
logDebug("第%d次检测发现有流量 (in_out_press_diff=%d Pa),停止延时关阀",
valve_safety.auto_close_check_count, ValveRawData.in_out_press_diff);
stopAutoCloseTimer();
}
}
return (events ^ AUTO_CLOSE_CHECK_EVT);
}
// 延时关阀超时事件处理(备用安全机制)
if (events & AUTO_CLOSE_TIMEOUT_EVT)
{
if (valve_safety.auto_close_enabled)
{
logError("******************************");
logError("延时关阀:超时保护,强制关闭阀门");
// 强制执行关阀动作
BSP_VALVE_Close(kValveCmdDelayClose); // 使用延时关阀原因
// 停止延时关阀功能
stopAutoCloseTimer();
}
return (events ^ AUTO_CLOSE_TIMEOUT_EVT);
}
// 微泄漏检测事件处理
if (events & MICRO_LEAK_CHECK_EVT)
{
// 只在阀门关闭状态下检测微泄漏
if (gValveData.switch_status == kClosed)
{
logDebug("微泄漏趋检测!!!!");
// 记录当前压差值
static int last_press = 0;
// 比较当前值与上次值
if (ValveRawData.out_press < last_press)
{
// 出口压力逐渐增小,可能是微泄漏
valve_safety.micro_leak_count++;
logError("微泄漏检测: 出口压力减小 %d -> %d (第%d次/共需%d次)",
last_press, ValveRawData.out_press,
valve_safety.micro_leak_count, MICRO_LEAK_CHECK_COUNT);
// 连续6次检测到压差增大判定为微泄漏
if (valve_safety.micro_leak_count >= MICRO_LEAK_CHECK_COUNT)
{
logError("******************************");
logError("检测到微泄漏");
BSP_VALVE_Close(kValveCmdMicroLeak); // 使用微泄漏关阀原因
BSP_VALVE_Lock(kValveCmdMicroLeak); // 锁定阀门,防止再次开启
valve_safety.micro_leak_count = 0; // 重置计数器
// 微泄漏关阀时停止延时关阀功能
stopAutoCloseTimer();
}
}
else
{
// 压差未增大,重置计数器
if (valve_safety.micro_leak_count > 0)
{
logDebug("微泄漏趋势中断,重置计数器");
valve_safety.micro_leak_count = 0;
}
}
// 更新上次压差值
last_press = ValveRawData.out_press;
}
else
{
// 阀门关闭状态,重置微泄漏计数器
valve_safety.micro_leak_count = 0;
}
// 继续下一次检测
tmos_start_task(check_task_id, MICRO_LEAK_CHECK_EVT, MS1_TO_SYSTEM_TIME(MICRO_LEAK_CHECK_INTERVAL_MS));
return (events ^ MICRO_LEAK_CHECK_EVT);
}
return 0;
}
void Function_Check(void)
{
check_task_id = TMOS_ProcessEventRegister(Check_ProcessEvent);
tmos_set_event(check_task_id, CHECK_EVT_START);
// 如果阀门处于开启状态,启动微泄漏检测
if (gValveData.switch_status == kOpened)
{
startMicroLeakDetection();
}
}
__INTERRUPT
__HIGH_CODE
void GPIOA_IRQHandler(void)
{
if (R16_PA_INT_IF & GPIO_Pin_9)
{
R16_PA_INT_IF = GPIO_Pin_9;
flag = 1;
tmos_set_event(press_task_id, BMP390_EVT_READ);
}
else if (R16_PA_INT_IF & GPIO_Pin_3)
{
R16_PA_INT_IF = GPIO_Pin_3;
flag = 2;
tmos_set_event(press_task_id, BMP390_EVT_READ);
}
else if (R16_PA_INT_IF & GPIO_Pin_6)
{
R16_PA_INT_IF = GPIO_Pin_6;
flag = 3;
tmos_set_event(press_task_id, BMP390_EVT_READ);
}
}