stm32_ota/SYSTEM/SYSLIB/syslib.c

397 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "syslib.h"
#include <string.h>
#include "usart.h"
#include "sysport.h"
/********************************************************************************
* @file syslib.c
* @author 晏诚科技 Mr.Wang
* @version V1.0.0
* @date 11-Dec-2018
* @brief 提供数据处理相关的函数、提供帧环形缓冲区
******************************************************************************
*******************************************************************************/
/**************************************************************************************************
* 名 称void InitQueueMem(FrameQueue_s* sFrame)
* 功能说明:帧环形缓冲区初始化
* 入口参数:
* @param1 *sFrame FrameQueue_s结构体类型指针
* 调用方法:外部调用
*************************************************************************************************/
void InitQueueMem(FrameQueue_s* sFrame)
{
sFrame->getIndex = 0;
sFrame->insertIndex = 0;
sFrame->hasDataLen = 0;
memset(sFrame->dataBuf, 0 , MAX_QUEUE_LEN) ;
}
/**************************************************************************************************
* 名 称uint8_t InsertQueueMemData(FrameQueue_s *sFrame, char *data, uint16_t len)
* 功能说明将数据插入帧环形缓冲区中并以HEAD1、HEAD2为帧头以TAIL1、TAIL2为帧尾
* 入口参数:
* @param1 *sFrame FrameQueue_s结构体类型指针
* @param2 *data 需要插入帧缓冲区的数据指针
* @param3 len 需要插入帧缓冲区的数据长度
* 出口参数FULL_ERROR/RW_OK
* 调用方法:外部调用
*************************************************************************************************/
uint8_t InsertQueueMemData(FrameQueue_s *sFrame, char *data, uint16_t len) //插入一帧数据函数内部会自动添加0x1234,0x5678 4个字节分别作为帧头和帧尾 写入缓冲区
{
if((sFrame->hasDataLen+len+4) >= MAX_QUEUE_LEN ) /*缓冲区剩余空间不够插入 新的数据帧和4字节帧头帧尾*/
{
return FULL_ERROR;
}
else /*缓冲区剩余空间够插入新的数据帧*/
{
sFrame->dataBuf[sFrame->insertIndex] = HEAD1 ; //插入帧头第一个字节HEAD1
sFrame->insertIndex = (sFrame->insertIndex+1) % MAX_QUEUE_LEN; //核心语句实现数据环形写入一旦指针到MAX_QUEUE_LEN位置则又从0开始写入缓冲区
sFrame->dataBuf[sFrame->insertIndex] = HEAD2 ; //插入帧头第二个字节HEAD2
sFrame->insertIndex = (sFrame->insertIndex+1) % MAX_QUEUE_LEN; //核心语句实现数据环形写入一旦指针到MAX_QUEUE_LEN位置则又从0开始写入缓冲区
for(int n=0; n<len; n++ ) //循环插入数据
{
sFrame->dataBuf[sFrame->insertIndex] = *(data++) ;
sFrame->insertIndex = (sFrame->insertIndex+1) % MAX_QUEUE_LEN; //核心语句实现数据环形写入一旦指针到MAX_QUEUE_LEN位置则又从0开始写入缓冲区
}
sFrame->dataBuf[sFrame->insertIndex] = TAIL1 ; //插入帧尾TAIL1
sFrame->insertIndex = (sFrame->insertIndex+1) % MAX_QUEUE_LEN; //核心语句实现数据环形写入一旦指针到MAX_QUEUE_LEN位置则又从0开始写入缓冲区
sFrame->dataBuf[sFrame->insertIndex] = TAIL2 ; //插入帧尾TAIL2
sFrame->insertIndex = (sFrame->insertIndex+1) % MAX_QUEUE_LEN; //核心语句实现数据环形写入一旦指针到MAX_QUEUE_LEN位置则又从0开始写入缓冲区
sFrame->hasDataLen+= (len+4) ; //更新sFrame->hasDataLen 已经存储数据长度
if( sFrame->hasDataLen >= MAX_QUEUE_LEN) //未知异常
{
InitQueueMem(sFrame) ;
SysErr("") ;
}
return RW_OK;
}
}
/**************************************************************************************************
* 名 称uint8_t GetQueueMemData(FrameQueue_s* sFrame, char* data, uint16_t* pLen)
* 功能说明:从帧缓冲区中取出一帧数据
* 入口参数:
* @param1 *sFrame FrameQueue_s结构体类型指针
* @param2 *data 取出的帧数据存放的内存地址
* @param3 len 去除的帧数据长度
* 出口参数EMPTY_ERROR/RW_OK
* 调用方法:外部调用
*************************************************************************************************/
uint8_t GetQueueMemData(FrameQueue_s* sFrame, char* data, uint16_t* pLen)
{
if(0 == sFrame->hasDataLen) /*帧缓冲区数据为空,即没有数据*/
{
return EMPTY_ERROR;
}
else /*帧缓冲区数据不为空,即存在帧数据*/
{
sFrame->getIndex = (sFrame->getIndex + 2) % MAX_QUEUE_LEN; //跳过帧头HEAD1、HEAD2 2个字节
*pLen = 0 ; //pLen置0
while( (TAIL1 != sFrame->dataBuf[sFrame->getIndex])
||((TAIL2 != sFrame->dataBuf[(sFrame->getIndex + 1) % MAX_QUEUE_LEN])) ) /*查找帧尾*/
{
(*pLen)++ ; //pLen计数器累加
*(data++) = sFrame->dataBuf[sFrame->getIndex] ; //先将sFrame->dataBuf[sFrame->getIndex]赋值给 *(data++)在将data指针指向下一个字节
sFrame->getIndex = (sFrame->getIndex + 1) % MAX_QUEUE_LEN;
if( (*pLen >= sFrame->hasDataLen) || (sFrame->getIndex >= MAX_QUEUE_LEN))//异常处理
{
InitQueueMem(sFrame) ;
SysErr("") ;
return EMPTY_ERROR;
}
}
sFrame->getIndex = (sFrame->getIndex + 2) % MAX_QUEUE_LEN; //跳过帧尾TAIL1、TAIL2 2个字节
sFrame->hasDataLen -= (*pLen+4) ; //计算正确的帧数据长度
return RW_OK;
}
}
/**************************************************************************************************
* 名 称: void SysStrcat(char *dest, uint16_t destSize, char *src)
* 说 明: 将str字符串拼接到dest字符串结尾处
* 入口参数:
* @param1 *dest: 目的地址
* @param2 destSize: 目的空间的最大size
* @param3 *src: 源地址
****************************************************************************************************/
void SysStrcat(char *dest, uint16_t destSize, char *src)
{
int dLen = strlen(dest) ;
int sLen = strlen(src) ;
if( (dLen+sLen) >= destSize) //字符串拼接后将发生溢出
{
*(dest+destSize-sLen-1) = 0x00 ; //将目的字符串的最后添加字符串结尾
}
strcat(dest, src) ; //此时可以安全拼接字符串了
}
/**************************************************************************************************
* 名 称: uint16_t CopyValues(uint8_t *dest, const uint8_t *src, uint8_t lot, uint8_t maxLen)
* 说 明: 从源地址scr向目的地址dst拷贝字符遇到lot字符即结束拷贝,最多查询src后面maxLen长度的数据
* 入口参数:
* @param1 *dest: 目的地址
* @param2 *src: 源地址
* @param3 lot: 拷贝停止标志字符
* @param4 maxLen: 拷贝数据的最大长度
* 出口参数:
* @param1 uint16_t: 返回lot在源数组中的偏移量
************************************************************************************************************/
uint16_t CopyValues(uint8_t *dest, uint8_t *src, uint8_t lot, uint16_t maxLen)
{
uint16_t i = 0;
for(i = 0; *(src+i)!=lot; i++)
{
*(dest+i) = *(src+i);
if(i >= (maxLen-1))
break; //防止过多拷贝,造成死循环
}
return i ;
//*(dest+i) = 0 ; //添加字符串结尾
}
/**************************************************************************************************
* 名 称: void CopyStr(char *dest, char *src, char startLot, char endLot, uint16_t maxLen)
* 说 明: 从源地址scr向目的地址dst拷贝字符从字符startLot(不包含startLot)开始遇到endLot前一个字符即结束拷贝,最多查询src后面maxLen长度的数据
* 入口参数:
* @param1 *dest: 目的地址
* @param2 *src: 源地址
* @param3 startLot: 拷贝开始标志字符
* @param4 endLot: 拷贝停止标志字符
* @param5 maxLen: 拷贝数据的最大长度
************************************************************************************************************/
void CopyStr(char *dest, char *src, char startLot, char endLot, uint16_t maxLen)
{
uint16_t j = 0;
char *startAddr ;
startAddr = strchr((const char *)src, startLot);
for(j = 1; *(startAddr+j)!=endLot; j++)
{
*(dest+j-1) = *(startAddr+j);
if(j > maxLen)
break;//防止过多拷贝,在成死循环
}
// *(dest+j) = *(startAddr+j);
}
/**************************************************************************************************
* 名 称: void HexConvertToString(uint8_t * dest, uint8_t * src, uint16_t length)
* 功能说明: 将16进制数据转化为字符串数据
* 入口参数:
* @param1 *dest: 目的地址
* @param2 *src: 源地址
* @param3 length: 源地址数据长度
* 说 明: 例如将例如源数组{0x33,0x31}调用函数后得到目的字符串为“31”
*************************************************************************************************/
void HexConvertToString(uint8_t * dest, uint8_t *src, uint16_t length)
{
uint8_t *xad;
uint16_t i = 0;
uint8_t ch;
xad = src + length - 1;
for(i = 0; i < length; i++,xad--)
{
ch = (*xad>>4)&0x0F;
dest[i<<1] = ch+((ch<10)?'0':'7');
ch = *xad & 0x0F;
dest[(i<<1)+1] = ch + ((ch<10)?'0':'7');
}
}
/**************************************************************************************************
* 名 称: void ByteToHexStr( uint8_t* dest, const uint8_t* src, uint16_t sourceLen)
* 功能说明: 将16进制数据转化为16进制字符串数据
* 入口参数:
* @param1 *dest: 目的地址
* @param2 *src: 源地址
* @param3 sourceLen: 源地址数据长度
* 出口参数: 无
* 说 明: 例如源数组{0x43,0x21}调用函数后得到目的数组为{0x34,0x33,0x32,0x31}
* 调用实例: ByteToHexStr(macAddressBytes.bytes, macAddressNBytes, 12) ;
*************************************************************************************************/
void ByteToHexStr( uint8_t* dest, const uint8_t* src, uint16_t sourceLen)
{
uint16_t i;
uint8_t highByte, lowByte;
for (i = 0; i < sourceLen; i++)
{
highByte = src[i] >> 4;
lowByte = src[i] & 0x0f;
highByte += 0x30;
if (highByte > 0x39)
dest[i * 2] = highByte + 0x07;
else
dest[i * 2] = highByte;
lowByte += 0x30;
if (lowByte > 0x39)
dest[i * 2 + 1] = lowByte + 0x07;
else
dest[i * 2 + 1] = lowByte;
}
}
/**************************************************************************************************
* 名 称: char *itoa(int value, char *string, int radix)
* 功能说明: 整形数据转字符串
* 入口参数: int value, char *string, int radix
* 出口参数: char *:返回的字符串指针
* 说 明:
* radix=10 标示是10进制 非十进制转换结果为0 ;
* 例d=-379 ;执行 itoa(d, buf, 10) ; 后buf="-379"
*************************************************************************************************/
char *itoa(int value, char *string, int radix)
{
int i, d ;
int flag = 0 ;
char *ptr = string ;
/* This implementation only works for decimal numbers. */
if (radix != 10)
{
*ptr = 0 ;
return string ;
}
if (!value)
{
*ptr++ = 0x30 ;
*ptr = 0 ;
return string ;
}
/* if this is a negative value insert the minus sign. */
if (value < 0)
{
*ptr++ = '-' ;
/* Make the value positive. */
value *= -1 ;
}
for (i = 10000; i > 0; i /= 10)
{
d = value / i ;
if (d || flag)
{
*ptr++ = (char)(d + 0x30) ;
value -= (d * i) ;
flag = 1 ;
}
}
/* Null terminate the string. */
*ptr = 0 ;
return string ;
} /* NCL_Itoa */
/**************************************************************************************************
* 名 称: char * uitoa(unsigned int num, char *str)
* 功能说明: 无符号整形数据转10进制字符串
* 入口参数: int value, char *string
* 出口参数: char *:返回的字符串指针
*************************************************************************************************/
char *uitoa(unsigned int value, char *string)
{
unsigned char i = 0, index = 0 ;
unsigned char temp = 0 ;
unsigned int bottom = 10000 ;
for(i = 0; i < 5; i++)
{
temp = value/bottom ;
if(temp>0 || index>0) string[index++]=0x30+temp ;
value %= bottom ;
bottom /= 10 ;
}
if(index==0) string[index++]=0x30;
//string[index]='\0';
return string;
}
/**************************************************************************************************
* 名 称: int kmp(const char* _str, const char* _ptn)
* 功能说明: 从源地址—str中寻找字符串—ptn, 并返回偏移量
* 入口参数:
* @param1 *src: 源地址
* @param2 *_ptn: 指向子串的指针
* 出口参数:
* @param1 int:
* @arg -1源地址找不到子串
* @arg 非-1子串相对源地址的偏移量
*************************************************************************************************/
int kmp(const char *_str, const char *_ptn)
{
uint16_t m = strlen((const char *)_str) ;
uint16_t n = strlen((const char *)_ptn) ;
uint16_t i = 0, j = 0 ;
uint16_t loop = 0 ;
char* next = (char*)portMalloc((size_t)(n*sizeof(char))) ;
kmp_next2(_ptn, next) ;
i = 0 ; j = 0 ;
while(i < m && j < n)
{
loop++ ;
if(_str[i] == _ptn[j])
{
++i ;
++j ;
}
else if(0 == j)
++i ;
else
j = next[j] ;
}
portFree(next) ; //next = NULL;
if(j >= n)
return i-n ;
else
return -1 ;
}
void kmp_next2(const char* _ptn, char* _next)
{
uint16_t n = strlen((const char *)_ptn) ;
uint16_t i, j ;
if(n >= 1)
_next[0] = 0 ;
i = 1 ;
j = 0 ;
while(i < n)
{
if(_ptn[i] == _ptn[j])
{
++i ;
++j ;
if(_ptn[i] != _ptn[j])
_next[i] = j ;
else
_next[i] = _next[j] ;
}
else if(0 == j)
_next[++i] = j ;
else
j = _next[j] ;
}
}