关于医疗器械的算法、协议开发(一)

本文详细介绍了开发血氧模块的通讯协议驱动、数据解析算法以及接收传输协议处理过程,包括串口通讯的设置、数据校验、握手与自测命令,以及血氧数据的实时解析和连接状态管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

	最近在开发关于呼吸监测仪的血氧模块采集协议及数据处理算法,这里就分享一下关于这期间的一些流程!
	具体步骤分别为
	1.编写关于通讯协议的驱动方式
	2.编写数据协议的解析算法
	3.编写关于协议数据解析后的接收传输协议处理
  1. 首先是了解关于与检测模块的通讯方式:
    比较常见的通讯模式有以下几种:
    UART、UASRT、SPI、I2C、CAN等通讯方式,相关驱动可以去找例程,这里就串口为例:
    以下为串口驱动的应用层:(具体的驱动代码可以参考我的另一篇文章:https://blog.youkuaiyun.com/AN15778423590/article/details/124851445?spm=1001.2014.3001.5502)
#include "SpO2DrvSatex.h"
#include "main.h"
#include "stdint.h"
#include <stdlib.h>

SpO2DrvSatex * SpO2DrvSatex::_instance = NULL;

UART_HandleTypeDef huart2;
uint8_t _rcvBuf[1] = {0};

SpO2DrvSatex::SpO2DrvSatex()
    :_ringBuf(512),_pr(0), _spo2(0), _error(0),_connect(0),_timeoutCnt(0)
{
    _rcvBuf[0] = 0;
    _instance = this;
}

SpO2DrvSatex::~SpO2DrvSatex()
{

}

static void UART2_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (SpO2DrvSatex::Instance())
    {
        SpO2DrvSatex::Instance()->rcvData();
    }
}

static void USART2_MspInit(UART_HandleTypeDef* uartHandle)
{

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(uartHandle->Instance==USART2)
    {
        /* USART2 clock enable */
        __HAL_RCC_USART2_CLK_ENABLE();

        __HAL_RCC_GPIOA_CLK_ENABLE();
        /*
    USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* USER CODE BEGIN USART2_MspInit 1 */
        HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(USART2_IRQn);
        /* USER CODE END USART2_MspInit 1 */
    }
}

static void USART2_MspDeInit(UART_HandleTypeDef* uartHandle)
{

    if(uartHandle->Instance==USART2)
    {

        /* Peripheral clock disable */
        __HAL_RCC_USART2_CLK_DISABLE();

        /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);

        /* USER CODE BEGIN USART2_MspDeInit 1 */
        HAL_NVIC_DisableIRQ(USART2_IRQn);
        /* USER CODE END USART2_MspDeInit 1 */
    }
}

static void MX_USART2_UART_Init(void)
{
    huart2.RxCpltCallback = UART2_RxCpltCallback;                      //Is a function specified for the device
    huart2.MspInitCallback = USART2_MspInit;                           //Is a function specified for the device
    huart2.MspDeInitCallback = USART2_MspDeInit;                       //Is a function specified for the device
    huart2.Instance = USART2;
    huart2.Init.BaudRate = 9600;
    huart2.Init.WordLength = UART_WORDLENGTH_9B;
    huart2.Init.StopBits = UART_STOPBITS_1;
    huart2.Init.Parity = UART_PARITY_ODD;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart2) != HAL_OK)
    {
        Error_Handler();
    }

    huart2.RxCpltCallback = UART2_RxCpltCallback;

}

/*************************************************************
  *Brief:Array checksum calculation
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
int SpO2DrvSatex::CheckSum(uint8_t *buf, int len)
{
    uint8_t sum = 0;

    for(int i = 1; i<len-1; i++)
    {
        sum += buf[i];
    }
    return sum;
}

int SpO2DrvSatex::CheckEstimate(uint8_t *buf, int len)
{	
    uint8_t sum = 0;
    sum = CheckSum(buf,len);
    if(sum != buf[len-1])
    {
        return 1;    //This packet is wrong!
    }
    else
    {
        return 0;
    }
}

void SpO2DrvSatex::rcvData()
{
    _ringBuf.pushData(_rcvBuf[0]);
    _rcvBuf[0] = 0;
    HAL_UART_Receive_IT(&huart2, _rcvBuf, 1);
}

void SpO2DrvSatex::drvInit()
{
    MX_USART2_UART_Init();
    HAL_UART_Receive_IT(&huart2, _rcvBuf, 1);
}

void SpO2DrvSatex::handleEvent(uint8_t *buf, int len)
{
    uint8_t cmdId = buf[4];

    int flag = 0;
    flag = CheckEstimate(buf,len);

    if (flag)
    {
        return;
    }

    _timeoutCnt = 0;
    _connect = 1;
    if (cmdId == 0x81)
    {
        beginHandshake();
        beginSelftest();
    }

    if (cmdId == 0x85)
    {
        _error=buf[14]&0x20;
        _pr =  (buf[10] << 8) | buf[9];
        _spo2 = buf[11];
    }
}

void SpO2DrvSatex::handleProtocol()
{
    int loopCnt = 0;
    while (_ringBuf.length() >= 10)
    {
        loopCnt++;
        if (loopCnt > 50)
            break;

        uint8_t head = _ringBuf[0];
        if (head != 0xFA || _ringBuf[2] != 0x03)
        {
            _ringBuf.popData();
            continue;
        }
        else
        {
            int len = _ringBuf[1];
            if (_ringBuf.length() >= len)
            {
                uint8_t *buf = new uint8_t[len];

                for (int i  =0 ; i <= len ; i++)
                {
                    buf[i] = _ringBuf.popData();
                }

                handleEvent(buf, len);
                delete [] buf;
            }
            else
            {
                break;
            }
        }

    }
}

/*************************************************************
  *Brief:Check whether the blood oxygen module is connected(5s)
  *Arguments:
  *Returns:
  *Author:
  *Date:2021
****************************************************************/
void SpO2DrvSatex::handleConnectStatus()
{
    static int timeOutCnt = 0;
    int32_t cnt = HAL_GetTick();
    if (timeOutCnt == 0)
    {
        timeOutCnt = cnt;
        return;
    }

    if (cnt - timeOutCnt >= 1000)
    {
        timeOutCnt = cnt;
        _timeoutCnt++;
    }

    if (_timeoutCnt >= 5)
    {
        _connect = 0;
    }
}

