110VCGQ/project/power/Core/Src/user_lib.c
2023-04-21 17:47:03 +08:00

510 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* user_lib.c
*
* Created on: 2023年1月30日
* Author: wyf
*/
#include "user_lib.h"
// CRC 高位字节值表
static const uint8_t s_CRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
// CRC 低位字节值表
const uint8_t s_CRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
/*
*********************************************************************************************************
* 函 数 名: str_len
* 功能说明: 计算字符串长度.0是结束符
* 形 参: _str : 缓冲区
* 返 回 值: 无
*********************************************************************************************************
*/
int str_len(char *_str)
{
int len = 0;
while (*_str++) len++;
return len;
}
/*
*********************************************************************************************************
* 函 数 名: str_cpy
* 功能说明: 复制字符串
* 形 参: tar : 目标缓冲区
* src : 源缓冲区
* 返 回 值: 无
*********************************************************************************************************
*/
void str_cpy(char *_tar, char *_src)
{
do
{
*_tar++ = *_src;
}
while (*_src++);
}
/*
*********************************************************************************************************
* 函 数 名: str_cmp
* 功能说明: 字符串比较
* 形 参: s1 : 字符串1
* s2 : 字符串2
* 返 回 值: 0 表示相等 非0表示不等
*********************************************************************************************************
*/
int str_cmp(char * s1, char * s2)
{
while ((*s1!=0) && (*s2!=0) && (*s1==*s2))
{
s1++;
s2++;
}
return *s1 - *s2;
}
/*
*********************************************************************************************************
* 函 数 名: str_copy
* 功能说明: 复制字符串
* 形 参: tar : 目标缓冲区
* src : 源缓冲区
* 返 回 值: 无
*********************************************************************************************************
*/
void mem_set(char *_tar, char _data, int _len)
{
while (_len--)
{
*_tar++ = _data;
}
}
/*
*********************************************************************************************************
* 函 数 名: int_to_ascii
* 功能说明: 将整数转换为ASCII数组。支持负数。
* 形 参: _Number : 整数
* _pBuf : 目标缓冲区, 存放转换后的结果。以0结束的字符串。
* _len : ASCII字符个数, 字符串长度
* 返 回 值: 无
*********************************************************************************************************
*/
void int_to_str(int _iNumber, char *_pBuf, unsigned char _len)
{
unsigned char i;
int iTemp;
if (_iNumber < 0) /* 负数 */
{
iTemp = -_iNumber; /* 转为正数 */
}
else
{
iTemp = _iNumber;
}
mem_set(_pBuf, ' ',_len);
/* 将整数转换为ASCII字符串 */
for (i = 0; i < _len; i++)
{
_pBuf[_len - 1 - i] = (iTemp % 10) + '0';
iTemp = iTemp / 10;
if (iTemp == 0)
{
break;
}
}
_pBuf[_len] = 0;
if (_iNumber < 0) /* 负数 */
{
for (i = 0; i < _len; i++)
{
if ((_pBuf[i] == ' ') && (_pBuf[i + 1] != ' '))
{
_pBuf[i] = '-';
break;
}
}
}
}
/*
*********************************************************************************************************
* 函 数 名: str_to_int
* 功能说明: 将ASCII码字符串转换成整数。 遇到小数点自动越过。
* 形 参: _pStr :待转换的ASCII码串. 可以以逗号,#或0结束。 2014-06-20 修改为非0-9的字符。
* 返 回 值: 二进制整数值
*********************************************************************************************************
*/
int str_to_int(char *_pStr)
{
unsigned char flag;
char *p;
int ulInt;
unsigned char i;
unsigned char ucTemp;
p = _pStr;
if (*p == '-')
{
flag = 1; /* 负数 */
p++;
}
else
{
flag = 0;
}
ulInt = 0;
for (i = 0; i < 15; i++)
{
ucTemp = *p;
if (ucTemp == '.') /* 遇到小数点自动跳过1个字节 */
{
p++;
ucTemp = *p;
}
if ((ucTemp >= '0') && (ucTemp <= '9'))
{
ulInt = ulInt * 10 + (ucTemp - '0');
p++;
}
else
{
break;
}
}
if (flag == 1)
{
return -ulInt;
}
return ulInt;
}
/*
*********************************************************************************************************
* 函 数 名: BEBufToUint16
* 功能说明: 将2字节数组(大端Big Endian次序高字节在前)转换为16位整数
* 形 参: _pBuf : 数组
* 返 回 值: 16位整数值
*
* 大端(Big Endian)与小端(Little Endian)
*********************************************************************************************************
*/
uint16_t BEBufToUint16(uint8_t *_pBuf)
{
return (((uint16_t)_pBuf[0] << 8) | _pBuf[1]);
}
/*
*********************************************************************************************************
* 函 数 名: LEBufToUint16
* 功能说明: 将2字节数组(小端Little Endian低字节在前)转换为16位整数
* 形 参: _pBuf : 数组
* 返 回 值: 16位整数值
*********************************************************************************************************
*/
uint16_t LEBufToUint16(uint8_t *_pBuf)
{
return (((uint16_t)_pBuf[1] << 8) | _pBuf[0]);
}
/*
*********************************************************************************************************
* 函 数 名: BEBufToUint32
* 功能说明: 将4字节数组(大端Big Endian次序高字节在前)转换为16位整数
* 形 参: _pBuf : 数组
* 返 回 值: 16位整数值
*
* 大端(Big Endian)与小端(Little Endian)
*********************************************************************************************************
*/
uint32_t BEBufToUint32(uint8_t *_pBuf)
{
return (((uint32_t)_pBuf[0] << 24) | ((uint32_t)_pBuf[1] << 16) | ((uint32_t)_pBuf[2] << 8) | _pBuf[3]);
}
/*
*********************************************************************************************************
* 函 数 名: LEBufToUint32
* 功能说明: 将4字节数组(小端Little Endian低字节在前)转换为16位整数
* 形 参: _pBuf : 数组
* 返 回 值: 16位整数值
*********************************************************************************************************
*/
uint32_t LEBufToUint32(uint8_t *_pBuf)
{
return (((uint32_t)_pBuf[3] << 24) | ((uint32_t)_pBuf[2] << 16) | ((uint32_t)_pBuf[1] << 8) | _pBuf[0]);
}
/*
*********************************************************************************************************
* 函 数 名: CRC16_Modbus
* 功能说明: 计算CRC。 用于Modbus协议。
* 形 参: _pBuf : 参与校验的数据
* _usLen : 数据长度
* 返 回 值: 16位整数值。 对于Modbus ,此结果高字节先传送,低字节后传送。
*
* 所有可能的CRC值都被预装在两个数组当中当计算报文内容时可以简单的索引即可
* 一个数组包含有16位CRC域的所有256个可能的高位字节另一个数组含有低位字节的值
* 这种索引访问CRC的方式提供了比对报文缓冲区的每一个新字符都计算新的CRC更快的方法
*
* 注意:此程序内部执行高/低CRC字节的交换。此函数返回的是已经经过交换的CRC值也就是说该函数的返回值可以直接放置
* 于报文用于发送;
*********************************************************************************************************
*/
uint16_t CRC16_Modbus(uint8_t *_pBuf, uint16_t _usLen)
{
uint8_t ucCRCHi = 0xFF; /* 高CRC字节初始化 */
uint8_t ucCRCLo = 0xFF; /* 低CRC 字节初始化 */
uint16_t usIndex; /* CRC循环中的索引 */
while (_usLen--)
{
usIndex = ucCRCHi ^ *_pBuf++; /* 计算CRC */
ucCRCHi = ucCRCLo ^ s_CRCHi[usIndex];
ucCRCLo = s_CRCLo[usIndex];
}
return ((uint16_t)ucCRCHi << 8 | ucCRCLo);
}
/*
*********************************************************************************************************
* 函 数 名: CaculTwoPoint
* 功能说明: 根据2点直线方程计算Y值
* 形 参: 2个点的坐标和x输入量
* 返 回 值: x对应的y值
*********************************************************************************************************
*/
int32_t CaculTwoPoint(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x)
{
return y1 + ((int64_t)(y2 - y1) * (x - x1)) / (x2 - x1);
}
/*
*********************************************************************************************************
* 函 数 名: BcdToChar
* 功能说明: 将BCD码转为ASCII字符。 比如 0x0A ==> 'A'
* 形 参: _bcd 输入的二进制数。必须小于16
* 返 回 值: 转换结果
*********************************************************************************************************
*/
char BcdToChar(uint8_t _bcd)
{
if (_bcd < 10)
{
return _bcd + '0';
}
else if (_bcd < 16)
{
return _bcd + 'A';
}
else
{
return 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: HexToAscll
* 功能说明: 将二进制数组转换为16进制格式的ASCII字符串。每个2个ASCII字符后保留1个空格。
* 0x12 0x34 转化为 0x31 0x32 0x20 0x33 0x34 0x00 即 "1234"
* 形 参: _pHex :输入的数据,二进制数组
* _pAscii :存放转换结果, ASCII字符串0结束。1个二进制对应2个ASCII字符.
* 返 回 值: 转换得到的整数
*********************************************************************************************************
*/
void HexToAscll(uint8_t * _pHex, char *_pAscii, uint16_t _BinBytes)
{
uint16_t i;
if (_BinBytes == 0)
{
_pAscii[0] = 0;
}
else
{
for (i = 0; i < _BinBytes; i++)
{
_pAscii[3 * i] = BcdToChar(_pHex[i] >> 4);
_pAscii[3 * i + 1] = BcdToChar(_pHex[i] & 0x0F);
_pAscii[3 * i + 2] = ' ';
}
_pAscii[3 * (i - 1) + 2] = 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: AsciiToUint32
* 功能说明: 变长的 ASCII 字符转换为32位整数 ASCII 字符以空格或者0结束 。 支持16进制和10进制输入
* 形 参: *pAscii 要转换的ASCII码
* 返 回 值: 转换得到的整数
*********************************************************************************************************
*/
uint32_t AsciiToUint32(char *pAscii)
{
uint8_t i;
char bTemp;
char bIsHex;
char bLen;
char bZeroLen;
uint32_t lResult;
uint32_t lBitValue;
/* 判断是否是16进制数 */
bIsHex = 0;
if ((pAscii[0] == '0') && ((pAscii[1] == 'x') || (pAscii[1] == 'X')))
{
bIsHex=1;
}
lResult=0;
// 最大数值为 4294967295, 10位+2字符"0x" //
if (bIsHex == 0)
{ // 十进制 //
// 求长度 //
lBitValue=1;
/* 前导去0 */
for (i = 0; i < 8; i++)
{
bTemp = pAscii[i];
if (bTemp != '0')
break;
}
bZeroLen = i;
for (i = 0; i < 10; i++)
{
if ((pAscii[i] < '0') || (pAscii[i] > '9'))
break;
lBitValue = lBitValue * 10;
}
bLen = i;
lBitValue = lBitValue / 10;
if (lBitValue == 0)
lBitValue=1;
for (i = bZeroLen; i < bLen; i++)
{
lResult += (pAscii[i] - '0') * lBitValue;
lBitValue /= 10;
}
}
else
{ /* 16进制 */
/* 求长度 */
lBitValue=1;
/* 前导去0 */
for (i = 0; i < 8; i++)
{
bTemp = pAscii[i + 2];
if(bTemp!='0')
break;
}
bZeroLen = i;
for (; i < 8; i++)
{
bTemp=pAscii[i+2];
if (((bTemp >= 'A') && (bTemp <= 'F')) ||
((bTemp>='a')&&(bTemp<='f')) ||
((bTemp>='0')&&(bTemp<='9')) )
{
lBitValue=lBitValue * 16;
}
else
{
break;
}
}
lBitValue = lBitValue / 16;
if (lBitValue == 0)
lBitValue = 1;
bLen = i;
for (i = bZeroLen; i < bLen; i++)
{
bTemp = pAscii[i + 2];
if ((bTemp >= 'A') && (bTemp <= 'F'))
{
bTemp -= 0x37;
}
else if ((bTemp >= 'a') && (bTemp <= 'f'))
{
bTemp -= 0x57;
}
else if ((bTemp >= '0') && (bTemp <= '9'))
{
bTemp -= '0';
}
lResult += bTemp*lBitValue;
lBitValue /= 16;
}
}
return lResult;
}