C语言宏,函数

// 十进制转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;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值