记录串口数据命令提取 -- STM32

#include "usartDeal.h"
#include "stdlib.h"
#include "usart.h"
#include "string.h"
//Edit time: 2019-03-20 
//author   : Wenkic
/* .h 定义宏
#define USARTDEALPenetrate(Soure)  Soure->Usart_Flag.Penetrate    //开启的模式  透传模式开关(0:关 1:开)
#define USARTDEALOKFlag(Soure)     Soure->Usart_Flag.PackOKFlag   //检查OK标志  提取包标志
#define USARTDEALCmdBuff(Soure)    Soure->Usart_CmdBuff.Cmd_Buff  //命令缓存Buff
#define USARTDEALCmdLen(Soure)     Soure->Usart_CmdBuff.Cmd_Len   //命令缓存Buff长度
#define USARTDEALTimeOut(Soure)    Soure->Usart_CmdBuff.TimeOutMS //超时时间

#define USARTDEALFormHead(Soure)   Soure->Usart_Form.head         //命令格式包头
#define USARTDEALFormEnd(Soure)    Soure->Usart_Form.End          //命令格式包尾

//使用 判断标志是否等1 ,使用完,就清除寻找下一条命令格式
      if(USARTDEALOKFlag(Uart1Dat) == 1)
			{
				 Usart_SendString(COM1, (u8*)USARTDEALCmdBuff(Uart1Dat),USARTDEALCmdLen(Uart1Dat) );
				 USARTDEALOKFlag(Uart1Dat) = 0;
			}

*/
#if 0  //.h 定义的数据结构
/*
//数据的格式
*/
typedef struct _Usart_Form
{
    __IO uint8_t  headByteSize;   //包头字节数
    __IO uint8_t *head;           //包头
    __IO uint8_t  EndByteSize;	  //包尾字节数
    __IO uint8_t *End;            //包尾
    __IO uint8_t  DLenAddr;       //数据长度位(初始)
    __IO uint8_t  OtherLen;       //除去数据包后剩余的字节
} Usart_FormType,*pUsart_FormType;
/*
//数据包
*/
typedef struct _Usart_RxBuff
{
    __IO uint16_t Rx_BuffSize;         //缓存数据包的大小
    __IO uint8_t *Rx_Buff;    				 //接受数据包
    __IO uint16_t BuffWptr;            //写指针
    __IO uint16_t BuffRptr;	           //读指针

} Usart_RxBuffType,*pUsart_RxBuffType;
/*
//命令包
*/
typedef struct _Usart_CmdBuff
{
    __IO uint16_t Cmd_BuffSize;        //提取命令数据包大小
    __IO uint8_t *Cmd_Buff;   				 //存放提取命令数组
    __IO uint16_t Cmd_Len;             //提取命令数据包大小
    __IO uint16_t CacheSize;           //数据剩余量
    __IO uint16_t TimeOutMS;           //计算超时时间
} Usart_CmdBuffType,*pUsart_CmdBuffType;
/*
//==标志,模式
*/
typedef struct _Usart_Flag
{
    __IO uint8_t PackOKFlag;           //提取包标志
    __IO uint8_t Penetrate;            //透传模式开关(0:关 1:开)
} Usart_FlagType,*pUsart_FlagType;

typedef struct _Usart_Dat   //串口数据处理
{
    Usart_FormType     Usart_Form;     //数据命令的格式
    Usart_RxBuffType   Usart_RxBuff;   //缓存数据包
    Usart_CmdBuffType  Usart_CmdBuff;  //命令提取数据包
    Usart_FlagType     Usart_Flag   ;  //标记
} USARTDEALTYPE,*pUSARTDEALTYPE;
#endif




pUSARTDEALTYPE Uart1Dat = NULL;  //创建结构指针
//公开函数
void UsartDealInit(void);     /*上电初始化*/
void UsartDealTime1ms(void);  /*放入1ms定时器*/

