#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); } }