// 十进制转BCD
// 传入25,返回0x25
static inline uint8_t decimal_bcd_code(uint8_t decimal){
return 0xf0&((decimal/10)<<4) | (decimal%10);
}
// 将"hhmmss"转换成以秒为单位的时间戳
int32_t strtime_to_inttime(uint8_t* str){
uint8_t hour = (str[0]-'0')*10+(str[1]-'0');
uint8_t min = (str[2]-'0')*10+(str[3]-'0');
uint8_t sec = (str[4]-'0')*10+(str[5]-'0');
return (hour*60+min)*60+sec;
}
// 将 int32_t 类型的时间戳 转化成类似"232322"字符串,代表23:23:22
void inttime_to_strtime(int32_t time,uint8_t*strtime){
uint8_t hour = (uint8_t)(time/3600);
uint8_t min = (uint8_t)(((int32_t)(time - hour*3600))/60);
uint8_t sec = time % 60;
sprintf(strtime,"%02d%02d%02d",hour,min,sec);
}
// 将时间字符串转成16进制数组
// "20160801085857"->{0x20,0x16,0x08,0x01,0x08,0x58,0x57}
#define STR_TO_BCD(str,array) do{\
uint8_t i = 0;\
for(i = 0;i < 7;i ++){\
(uint8_t)(((uint8_t*)(array))[i]) = ((uint8_t)( ((uint8_t*)(str))[i*2]-'0')<<4)+(((uint8_t*)(str))[i*2+1]-'0');\
}\
}while(0);
// 将一字节的bcd码转成实际数(16进制和10进制表示一样的数)
static uint8_t PI_bcd_to_hex(uint8_t data){
uint8_t temp;
temp = ((data>>4)*10 + (data&0x0f));
return temp;
}
1:字符串格式化
sprintf(data_temp,"%12.6f,",i);代表一共12个字符(包括'.')
2:字符串提取方法
/**
* @brief 根据开头 结尾 截取字符串
* @note
* @param *dest: 存储截取的的字符串
* @param d_max_len: 最大截取字符串长度
* @param *src: 源字符串地址
* @param *start_str: 开始字符串地址
* @param *end_str: 结束字符串地址
* @retval -1:找不到数据,>= 0找到之后返回的字符数量
*/
static inline int32_t SubStr(uint8_t *dest, uint8_t d_max_len, const uint8_t *src, const uint8_t *start_str, const uint8_t *end_str){
uintptr_t start_p = 0;
uintptr_t end_p = 0;
uintptr_t len = 0;
int32_t ret = 0;
start_p = (uintptr_t)strstr(src, start_str) + (len = strlen(start_str));
if(len == start_p)
return 0;
end_p = (uintptr_t)strstr((char *)start_p, end_str);
if(0 == end_p)
return 0;
if((end_p - start_p) < d_max_len) //内存访问边界保护
{
memcpy(dest, (char *)start_p, (end_p - start_p));
return end_p - start_p;
}
return -1;
}
// 返回匹配到的字符串个数,字符串放在dest数组中,若字符串长度超过了d_max_len截断
// 这是为了HJ212str协议设计,只要传入源字符串,标记开始的解析字符,
// 而标记结束的解析字符,函数内部有";",",","&"
// 能得到中间字符串
// 如
// &&PolId=w21003,InfoId=i13001,InfoId=i13002,InfoId=i13003,InfoId=i13004,
// InfoId=i13005,InfoId=i13006,InfoId=i13007,InfoId=i130
// 08,InfoId=i13009,InfoId=i13010,InfoId=i13011,InfoId=i1
// 3012,InfoId=i13013&&
// 标记开始的解析字符 "InfoId=i"
// 由此得到各InfoId的数据,以字符串给出
static inline int32_t SubStrSuper(uint8_t *dest,
uint8_t d_max_len,//表示dest[0]的长度
uint8_t d_max_num,//表示dest的数组元素个数
const uint8_t *src,//源数据指针
uint16_t src_len,//源数据长度
const uint8_t *start_str
){
uintptr_t start_p = (uintptr_t)src;
uintptr_t temp_p = 0;
uint8_t start_str_len = strlen(start_str);
uint8_t i = 0;
uint8_t dest_index = 0;
do{
temp_p = (uintptr_t)strstr((uint8_t*)start_p, start_str);
if(temp_p == 0){break;}
temp_p = temp_p - start_p;//得到偏移量
start_p = start_p + temp_p + start_str_len;
if(((uintptr_t)src+src_len) < start_p){break;}
if(((temp_p = (uintptr_t)strstr((uint8_t*)start_p,",")) != 0)
|| ((temp_p = (uintptr_t)strstr((uint8_t*)start_p,";")) != 0)
|| ((temp_p = (uintptr_t)strstr((uint8_t*)start_p,"&")) != 0) ){
memcpy(&dest[i],(uint8_t*)start_p,((temp_p - start_p) > d_max_len)?d_max_len:(temp_p - start_p));
start_p = temp_p;
i += d_max_len;
dest_index ++;
}else{
break;
}
if(dest_index >= d_max_num){break;}
}while(((uintptr_t)src+src_len) >= start_p);
return dest_index;
}
4:各类常用宏和头文件
#define MIN(a,b) ((a)>(b)?b:a)
#define MAX(a,b) ((a)>(b)?a:b)
#define LEN_(X) (sizeof(X)/sizeof(X[0]))
// 字符串是否相等
#define STR_EQUAL(a,b) (strcmp((a),(b)) == 0)
#define ASCII_TIME_SIZE (sizeof("102030")-1)
将0x12 0x23 0x34 0x45 变成 0x45342312 应该叫做小端
#define __Getu32(buf) ((uint32_t)((buf)[3])<<24 | (uint32_t)((buf)[2])<<16 | (uint32_t)((buf)[1])<<8 | (uint32_t)((buf)[0]))
// 串口发来的0x12,0x34,0x56,0x78 变成0x12345678
#define __Getu32(buf) ((uint32_t)((buf)[0])<<24 | (uint32_t)((buf)[1])<<16 | (uint32_t)((buf)[2])<<8 | (uint32_t)((buf)[3]))
#define __Getu16_little(src) ((uint16_t)(src)[0] + ((uint16_t)(src)[1] << 8))
#define __Getu16_big(src) ((uint16_t)(src)[1] + ((uint16_t)(src)[0] << 8))
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
5字符串转换头文件
#include <stdlib.h>
6 常用结构体
typedef struct SERIAL_DATA_CONTROL_STRU{
uint8_t RxBuffer[200];
bool RxBufferRecFlag;
uint16_t RxBufferIndex;
}SERIAL_DATA_CONTROL;
// 增加一个字节的数据时候用
#define SERIAL_DATA_ADD_BYTE(STRU_PTR,BYTE) \
do{\
if(((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBufferIndex < (sizeof(((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBuffer)/sizeof(((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBuffer[0]))){\
((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBuffer[((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBufferIndex] = (uint8_t)BYTE;\
((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBufferIndex++;\
} \
((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBufferRecFlag = false;\
}while(false);
// 空闲中断发生时候用
#define SERIAL_DATA_RECOVER_BYTE(STRU_PTR) ((SERIAL_DATA_CONTROL*)STRU_PTR)->RxBufferRecFlag = true;
uint16_t SerialDataRec(SERIAL_DATA_CONTROL* ptr, uint8_t* tarbuf, uint16_t tarbufmaxlen);
uint16_t SerialDataRec(SERIAL_DATA_CONTROL* ptr, uint8_t* tarbuf, uint16_t tarbufmaxlen) {
if(ptr->RxBufferRecFlag == true) {
uint16_t rec_len = ptr->RxBufferIndex;
uint16_t min = (tarbufmaxlen > rec_len) ? rec_len : tarbufmaxlen;
memcpy(tarbuf, ptr->RxBuffer, min);
ptr->RxBufferRecFlag = false;
ptr->RxBufferIndex = 0;
return min;
}
return 0;
}
用于模拟串口的空闲中断
typedef struct{
bool RecFinish;
bool RecCountStart;
uint16_t RecTimeCount100Ms;
}UART_TIME_CONTROL;
#define UART_TIME_CONTROL_100MS_INTER(stru) if((stru.RecCountStart == true) && (stru.RecFinish == false)){\
stru.RecTimeCount100Ms++;\
if(stru.RecTimeCount100Ms >= 2){\
stru.RecFinish = true;\
}else{\
stru.RecFinish = false;\
}\
}
#define UART_TIME_CONTROL_START_COUNT(stru) \
stru.RecFinish = false;\
stru.RecCountStart = true;\
stru.RecTimeCount100Ms = 0;
bool UART_TIME_CONTROL_TIMEOUT(UART_TIME_CONTROL* strptr);
bool UART_TIME_CONTROL_TIMEOUT(UART_TIME_CONTROL* strptr){
if(strptr->RecFinish == true){
strptr->RecCountStart = false;
strptr->RecFinish = false;
strptr->RecTimeCount100Ms = 0;
return true;
}
return false;
}