//私有函数
pUSARTDEALTYPE UsartDatCreateInit(void); //初始化数据结构
void UsartDatDel(pUSARTDEALTYPE temp);   //释放内存
void UsartDataParse(pUSARTDEALTYPE Soure);/*命令提取*/
void UsartDatWrite(pUSARTDEALTYPE Dat, u8 Data);/*环形数据写*/


/*
思路(缓存区):
  1>一个数据环形缓存区
  2>环形缓存区写函数, 如果数据超前,会覆盖就的数据
  3>环形缓存区读函数
思路(数据结构)
  1>提取命令格式,包头,包头大小,包尾,包尾大小,数据包大小的位置,剩余长度
	2>缓存区结构,缓存区,缓存区大小,缓存写指针,缓存读指针
	3>提取命令结构, 命令缓存,命令缓存区大小,缓存数,提取超时计数,数据剩余量
  4>命令标志结构, 提取成功标志,是否透传数据标志,
思路(命令提取)
  1>是否是透传模式
  2>透传模式,有数据就提取,直到无数据为止
  3>非透传模式(命令提取模式)
	  1)检测起始包头字节,开始超时赋值
		2)检测多字节包头
		3)等待到数据包长度位,计算总长度
		4)接收总长度数据
		5)完成后,向后回推包尾的位置,检测包尾是否相同,相同就判断提取成功
		6)成功后,标志置位,清除超时时间
*/

void USART2_IRQHandler(void)
{
    u8 res = 0;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
    {
        res = USART_ReceiveData(USART2);
        UsartDatWrite( Uart1Dat, res);    //环形数据缓存
    }
}

/*上电初始化*/
void UsartDealInit(void)
{
    Uart1Dat = UsartDatCreateInit();  //创建对象
}

/*放入1ms定时器*/
void UsartDealTime1ms(void)
{
    if(Uart1Dat->Usart_CmdBuff.TimeOutMS)
    {
        Uart1Dat->Usart_CmdBuff.TimeOutMS--;    //超时计算
    }
    /*命令提取*/
    UsartDataParse(Uart1Dat);
}