void SpO2DrvSatex::drvLoopRun()
{
    handleConnectStatus();
    handleProtocol();
}

/*************************************************************
  *Brief:send to Handshake command
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
void SpO2DrvSatex::beginHandshake()
{
    uint8_t _tsiBuf[10]={0xFA,0x0A,0x03,0x01,0x01,0xEE,0x00,0x00,0x00};
    int add = sizeof(_tsiBuf)/sizeof (uint8_t);
    _tsiBuf[9]=CheckSum(_tsiBuf,add);

    for(int i=0;i<10;i++)
    {
        HAL_UART_Transmit(&huart2, &_tsiBuf[i], 10, 100);
        //HAL_Delay(20);
    }
}

/*************************************************************
  *Brief:beginSelftest
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
void SpO2DrvSatex::beginSelftest()
{
    uint8_t _tsiBuf[10]={0xFA,0x0A,0x03,0x02,0x03,0xEE,0x00,0x00,0x00};
    int add = sizeof(_tsiBuf)/sizeof (uint8_t);
    _tsiBuf[9]=CheckSum(_tsiBuf,add);
    for(int i=0;i<10;i++)
    {
        HAL_UART_Transmit(&huart2, &_tsiBuf[i], 10, 100);
        //HAL_Delay(20);
    }
}

uint8_t SpO2DrvSatex::getSelftestResult()
{
    return 0;
}

uint8_t SpO2DrvSatex::setPatient(int type)
{
    uint8_t _tsiBuf[12]={0xFA,0x0A,0x03,0x02,0x04,0xEE,0x00,0x00,0x00};
    int add;
    switch(type)
    {
    case 0:
        _tsiBuf[10]=0x00;                                                            //adult
        add = sizeof(_tsiBuf)/sizeof (uint8_t);
        _tsiBuf[11]=CheckSum(_tsiBuf,add);
        for(int i=0;i<10;i++)
        {
            HAL_UART_Transmit(&huart2, &_tsiBuf[i], 11, 100);
            //HAL_Delay(20);
        }
        break;

    case 1:
        _tsiBuf[10]=0x01;                                                            //kid
        add = sizeof(_tsiBuf)/sizeof (uint8_t);
        _tsiBuf[11]=CheckSum(_tsiBuf,add);
        for(int i=0;i<10;i++)
        {
            HAL_UART_Transmit(&huart2, &_tsiBuf[i], 11, 100);
            //HAL_Delay(20);
        }

        break;
    }

    return 0;
}

uint8_t SpO2DrvSatex::getSpo2()
{
    return _spo2;
}

uint16_t SpO2DrvSatex::getPr()
{
    return _pr;
}

uint8_t SpO2DrvSatex::connectStatus()
{
    if(_connect==0)
    {
        return SpO2_DISCONNECT;
    }
    else
    {
        return SpO2_CONNECT;
    }
}

uint8_t SpO2DrvSatex::errcode()
{
    uint8_t ret = 0;

    if (_error & 0x20)
    {
        ret |= (1 << SpO2Error_Sensor_Falloff);
    }

    if (_error & 0x40)
    {
        ret |= (1 << SpO2Error_Sensor_Falloff);
    }

    return ret;
}

uint8_t SpO2DrvSatex::type()
{
    return SpO2_WIRED;
}


  1. 编写数据协议的解析算法
#include "ProtocolSpO2RawData.h"
#include "ProtocolId.h"
#include "Spo2.h"
#include "PatientManager.h"
#include "Spo2def.h"

ProtocolSpO2RawData::ProtocolSpO2RawData(ProtocolManager *pMng)
    :_ringBuf(2048),_pr(PR_INVALID_VALUE), _spo2(SPO2_INVALID_VALUE), _error(0),_connect(0),_timeoutCnt(0), ProtocolObj(PROTOCOL_ID_SPO2_RAW_DATA, pMng)
{

}

ProtocolSpO2RawData::~ProtocolSpO2RawData()
{

}

int ProtocolSpO2RawData::handleRcvData(uint8_t *data, uint16_t len)
{
    rcvData(data, len);
    return len;
}

int ProtocolSpO2RawData::init()
{
    SysSpO2->registerSpo2Drv(this);
    return 0 ;
}

int ProtocolSpO2RawData::loopRun()
{
    handleConnectStatus();
    handleProtocol();
    return 0;
}

/*************************************************************
  *Brief:Array checksum calculation
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
int ProtocolSpO2RawData::CheckSum(uint8_t *buf, int len)
{
    uint8_t sum = 0;

    for(int i = 1; i < len-1; i++)
    {
        sum += buf[i];
    }
    return sum;
}

int ProtocolSpO2RawData::CheckEstimate(uint8_t *buf, int len)
{
    uint8_t sum = 0;
    sum = CheckSum(buf, len);
    if(sum != buf[len-1])
    {
        return 1;    //This packet is wrong!
    }
    else
    {
        return 0;
    }
}

void ProtocolSpO2RawData::rcvData(uint8_t *buf, int len)
{
    for (int i = 0; i < len ; i++)
    {
        _ringBuf.pushData(buf[i]);
    }
}

void ProtocolSpO2RawData::drvInit()
{

}

void ProtocolSpO2RawData::parseData(uint8_t *buf, int len)
{
    uint8_t cmdId = buf[4];

    int sum = 0;
    sum = CheckSum(buf,len);

    if (sum != buf[len-1])
    {
        return;
    }

    _timeoutCnt = 0;
    _connect = 1;

    if (cmdId == 0x81)
    {
        beginHandshake();
        beginSelftest();
    }

    if (cmdId == 0x85)
    {
        _error=buf[14]&0x20;
        _pr =  (buf[10] << 8) | buf[9];
        _spo2 = buf[11];
    }
}

void ProtocolSpO2RawData::handleProtocol()
{
    int loopCnt = 0;
    while (_ringBuf.length() >= 10)
    {
        loopCnt++;
        if (loopCnt > 50)
            break;
        uint8_t head = _ringBuf[0];
        if (head != 0xFA || _ringBuf[2] != 0x03)
        {
            _ringBuf.popData();
            continue;
        }
        else
        {
            int len = _ringBuf[1];
            if (len == 0)
            {
                _ringBuf.popData();
                continue;
            }
            if (_ringBuf.length() >= len)
            {
                uint8_t *buf = new uint8_t[len];

                for (int i  = 0 ; i < len ; i++)
                {
                    buf[i] = _ringBuf.popData();
                }

                parseData(buf, len);
                delete [] buf;
            }
            else
            {
                break;
            }
        }
    }
}

/*************************************************************
  *Brief:Check whether the blood oxygen module is connected(5s)
  *Arguments:
  *Returns:
  *Author:
  *Date:2021
****************************************************************/
void ProtocolSpO2RawData::handleConnectStatus()
{
    static int timeOutCnt = 0;
    int32_t cnt = HAL_GetTick();
    if (timeOutCnt == 0)
    {
        timeOutCnt = cnt;
        return;
    }

    if (cnt - timeOutCnt >= 1000)
    {
        timeOutCnt = cnt;
        _timeoutCnt++;
    }

    if (_timeoutCnt >= 5)
    {
        _spo2 = SPO2_INVALID_VALUE;
        _pr = PR_INVALID_VALUE;
        _error = 0;
        _connect = 0;
    }
}

