#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; //倒计时清零
}
}
}
}
}
}