//数据包创建与初始化
pUSARTDEALTYPE UsartDatCreateInit(void)
{
    pUSARTDEALTYPE temp = (pUSARTDEALTYPE)malloc(sizeof(USARTDEALTYPE));
    COM_Printf(2, "pUSARTDEALTYPE sizeof = %d \r\n", sizeof(USARTDEALTYPE));

    if(temp == NULL)
    {
        COM_Printf(2, "err file = \"%s\" ,line = \"%d\"\r\n", (uint8_t *)__FILE__, __LINE__);
    }
    temp->Usart_Form.headByteSize = 2;  //包头的长度
    temp->Usart_Form.head = malloc(temp->Usart_Form.headByteSize);
    if(temp->Usart_Form.head == NULL)
    {
        COM_Printf(2, "err file = \"%s\" ,line = \"%d\"\r\n", (uint8_t *)__FILE__, __LINE__);
    }
    temp->Usart_Form.head[0] = 0xAD;    //包头
    temp->Usart_Form.head[1] = 0xDA;
    temp->Usart_Form.EndByteSize  = 2;  //包尾长度
    temp->Usart_Form.End  = malloc(temp->Usart_Form.EndByteSize);
    if(temp->Usart_Form.End == NULL)
    {
        COM_Printf(2, "err file = \"%s\" ,line = \"%d\"\r\n", (uint8_t *)__FILE__, __LINE__);
    }
    temp->Usart_Form.End[0] = 0xDA ;	  //包尾
    temp->Usart_Form.End[1] = 0xAD ;
    temp->Usart_Form.DLenAddr     = 2;	//数据包长度的位置--->修改(注意是0开始)
    temp->Usart_Form.OtherLen     = 5;	//剩余长度 -->修改

    temp->Usart_RxBuff.Rx_BuffSize   = 200; //接收的缓存
    temp->Usart_RxBuff.Rx_Buff       = malloc(temp->Usart_RxBuff.Rx_BuffSize);
    if(temp->Usart_RxBuff.Rx_Buff == NULL)
    {
        COM_Printf(2, "err file = \"%s\" ,line = \"%d\"\r\n", (uint8_t *)__FILE__, __LINE__);
    }
    temp->Usart_RxBuff.BuffRptr      = 0;
    temp->Usart_RxBuff.BuffWptr      = 0;
    temp->Usart_CmdBuff.Cmd_BuffSize = 100; //命令提取缓存
    temp->Usart_CmdBuff.Cmd_Buff     = malloc(temp->Usart_CmdBuff.Cmd_BuffSize);
    if(temp->Usart_CmdBuff.Cmd_Buff  == NULL)
    {
        COM_Printf(2, "err file = \"%s\" ,line = \"%d\"\r\n", (uint8_t *)__FILE__, __LINE__);
    }
    temp->Usart_CmdBuff.Cmd_Len      = 0;   //命令长度
    temp->Usart_CmdBuff.CacheSize    = 0;   //剩余数据
    temp->Usart_Flag.PackOKFlag      = 0;   //提取是否成功
    temp->Usart_Flag.Penetrate       = 0;   //0:关闭透传 1:开启透传
    return temp;
}
//数据包对象释放
void UsartDatDel(pUSARTDEALTYPE temp)
{
    if(temp == NULL)
    {
        return;
    }
    if(temp->Usart_Form.head != NULL)
    {
        free((u8 *)temp->Usart_Form.head);    //释放包头
    }
    if(temp->Usart_Form.End  != NULL)
    {
        free((u8 *)temp->Usart_Form.End);    //释放包尾
    }
    if(temp->Usart_RxBuff.Rx_Buff != NULL)
    {
        free((u8 *)temp->Usart_RxBuff.Rx_Buff);
    }
    if(temp->Usart_CmdBuff.Cmd_Buff != NULL)
    {
        free((u8 *)temp->Usart_CmdBuff.Cmd_Buff);
    }
    free(temp);
}


/*环形数据写*/
void UsartDatWrite(pUSARTDEALTYPE Dat, u8 Data)
{

    static u16 Cnt = 0;
    if(Dat->Usart_RxBuff.BuffWptr == (Dat->Usart_RxBuff.BuffRptr - 1))
    {
        Dat->Usart_RxBuff.BuffRptr++;  //数据超前,覆盖旧的数据
        Dat->Usart_RxBuff.BuffRptr %= Dat->Usart_RxBuff.Rx_BuffSize;
        printf("Cnt = %d \r\n",Cnt);
    }
    Dat->Usart_RxBuff.Rx_Buff[Dat->Usart_RxBuff.BuffWptr ++] = Data;
    Dat->Usart_RxBuff.BuffWptr %= Dat->Usart_RxBuff.Rx_BuffSize;	//写地址环形变换
}
/*环形数据提取*/
uint8_t UsartDatRead(pUSARTDEALTYPE Soure, uint8_t *ReaDat)
{
    if(Soure->Usart_RxBuff.BuffWptr == (Soure->Usart_RxBuff.BuffRptr))
    {
        return 0;
    }
    ReaDat[0] = Soure->Usart_RxBuff.Rx_Buff[Soure->Usart_RxBuff.BuffRptr++];
    Soure->Usart_RxBuff.BuffRptr %= Soure->Usart_RxBuff.Rx_BuffSize; //读地址环形变化
    return 1;
}