void ProtocolSpO2RawData::drvLoopRun()
{
//    handleConnectStatus();
//    handleProtocol();
}

/*************************************************************
  *Brief:send to Handshake command
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
void ProtocolSpO2RawData::beginHandshake()
{
    uint8_t buf[10] = {0xFA,0x0A,0x03,0x01,0x01,0xEE,0x00,0x00,0x00};
    int len = sizeof(buf)/sizeof (uint8_t);
    buf[9] = CheckSum(buf, len);
    sendData(buf, len);
}

/*************************************************************
  *Brief:beginSelftest
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
void ProtocolSpO2RawData::beginSelftest()
{
    uint8_t buf[10] = {0xFA,0x0A,0x03,0x02,0x03,0xEE,0x00,0x00,0x00};
    int len = sizeof(buf)/sizeof (uint8_t);
    buf[9] = CheckSum(buf, len);
    sendData(buf, len);
}

uint8_t ProtocolSpO2RawData::getSelftestResult()
{
    return 0;
}

uint8_t ProtocolSpO2RawData::setPatient(int type)
{
    uint8_t buf[12] = {0xFA,0x0A,0x03,0x02,0x04,0xEE,0x00,0x00,0x00};
    int len = sizeof(buf)/sizeof (uint8_t);;
    switch(type)
    {
    case PatientManager::PATIENT_TYPE_ADULT:
        buf[10] = 0x00;                                                            //adult
        buf[11] = CheckSum(buf, len);
        sendData(buf, len);
        break;

    case PatientManager::PATIENT_TYPE_KID:
        buf[10] = 0x01;                                                            //kid
        buf[11]=CheckSum(buf, len);
        sendData(buf, len);
        break;
    }
    return len;
}

uint8_t ProtocolSpO2RawData::getSpo2()
{
    uint8_t spo2 = _spo2;
    if (_spo2 == 0x7F )
    {
        spo2 = SPO2_INVALID_VALUE;
    }
    return spo2;
}

uint16_t ProtocolSpO2RawData::getPr()
{
    uint16_t pr = _pr;
    if (_pr == 0x1FF)
    {
        pr = PR_INVALID_VALUE;
    };
    return pr;
}

uint8_t ProtocolSpO2RawData::connectStatus()
{
    if(_connect == 0)
    {
        return SpO2_DISCONNECT;
    }
    else
    {
        return SpO2_CONNECT;
    }
}

uint8_t ProtocolSpO2RawData::errcode()
{
    uint8_t ret = 0;

    if (_error & 0x20)
    {
        ret |= (1 << SpO2Error_Sensor_Falloff);
    }

    if (_error & 0x40)
    {
        ret |= (1 << SpO2Error_Sensor_Falloff);
    }

    return ret;
}

uint8_t ProtocolSpO2RawData::type()
{
    return SpO2_WIRED;
}

#include "ProtocolDrvUart.h"
#include "main.h"
#include "ProtocolManager.h"

ProtocolDrvUart * ProtocolDrvUart::_instance = NULL;

UART_HandleTypeDef huart6;

static void UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (ProtocolDrvUart::Instance())
    {
        ProtocolDrvUart::Instance()->receiveData();
    }
}

/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
static void UART_MspInit(UART_HandleTypeDef* huart)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(huart->Instance==USART6)
    {
        /* Peripheral clock enable */
        __HAL_RCC_USART6_CLK_ENABLE();

        __HAL_RCC_GPIOC_CLK_ENABLE();
        /**USART3 GPIO Configuration
        PC6     ------> USART6_TX
        PC7     ------> USART6_RX
        */
        GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        /* USART6 interrupt Init */
        //HAL_NVIC_SetPriority(USART3_IRQn, 6, 0);
        //HAL_NVIC_EnableIRQ(USART3_IRQn);
    }
}

