current_v/Src/o2_sensor.c
2025-12-31 08:21:43 +08:00

319 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file o2_sensor.c
* @author Motor Control SDK Team, Yuwell Software XiangenWang
* @brief Voice Recognition Module Initialization Section,
including peripheral initialization and message node insertion, etc.
* @version 1.0
* @changelog version 1.0 初始版本 2025.11.21
- 新增:新建第一个版本的软件,待完善解析命令后的程序执行部分
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2025 Yuwell Software Danyang.Jiangsu.China.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Yuwell Software nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for Yuwell Software.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY Yuwell Software AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL Yuwell Software OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* USER CODE END Header */
#include "o2_sensor.h"
#include "string.h"
// 存储氧传感器数据
O2SensorData o2_sensor_data;
#define REQUEST_FRAME_LENGTH (4)
#define OXG_FAULT_MAX (30)
/**
* @brief 向氧传感器发送数据请求指令
* @param NONE
* @retval NONE
* @note 1. 固定发送请求帧:{0x11, 0x01, 0x01, 0xED}帧长度由REQUEST_FRAME_LENGTH宏定义
* 2. 通过OXG_UART_TRANS_BYTE函数逐字节发送数据依赖UART外设已初始化完成
* @author jarvis
* @date 2025.11.25
*/
void oxg_sensor_task(void)
{
const uint8_t sendDate[REQUEST_FRAME_LENGTH] = {0x11, 0x01, 0x01, 0xED};
for(uint8_t i = 0;i < REQUEST_FRAME_LENGTH; i++)
{
OXG_UART_TRANS_BYTE(sendDate[i]);
}
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
if(!xOxygenEventGroupCheckBit(&global_event, EVENT_O2_SENSOR_ERROR)) // 若当前未发生传感器故障
{
o2_sensor_data.fault_count++;
if(o2_sensor_data.fault_count > OXG_FAULT_MAX)
{
vOxygenEventGroupSetBits(&global_event, EVENT_O2_SENSOR_ERROR); // 标志当前已发生氧传感器故障信号
}
}
}
/**
* @brief 初始化氧传感器故障计数器
* @param NONE
* @retval NONE
* @note NONE
* @author jarvis
* @date 2025.11.25
*/
void oxg_sensor_init(void)
{
FL_GPIO_InitTypeDef GPIO_InitStruct;
o2_sensor_data.fault_count = 0;
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
/* 氧传感器初始化 */
GPIO_InitStruct.pin = FL_GPIO_PIN_4|FL_GPIO_PIN_5;
GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.pull = FL_DISABLE;
GPIO_InitStruct.remapPin = FL_DISABLE;
GPIO_InitStruct.analogSwitch = FL_DISABLE;
FL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// 需要单独拿出来初始化 因为时钟初始化的比较晚
FL_UART_InitTypeDef UART_InitStruct = {0};
UART_InitStruct.baudRate = 9600; //波特率
UART_InitStruct.dataWidth = FL_UART_DATA_WIDTH_8B; //数据位数
UART_InitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B; //停止位
UART_InitStruct.parity = FL_UART_PARITY_NONE; //奇偶校验
UART_InitStruct.transferDirection = FL_UART_DIRECTION_TX_RX; //接收-发送使能
FL_UART_Init(UART5, &UART_InitStruct);
NVIC_DisableIRQ(UART5_IRQn);
NVIC_SetPriority(UART5_IRQn,2);//中断优先级配置
NVIC_EnableIRQ(UART5_IRQn);
FL_UART_ClearFlag_RXBuffFull(UART5);
FL_UART_EnableIT_RXBuffFull(UART5);
FL_UART_ClearFlag_TXShiftBuffEmpty(UART5);
}
/**
* @brief 解析氧传感器接收的原始数据
* @param p_o2_frame - O2SensorData类型指针指向存储原始数据和解析结果的结构体
* @retval NONE
* @note 1. 氧浓度 = DF[0]*256 + DF[1]16位无符号数据拼接
* 2. 氧流量 = DF[2]*256 + DF[3]16位无符号数据拼接
* 3. 温度解析功能默认注释禁用,如需启用可取消#if 0宏定义
* 4. 需确保p_o2_frame指针非空且O2_raw_data.DF数组已存储有效原始数据
* @author jarvis
* @date 2025.11.25
*/
static void o2_data_decode(O2SensorData* p_o2_frame)
{
MsgQueueItem queue_item;
// 计算氧传感器的氧浓度
p_o2_frame->o2_concentration = p_o2_frame->O2_raw_data.DF[0]*256+p_o2_frame->O2_raw_data.DF[1];
// 计算氧浓度的流量值
p_o2_frame->o2_flow = p_o2_frame->O2_raw_data.DF[2]*256+p_o2_frame->O2_raw_data.DF[3];
// 向队列中插入一条氧传感器数据
queue_item.type = MSG_TYPE_OXYGEN_SENSOR;
queue_item.data.oxygen.concentration = p_o2_frame->o2_concentration;
queue_item.data.oxygen.flow_rate = p_o2_frame->o2_flow;
modify_or_add_queue_node_by_type(&global_queue, queue_item.type, queue_item); // 修改队列中的浓度数据
if(xOxygenEventGroupCheckBit(&global_event, EVENT_O2_SENSOR_ERROR)) // 若当前存在错误标志则清空故障
{
vOxygenEventGroupClearBits(&global_event, EVENT_O2_SENSOR_ERROR);
o2_sensor_data.fault_count = 0;
}
}
/**
* @brief 氧传感器数据接收字节处理函数(状态机实现)
* @param byte - 从UART接收的单个字节数据
* @retval NONE
* @note 1. 采用状态机处理帧接收等待帧头1(0x16)→等待帧头2(0x09)→等待帧头3(0x01)→接收数据→校验帧
* 2. 数据段长度固定为8字节DF_DATE_LENGTH=8接收完成后进行求和校验
* 3. 校验逻辑sum=0x16+0x09+0x01+8字节数据 → 校验和=256-sum与接收的校验字节比对
* 4. 校验成功后更新帧状态为O2_FRAME_COMPLETE并调用o2_data_decode解析数据
* 5. 依赖全局变量o2_sensor_data存储接收状态、帧状态和原始数据
* @author jarvis
* @date 2025.11.25
*/
static void request_o2_byte_process(uint8_t byte)
{
static uint8_t wait_data_count = 0;
const uint8_t DF_DATE_LENGTH = 8;
uint8_t check_sum = 0;
switch(o2_sensor_data.receive_state)
{
case O2_STATE_WAIT_HEADER1:
if(byte == 0x16)
{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER2;
o2_sensor_data.frame_state = O2_FRAME_RECEIVING;
}else{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
}
break;
case O2_STATE_WAIT_HEADER2:
if(byte == 0x09)
{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER3;
}else{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
}
break;
case O2_STATE_WAIT_HEADER3:
if(byte == 0x01)
{
o2_sensor_data.receive_state = O2_STATE_RECV_DATA;
wait_data_count = 0;
memset(o2_sensor_data.O2_raw_data.DF, 0, sizeof(o2_sensor_data.O2_raw_data.DF)); // 清空缓存
}else{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
}
break;
case O2_STATE_RECV_DATA:
o2_sensor_data.O2_raw_data.DF[wait_data_count] = byte;
wait_data_count++;
if(wait_data_count == DF_DATE_LENGTH)
{
o2_sensor_data.receive_state = O2_STATE_CHECK_FRAME;
}
break;
case O2_STATE_CHECK_FRAME:
check_sum = 0x16 + 0x09 + 0x01 + o2_sensor_data.O2_raw_data.DF[0] +\
o2_sensor_data.O2_raw_data.DF[1] + o2_sensor_data.O2_raw_data.DF[2] + \
o2_sensor_data.O2_raw_data.DF[3] + o2_sensor_data.O2_raw_data.DF[4] + \
o2_sensor_data.O2_raw_data.DF[5] + o2_sensor_data.O2_raw_data.DF[6] + o2_sensor_data.O2_raw_data.DF[7];
check_sum = 256 - check_sum;
if(check_sum == byte) // 对数据进行校验 校验合格之后对数据进行处理
{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
o2_sensor_data.frame_state = O2_FRAME_COMPLETE;
o2_data_decode(&o2_sensor_data);
}else{
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1;
o2_sensor_data.frame_state = O2_FRAME_IDLE;
}
break;
default:
o2_sensor_data.frame_state = O2_FRAME_IDLE;
o2_sensor_data.receive_state = O2_STATE_WAIT_HEADER1; // 默认状态下将状态机改为原始状态
}
}
/**
* @brief UART5接收中断服务函数
* @param NONE
* @retval NONE
* @note 1. 中断触发条件UART5接收缓冲区非空RXBuffFull中断
* 2. 读取接收字节后调用request_o2_byte_process函数进行状态机处理
* 3. 静态变量count未实际使用可根据需求保留或删除
* 4. 需提前配置UART5接收中断使能确保FL_UART相关驱动函数已实现
* @author jarvis
* @date 2025.11.25
*/
void UART5_IRQHandler(void)
{
uint8_t temp_data;
if((FL_ENABLE == FL_UART_IsEnabledIT_RXBuffFull(O2_SENSOR_USED_UART_NUM))
&&(FL_SET == FL_UART_IsActiveFlag_RXBuffFull(O2_SENSOR_USED_UART_NUM)))
{
temp_data = FL_UART_ReadRXBuff(O2_SENSOR_USED_UART_NUM);
request_o2_byte_process(temp_data);
}
}
/************************ (C) COPYRIGHT YUWELL *****END OF FILE****/