319 lines
10 KiB
C
319 lines
10 KiB
C
/* 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>© 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****/
|