/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
static void UART_MspDeInit(UART_HandleTypeDef* huart)
{
    if(huart->Instance == USART6)
    {
        /* Peripheral clock disable */
        __HAL_RCC_USART6_CLK_DISABLE();

        /**USART6 GPIO Configuration
        PC6     ------> USART6_TX
        PC7     ------> USART6_RX
        */
        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6|GPIO_PIN_7);

        /* USART3 interrupt DeInit */
        HAL_NVIC_DisableIRQ(USART6_IRQn);
    }
}

 static void UARTErrorCallback(struct __UART_HandleTypeDef *huart)
 {
    if (huart->ErrorCode & HAL_UART_ERROR_ORE)
    {
        __HAL_UART_CLEAR_OREFLAG(huart);
    }
    log_info("-------------------error:%d\n", huart->ErrorCode);
 }
/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART6_UART_Init(void)
{
    huart6.MspInitCallback = UART_MspInit;
    huart6.MspDeInitCallback= UART_MspDeInit;
    huart6.Instance = USART6;
    huart6.Init.BaudRate = 38400;
    huart6.Init.WordLength = UART_WORDLENGTH_8B;
    huart6.Init.StopBits = UART_STOPBITS_1;
    huart6.Init.Parity = UART_PARITY_NONE;
    huart6.Init.Mode = UART_MODE_TX_RX;
    huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart6.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart6) != HAL_OK)
    {
        Error_Handler();
    }

    huart6.RxCpltCallback = UART_RxCpltCallback;
    huart6.ErrorCallback = UARTErrorCallback;
}