/*命令提取*/
void UsartDataParse(pUSARTDEALTYPE Soure)
{
    static uint8_t Part = 0;      //提取命令解析的步骤记录
    static uint8_t WillCount = 0; //保存将提取的次数
    uint16_t clcye = 100;         //一个循环提取的次数


    if(Soure == NULL)
    {
        return;
    }
    if(Soure->Usart_RxBuff.BuffWptr == (Soure->Usart_RxBuff.BuffRptr))
    {
        //无数据提取
        return;
    }
    if(Soure->Usart_Flag.PackOKFlag == 1)
    {
        //有命令未处理
        return;
    }
    if(Soure->Usart_Flag.Penetrate == 1)   ///透传模式
    {
        //初始提取长度
        USARTDEALCmdLen(Soure) = 0;
        //读取数据
        while(UsartDatRead(Soure, (uint8_t *)&USARTDEALCmdBuff(Soure)[USARTDEALCmdLen(Soure)] ))
        {
            USARTDEALCmdLen(Soure)++; //长度地址自增
            //长度地址越界退出
            if(USARTDEALCmdLen(Soure) >= Soure->Usart_CmdBuff.Cmd_BuffSize)
            {
                break;
            }
        }
        if(USARTDEALCmdLen(Soure))
        {
            Soure->Usart_Flag.PackOKFlag = 1; //标志置位
        }
    }
    else
    {
        while(clcye --)
        {
            if(USARTDEALTimeOut(Soure)  == 0)
            {
                Part = 0;
                USARTDEALCmdLen(Soure) = 0; //初始提取长度
            }

            if(UsartDatRead(Soure, (uint8_t *)&USARTDEALCmdBuff(Soure)[USARTDEALCmdLen(Soure)] ))
            {
                //提取数据成功
                switch(Part)
                {
                    case 0:   //寻找包头收字母
                    {
                        if(USARTDEALCmdBuff(Soure) [0] == USARTDEALFormHead(Soure)[0] )
                        {
                            USARTDEALTimeOut(Soure)  = 10; //设置命令查找倒计时
                            USARTDEALCmdLen(Soure)++;
                            Part++;
                            if(Soure->Usart_Form.headByteSize == 1)
                            {
                                Part = 2;
                            }
                        }
                        break;
                    }
                    case 1:   //多字节包头数据比较
                    {
                        USARTDEALCmdLen(Soure)++;
                        if(USARTDEALCmdLen(Soure) == Soure->Usart_Form.headByteSize)
                        {
                            if(strncmp((char *)USARTDEALCmdBuff(Soure), (char *)USARTDEALFormHead(Soure), Soure->Usart_Form.headByteSize) == 0)
                            {
                                Part++;
                            }
                            else     //对比失败
                            {
                                Part = 0;
                                USARTDEALCmdLen(Soure) = 0; //初始提取长度
                            }
                        }
                        break;
                    }
                    case 2:   //数据长度位置
                    {
                        if(Soure->Usart_Form.DLenAddr == USARTDEALCmdLen(Soure))
                        {
                            WillCount = USARTDEALCmdBuff(Soure) [USARTDEALCmdLen(Soure)] + \
                                        Soure->Usart_Form.OtherLen;
                            Part++;
                        }
                        USARTDEALCmdLen(Soure)++;
                        break;
                    }
                    case 3:   //接收完数据包
                    {
                        if(USARTDEALCmdLen(Soure) == WillCount - 1)   //
                        {
                            if(strncmp((char *)&USARTDEALCmdBuff(Soure)                                                         [USARTDEALCmdLen(Soure) - Soure->Usart_Form.EndByteSize+1], \
                                       (char *)USARTDEALFormEnd(Soure), Soure->Usart_Form.EndByteSize) == 0)
                            {
                                Part = 0;
                                USARTDEALTimeOut(Soure)  = 0; //倒计时清零
                                USARTDEALCmdLen(Soure)++;
                                Soure->Usart_Flag.PackOKFlag = 1;
                                return ;
                            }
                            else      //检测包尾失败
                            {
                                USARTDEALTimeOut(Soure)  = 0; //倒计时清零
                                break;
                            }
                        }
                        USARTDEALCmdLen(Soure)++;
                        break;
                    }
                    default:
                    {
                        USARTDEALTimeOut(Soure)  = 0; //倒计时清零
                    }
                }
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值