/*************************************************************
  *Brief:副cpu复位gpio
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
static void CocCpuResetGpioInit()
{
    GPIO_InitTypeDef GPIO_InitStruct;
    __HAL_RCC_GPIOI_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
}

static  void CocCpuReset()
{
    HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3, GPIO_PIN_SET);
    HAL_Delay(2);
    HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3, GPIO_PIN_RESET);
}


ProtocolDrvUart::ProtocolDrvUart()
{
    _rcvBuf[0] = 0;
}

ProtocolDrvUart::~ProtocolDrvUart()
{

}

int ProtocolDrvUart::sendData(uint8_t *buf, uint16_t len)
{
    if (buf)
    {
        int ret = HAL_UART_Transmit(&huart6, buf, len, 100);
        if (ret == HAL_OK)
        {
            return len;
        }
    }
    return -1;
}

void ProtocolDrvUart::protocolDrvInit()
{
    //CocCpuResetGpioInit();
    /*************************************************************
  *Brief:我们主cpu开机在初始化串口通讯时应该将副cpu关闭
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
    //HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3, GPIO_PIN_SET);
    //HAL_Delay(10);
    MX_USART6_UART_Init();
    HAL_NVIC_SetPriority(USART6_IRQn, 6, 0);
    HAL_NVIC_EnableIRQ(USART6_IRQn);
    HAL_UART_Receive_IT(&huart6, _rcvBuf, 1);
    ready();
    _instance = this;
    //HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3, GPIO_PIN_RESET);
}

void ProtocolDrvUart::receiveData()
{
    rcvData(_rcvBuf, 1);
    _rcvBuf[0] = 0;
    HAL_UART_Receive_IT(&huart6, _rcvBuf, 1);
}


  1. 编写关于协议数据解析后的接收传输协议
#include "ProtocolManager.h"
#include "ProtocolHeartBeat.h"
#include "ProtocolAlarm.h"
#include "ProtocolSpo2.h"
#include "ProtocolDrvUart.h"
#include "ProtocolSpO2RawData.h"
#include "ProtocolWireless.h"

ProtocolManager * ProtocolManager::_instance = NULL;

ProtocolManager::ProtocolManager()
    :_circleBuf(2048)
{
    _allProtocolObjs.clear();
    _proDrv = NULL;
    _sendItems.clear();
}

ProtocolManager::~ProtocolManager()
{
    _sendItems.clear();
}

int ProtocolManager::registerProtocol(ProtocolObj *obj)
{
    int ret = 0;

    if (!obj)
    {
        return 1;
    }
     list<ProtocolObj *>::iterator it = _allProtocolObjs.begin();
     for (;it != _allProtocolObjs.end(); it++)
     {
         if (*it == obj)
         {
             ret = 1;
             return ret;
         }
     }

     obj->init();
     _allProtocolObjs.push_back(obj);
     return ret;
}

int ProtocolManager::unregisterProtocol(ProtocolObj *obj)
{
    int ret = 1;
    if (!obj)
    {
        return ret;
    }
     list<ProtocolObj *>::iterator it = _allProtocolObjs.begin();
     for (;it != _allProtocolObjs.end(); it++)
     {
         if (*it == obj)
         {
             ret = 0;
             _allProtocolObjs.erase(it);
             obj->deinit();
             return ret;
         }
     }
     return ret;
}

int ProtocolManager::loopRun()
{
     list<ProtocolObj *>::iterator it = _allProtocolObjs.begin();
     for (;it != _allProtocolObjs.end(); it++)
     {
         ProtocolObj *obj = *it;
         if (obj)
         {
            obj->loopRun();
         }
     }

     handleProtocol();
     handleSendItems();
     return 0;
}

void ProtocolManager::init()
{
    ProtocolDrvUart *drv = new ProtocolDrvUart();
    setProDrv(drv);

    ProtocolHeartBeat *pHeartBeat = new ProtocolHeartBeat(this);
    registerProtocol(pHeartBeat);

    ProtocolAlarm *pAlarm = new ProtocolAlarm(this);
    registerProtocol(pAlarm);

#if 0
    ProtocolSpo2 *pSpo2 = new ProtocolSpo2(this);
    registerProtocol(pSpo2);
#endif

    ProtocolSpO2RawData *pSpo2RawData = new ProtocolSpO2RawData(this);
    registerProtocol(pSpo2RawData);

    ProtocolWireless *pWireless = new ProtocolWireless(this);
    registerProtocol(pWireless);
}

void ProtocolManager::setProDrv(ProtocolDrv *drv)
{
    if (drv)
    {
        drv->protocolDrvInit();
        _proDrv = drv;
    }
}

int ProtocolManager::checkData(uint8_t *buf, int len)
{
    int sum = 0;
    for (int i = 0; i < len; i++)
    {
        sum += buf[i];
    }

    return sum;
}

#if 0
void ProtocolManager::handleProtocol()
{
//    int leng = _circleBuf.length();
//    for (int i = 0; i < leng; i++)
//    {
//        uint8_t ch = _circleBuf[i];
//        log_info("+++:0x%p %d\n", ch, leng);
//    }
//    return;
#if 0
    while (_circleBuf.length())
    {
        uint8_t c = _circleBuf.popData();
        log_info("----------------:%c\n", c);
    }
#endif
    int loopCnt = 0;
    while (_circleBuf.length() >= 7)
    {
        //log_info("+++++++++++++++++++:%d\n", _circleBuf.length());
        loopCnt++;
        if (loopCnt >= 50)
        {
            break;//防止出现死循环
        }
        uint8_t startCh = _circleBuf[0];
        if (startCh == 0xAA)
        {
            uint16_t len = (_circleBuf[3] << 8) | _circleBuf[4];
            //log_info("++++++++++:%d %d %d %d\n", _circleBuf[3], _circleBuf[4], _circleBuf.length(), len);
            //这里存在一个风险,如果数据长度即 _circleBuf[3]_circleBuf[4]数据错位那么就会导致我们buff存满永远处理不了数据
            //例如我们循环队列长度是2048 但是len解析出来是4096 那么就会出现错误
            //所以我们这里给buffer一个阀值
            //如果这包协议中len的长度超出我们的这个值就将数据推出buffer
            if (len > 500)
            {
                _circleBuf.popData();
                continue;
            }
            if (_circleBuf.length() < len + 7)
            {
                break;
            }
            else
            {
                uint8_t *buf = new uint8_t[len + 7];
                for (int i = 0; i < len + 7; i++)
                {
                    buf[i] = _circleBuf.popData();
                }
                int checkRcv = (buf[len + 5] << 8) | buf[len+6];
                int checkRes = checkData(&buf[5], len);
                if (checkRcv != checkRes)
                {
                    log_info("Rcv an invalid packet\n");
                }
                else
                {
                    uint16_t cmd = (buf[1] << 8) | buf[2];
                    list<ProtocolObj *>::iterator it = _allProtocolObjs.begin();
                    for (; it != _allProtocolObjs.end(); it++)
                    {
                        ProtocolObj *obj = *it;
                        if (obj)
                        {
                            if (obj->getId() == cmd)
                            {
                                obj->handleRcvData(&buf[5], len);
                            }
                        }
                    }
                }
                delete [] buf;
            }
        }
        else
        {
            //无效的头部信息
            _circleBuf.popData();
        }
    }
}
#endif

void ProtocolManager::handleProtocol()
{
    int loopCnt = 0;
    while (_circleBuf.length() >= 7)
    {
        loopCnt++;
        if (loopCnt >= 50)
        {
            break;//防止出现死循环
        }
        uint8_t startCh1 = _circleBuf[0];
        uint8_t startCh2 = _circleBuf[1];
        if (startCh1 == 0xAA && startCh2 == 0xFF)
        {
            uint16_t len = (_circleBuf[3] << 8) | _circleBuf[4];
            //这里存在一个风险,如果数据长度即 _circleBuf[3]_circleBuf[4]数据错位那么就会导致我们buff存满永远处理不了数据
            //例如我们循环队列长度是2048 但是len解析出来是4096 那么就会出现错误
            //所以我们这里给buffer一个阀值
            //如果这包协议中len的长度超出我们的这个值就将数据推出buffer
            if (len > 500)
            {
                _circleBuf.popData();
                continue;
            }
            if (_circleBuf.length() < len + 7)
            {
                break;
            }
            else
            {
                uint8_t *buf = new uint8_t[len + 7];
                for (int i = 0; i < len + 7; i++)
                {
                    //buf[i] = _circleBuf.popData();
                    buf[i] = _circleBuf[i];
                }
                int checkRcv = (buf[len + 5] << 8) | buf[len+6];
                int checkRes = checkData(&buf[5], len);
                if (checkRcv != checkRes)
                {
                    _circleBuf.popData();
                    log_info("Rcv an invalid packet\n");
                }
                else
                {
                    for (int i = 0; i < len + 7; i++)
                    {
                        _circleBuf.popData();
                    }
                    uint16_t cmd = buf[2];
                    list<ProtocolObj *>::iterator it = _allProtocolObjs.begin();
                    for (; it != _allProtocolObjs.end(); it++)
                    {
                        ProtocolObj *obj = *it;
                        if (obj)
                        {
                            if (obj->getId() == cmd)
                            {
                                obj->handleRcvData(&buf[5], len);
                            }
                        }
                    }
                }
                delete [] buf;
            }
        }
        else
        {
            //无效的头部信息
            _circleBuf.popData();
        }
    }
}

#if 0
void ProtocolManager::handleSendItems()
{
#if 1
    /*************************************************************
  *Brief:如果_proDrv一直为空,那么_sendItems就会一直累计
  * 可能会导致内存爆掉,但是我们系统是不允许这种情况出现的
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
    if (!_proDrv)
        return;
#endif
    int loopCnt = 0;
    while(!_sendItems.empty())
    {
        loopCnt++;
        if (loopCnt > 10)
            break;
        list<ProtocolSendItem *>::iterator it = _sendItems.begin();
        ProtocolSendItem *item = *it;
        _lock.lock();
        _sendItems.erase(it);
        _lock.unlock();
        if (_proDrv)
            _proDrv->sendData(item->buf, item->len);
        delete [] item->buf;
        delete item;
    }
}
#endif

void ProtocolManager::handleSendItems()
{
#if 1
    /*************************************************************
  *Brief:如果_proDrv一直为空,那么_sendItems就会一直累计
  * 可能会导致内存爆掉,但是我们系统是不允许这种情况出现的
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
    if (!_proDrv)
        return;
#endif
    static int tick = 0;
    int curTick = HAL_GetTick();
    if (curTick - tick < 100)
    {
        return;
    }

    tick = curTick;

    if(!_sendItems.empty())
    {
        list<ProtocolSendItem *>::iterator it = _sendItems.begin();
        ProtocolSendItem *item = *it;
        _lock.lock();
        _sendItems.erase(it);
        _lock.unlock();
        _proDrv->sendData(item->buf, item->len);
        delete [] item->buf;
        delete item;
    }
}

#if 0
int ProtocolManager::sendData(uint8_t *buf, uint16_t len, uint16_t cmd)
{
    if (buf)
    {
        uint16_t sum = 0;
        uint16_t sendLen = 1 + 2 + 2 + len + 2; //查看协议文档
        uint8_t *sendBuf = new uint8_t[sendLen];
        sendBuf[0] = 0xAA;
        sendBuf[1] = (cmd & 0xFF00)>>8;
        sendBuf[2] = (cmd & 0xFF);

        sendBuf[3] = (len & 0xFF00)>>8;
        sendBuf[4] = (len & 0xFF);

        for (int i = 0; i < len; i++)
        {
            sendBuf[5+ i] = buf[i];
            sum += buf[i];
        }

        sendBuf[5 + len] = (sum & 0xFF00)>>8;
        sendBuf[5 + len + 1] = (sum & 0xFF);
#if 0
        if (_proDrv && _proDrv->isReady())
            _proDrv->sendData(sendBuf, sendLen);
        delete sendBuf;
        return len;
#endif
        /*************************************************************
  *Brief:多线程发送数据不能直接发送
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
        ProtocolSendItem *item = new ProtocolSendItem;
        item->buf = sendBuf;
        item->len = sendLen;
        _lock.lock();
        _sendItems.push_back(item);
        _lock.unlock();
        return len;
    }
    return 0;
}
#endif

int ProtocolManager::sendData(uint8_t *buf, uint16_t len, uint8_t cmd)
{
    if (buf)
    {
        uint16_t sum = 0;
        uint16_t sendLen = 1 + 2 + 2 + len + 2; //查看协议文档
        uint8_t *sendBuf = new uint8_t[sendLen];
        sendBuf[0] = 0xAA;
        sendBuf[1] = 0xFF;
        sendBuf[2] = cmd;
        sendBuf[3] = (len & 0xFF00)>>8;
        sendBuf[4] = (len & 0xFF);
        for (int i = 0; i < len; i++)
        {
            sendBuf[5+ i] = buf[i];
            sum += buf[i];
        }
        sendBuf[5 + len] = (sum & 0xFF00)>>8;
        sendBuf[5 + len + 1] = (sum & 0xFF);
#if 0
        if (_proDrv && _proDrv->isReady())
            _proDrv->sendData(sendBuf, sendLen);
        delete sendBuf;
        return len;
#endif
/*************************************************************
  *Brief:多线程发送数据不能直接发送
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
        ProtocolSendItem *item = new ProtocolSendItem;
        item->buf = sendBuf;
        item->len = sendLen;
        _lock.lock();
        _sendItems.push_back(item);
        _lock.unlock();
        return len;
    }
    return 0;
}

int ProtocolManager::rcvData(uint8_t *buf, uint16_t len)
{
    int ret = 0;
    if (buf)
    {
        for (int i = 0; i < len; i++)
        {
            _circleBuf.pushData(buf[i]);
        }
        ret = len;
    }
    return ret;
}

#include "ProtocolSpO2RawData.h"
#include "ProtocolId.h"
#include "Spo2.h"
#include "PatientManager.h"
#include "Spo2def.h"

ProtocolSpO2RawData::ProtocolSpO2RawData(ProtocolManager *pMng)
    :_ringBuf(2048),_pr(PR_INVALID_VALUE), _spo2(SPO2_INVALID_VALUE), _error(0),_connect(0),_timeoutCnt(0), ProtocolObj(PROTOCOL_ID_SPO2_RAW_DATA, pMng)
{

}

ProtocolSpO2RawData::~ProtocolSpO2RawData()
{

}

int ProtocolSpO2RawData::handleRcvData(uint8_t *data, uint16_t len)
{
    rcvData(data, len);
    return len;
}

int ProtocolSpO2RawData::init()
{
    SysSpO2->registerSpo2Drv(this);
    return 0 ;
}

int ProtocolSpO2RawData::loopRun()
{
    handleConnectStatus();
    handleProtocol();
    return 0;
}

/*************************************************************
  *Brief:Array checksum calculation
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
int ProtocolSpO2RawData::CheckSum(uint8_t *buf, int len)
{
    uint8_t sum = 0;

    for(int i = 1; i < len-1; i++)
    {
        sum += buf[i];
    }
    return sum;
}

int ProtocolSpO2RawData::CheckEstimate(uint8_t *buf, int len)
{
    uint8_t sum = 0;
    sum = CheckSum(buf, len);
    if(sum != buf[len-1])
    {
        return 1;    //This packet is wrong!
    }
    else
    {
        return 0;
    }
}

void ProtocolSpO2RawData::rcvData(uint8_t *buf, int len)
{
    for (int i = 0; i < len ; i++)
    {
        _ringBuf.pushData(buf[i]);
    }
}

void ProtocolSpO2RawData::drvInit()
{

}

void ProtocolSpO2RawData::parseData(uint8_t *buf, int len)
{
    uint8_t cmdId = buf[4];

    int sum = 0;
    sum = CheckSum(buf,len);

    if (sum != buf[len-1])
    {
        return;
    }

    _timeoutCnt = 0;
    _connect = 1;

    if (cmdId == 0x81)
    {
        beginHandshake();
        beginSelftest();
    }

    if (cmdId == 0x85)
    {
        _error=buf[14]&0x20;
        _pr =  (buf[10] << 8) | buf[9];
        _spo2 = buf[11];
    }
}

void ProtocolSpO2RawData::handleProtocol()
{
    int loopCnt = 0;
    while (_ringBuf.length() >= 10)
    {
        loopCnt++;
        if (loopCnt > 50)
            break;
        uint8_t head = _ringBuf[0];
        if (head != 0xFA || _ringBuf[2] != 0x03)
        {
            _ringBuf.popData();
            continue;
        }
        else
        {
            int len = _ringBuf[1];
            if (len == 0)
            {
                _ringBuf.popData();
                continue;
            }
            if (_ringBuf.length() >= len)
            {
                uint8_t *buf = new uint8_t[len];

                for (int i  = 0 ; i < len ; i++)
                {
                    buf[i] = _ringBuf.popData();
                }

                parseData(buf, len);
                delete [] buf;
            }
            else
            {
                break;
            }
        }
    }
}

/*************************************************************
  *Brief:Check whether the blood oxygen module is connected(5s)
  *Arguments:
  *Returns:
  *Author:
  *Date:2021
****************************************************************/
void ProtocolSpO2RawData::handleConnectStatus()
{
    static int timeOutCnt = 0;
    int32_t cnt = HAL_GetTick();
    if (timeOutCnt == 0)
    {
        timeOutCnt = cnt;
        return;
    }

    if (cnt - timeOutCnt >= 1000)
    {
        timeOutCnt = cnt;
        _timeoutCnt++;
    }

    if (_timeoutCnt >= 5)
    {
        _spo2 = SPO2_INVALID_VALUE;
        _pr = PR_INVALID_VALUE;
        _error = 0;
        _connect = 0;
    }
}

void ProtocolSpO2RawData::drvLoopRun()
{
//    handleConnectStatus();
//    handleProtocol();
}

/*************************************************************
  *Brief:send to Handshake command
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
void ProtocolSpO2RawData::beginHandshake()
{
    uint8_t buf[10] = {0xFA,0x0A,0x03,0x01,0x01,0xEE,0x00,0x00,0x00};
    int len = sizeof(buf)/sizeof (uint8_t);
    buf[9] = CheckSum(buf, len);
    sendData(buf, len);
}

/*************************************************************
  *Brief:beginSelftest
  *Arguments:
  *Returns:
  *Author:xiaoyetongxue
  *Date:2021
****************************************************************/
void ProtocolSpO2RawData::beginSelftest()
{
    uint8_t buf[10] = {0xFA,0x0A,0x03,0x02,0x03,0xEE,0x00,0x00,0x00};
    int len = sizeof(buf)/sizeof (uint8_t);
    buf[9] = CheckSum(buf, len);
    sendData(buf, len);
}

uint8_t ProtocolSpO2RawData::getSelftestResult()
{
    return 0;
}

uint8_t ProtocolSpO2RawData::setPatient(int type)
{
    uint8_t buf[12] = {0xFA,0x0A,0x03,0x02,0x04,0xEE,0x00,0x00,0x00};
    int len = sizeof(buf)/sizeof (uint8_t);;
    switch(type)
    {
    case PatientManager::PATIENT_TYPE_ADULT:
        buf[10] = 0x00;                                                            //adult
        buf[11] = CheckSum(buf, len);
        sendData(buf, len);
        break;

    case PatientManager::PATIENT_TYPE_KID:
        buf[10] = 0x01;                                                            //kid
        buf[11]=CheckSum(buf, len);
        sendData(buf, len);
        break;
    }
    return len;
}

uint8_t ProtocolSpO2RawData::getSpo2()
{
    uint8_t spo2 = _spo2;
    if (_spo2 == 0x7F )
    {
        spo2 = SPO2_INVALID_VALUE;
    }
    return spo2;
}

uint16_t ProtocolSpO2RawData::getPr()
{
    uint16_t pr = _pr;
    if (_pr == 0x1FF)
    {
        pr = PR_INVALID_VALUE;
    };
    return pr;
}

uint8_t ProtocolSpO2RawData::connectStatus()
{
    if(_connect == 0)
    {
        return SpO2_DISCONNECT;
    }
    else
    {
        return SpO2_CONNECT;
    }
}

uint8_t ProtocolSpO2RawData::errcode()
{
    uint8_t ret = 0;

    if (_error & 0x20)
    {
        ret |= (1 << SpO2Error_Sensor_Falloff);
    }

    if (_error & 0x40)
    {
        ret |= (1 << SpO2Error_Sensor_Falloff);
    }

    return ret;
}

uint8_t ProtocolSpO2RawData::type()
{
    return SpO2_WIRED;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值