#include "string.h" #include "prj_com.h" void HexToStr(uint32_t Hex, char *Str, int16_t Len) { unsigned char Ch; while((Len--)>0){ Ch = Hex & 0xFU; Ch += (Ch<=0x9U) ? 0x30 : 0x37; *(Str+Len) = Ch; Hex = Hex>>4; } } // judge and convert a string to integer // return 0: either HEX or DEC found // return 10: DEC convertion completed // return 16: HEX convertion completed int str2int(char *str, uint32_t *n) { char ch; *n = 0; ch = *str++; // get 1st char of string if (ch<0x30 || ch>0x39) { // not ASCII 0~9 return(0); } if (ch==0x30) { // 1st char is '0' ch = *str++; if (ch=='\0') { // 2nd char is 'end' return(10); // DEC 0 found } if (ch!='x' && ch!='X') { // not HEX return(0); } ch = *str++; if (ch=='\0') { // 3rd char is 'end' return(0); } while (ch!='\0' && ch!=0x20) { // HEX convertion while (ch=='_') { // skip '_' between numbers ch = *str++; } if (ch>=0x30 && ch<=0x39) { // ASCII 0~9 ch -= 0x30; } else if (ch>=0x41 && ch<=0x46) { // ASCII A~F ch -= 0x41 - 10; } else if (ch>=0x61 && ch<=0x66) { // ASCII a~f ch -= 0x61 - 10; } else { return(0); } *n = (*n<<4) + ch; ch = *str++; } return(16); // HEX return } while (ch!='\0' && ch!=0x20) { // DEC convertion while (ch=='_') { // skip '_' between numbers ch = *str++; } if (ch>=0x30 && ch<=0x39) { ch -= 0x30; } else { return(0); } *n = (*n*10) + ch; ch = *str++; } return(10); // DEC return } // judge and convert a string to float // return 0: error, not float found // return 1: float convertion completed int str2float(char *str, float *f) { char ch; char fraction = 0; float precision = 1.0f; *f = 0.0f; ch = *str++; // get 1st char of string if (ch=='-'){ precision = -1.0f; ch = *str++; // skip '-' } while(ch!='\0' && ch!=0x20){ if (ch>=0x30 && ch<=0x39) { ch -= 0x30; *f = (*f)*10.0f + ch; if (fraction){ precision *= 0.1f; } } else if (ch=='.') { fraction = 1; } else { // unknow char return(0); } ch = *str++; } *f *= precision; return(1); } void int2str(int n, char *str) { int i = 0, j, sign; char temp; if ((sign = n) < 0) n = -n; do { str[i++] = n % 10 + '0'; } while ((n /= 10) > 0); if (sign < 0) str[i++] = '-'; str[i] = '\0'; for (j = 0; j < i / 2; j++) { temp = str[j]; str[j] = str[i - j - 1]; str[i - j - 1] = temp; } } void HexBufToStr(char *dest, unsigned char *src, int len) { char ddl, ddh; int i; for (i = 0; i < len; i++) { ddh = 48 + src[i] / 16; ddl = 48 + src[i] % 16; if (ddh > 57) { ddh = ddh + 7; } if (ddl > 57) { ddl = ddl + 7; } dest[i * 2] = ddh; dest[i * 2 + 1] = ddl; } dest[len * 2] = '\0'; } uint8_t ToUpper(uint8_t c) { return (c >= 'a' && c <= 'z') ? c & 0x5f : c; } void StrToHexBuf(char *dest, char *src, int len) { char h1, h2; char s1, s2; int i; for (i = 0; i < len; i++) { h1 = src[2 * i]; h2 = src[2 * i + 1]; s1 = ToUpper(h1) - 0x30; if (s1 > 9) { s1 -= 7; } s2 = ToUpper(h2) - 0x30; if (s2 > 9) { s2 -= 7; } dest[i] = s1 * 16 + s2; } } // width 2:uint16_t; 4:uint32_t; others:reserved // num number of uint16_t or uint32_t, not byte number void ToggleEndian(uint8_t *src, uint8_t *dst, uint16_t width, uint16_t num) { uint16_t b; src--; src += width; while(1){ b = width; while(b--){ *dst++ = *src--; } if (--num==0) { break; } src += (width<<1); } } // 1) pattern = 0xEDB88320 // G(x)=x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 // when initial=0xFFFFFFFF, GoodFCS = 0xDEBB20E3 uint32_t com_crc32L_next(uint32_t crc_cur, uint8_t *data, uint32_t len, uint32_t pattern) { uint8_t u8; uint8_t i; uint8_t fb; while(len-->0){ u8 = *data++; for(i=0;i<8;i++){ fb = (u8 ^ (uint8_t)crc_cur) & 0x01u; u8 = u8>>1; // LSB first crc_cur = crc_cur>>1; if (fb){ crc_cur = crc_cur ^ pattern; } } } return(crc_cur); } // 1) pattern = 0x8408 // G(x)=x16+x12+x5+1 // when initial=0xFFFF, GoodFCS = 0xF0B8 // 2) pattern = 0xA001 // G(x)=x16+x15+x2+1 // when initial=0xFFFF, GoodFCS = 0xF0B8 uint16_t com_crc16L_next(uint16_t crc_cur, uint8_t *data, uint32_t len, uint16_t pattern) { uint8_t u8; uint8_t i; uint8_t fb; while(len-->0){ u8 = *data++; for(i=0;i<8;i++){ fb = (u8 ^ (uint8_t)crc_cur) & 0x01u; u8 = u8>>1; // LSB first crc_cur = crc_cur>>1; if (fb){ crc_cur = crc_cur ^ pattern; } } } return(crc_cur); } // 1) pattern = 0x04C11DB7 // G(x)=x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 // when initial=0xFFFFFFFF, GoodFCS = 0xC704DD7B uint32_t com_crc32H_next(uint32_t crc_cur, uint8_t *data, uint32_t len, uint32_t pattern) { uint8_t u8; uint8_t i; uint8_t fb; while(len-->0){ u8 = *data++; for(i=0;i<8;i++){ fb = (u8 ^ (uint8_t)(crc_cur>>24)) & 0x80u; u8 = u8<<1; // MSB first crc_cur = crc_cur<<1; if (fb){ crc_cur = crc_cur ^ pattern; } } } return(crc_cur); } // 1) pattern = 0x1021 // G(x)=x16+x12+x5+1 // when initial=0xFFFF, GoodFCS = 0x // 2) pattern = 0x8005 // G(x)=x16+x15+x2+1 // when initial=0xFFFF, GoodFCS = 0x uint16_t com_crc16H_next(uint16_t crc_cur, uint8_t *data, uint32_t len, uint16_t pattern) { uint8_t u8; uint8_t i; uint8_t fb; while(len-->0){ u8 = *data++; for(i=0;i<8;i++){ fb = (u8 ^ (uint8_t)(crc_cur>>8)) & 0x80u; u8 = u8<<1; // MSB first crc_cur = crc_cur<<1; if (fb){ crc_cur = crc_cur ^ pattern; } } } return(crc_cur); } uint32_t strnchar(const char *src, char ch, int index) { int num = 0; const char *p = src; while (*p) { if(*p == ch) { if(num++ == index) { break; } else { p++; } } else { p++; } } return (uint32_t)(strlen(src) - strlen(p)); } uint32_t strcntchar(const char *src, char ch) { uint32_t num = 0; const char *p = src; while (*p) { if(*p == ch) { num++; } p++; } return num; } static uint8_t month_days[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}}; uint8_t is_leap(uint16_t year) { return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0; } uint8_t last_day_of_month(uint8_t year, uint8_t month) { return month_days[month][is_leap(2000 + year)]; } uint32_t days_from_leap_year_begin(uint8_t month, uint8_t day) { uint8_t i; uint32_t days = 0; for (i = 1; i < month; i++) { days += month_days[i][1]; } return (days + day); } uint32_t next_day(uint32_t date) { uint16_t year = (uint16_t)(date >> 16); uint8_t month = (uint8_t)(date >> 8); uint8_t day = (uint8_t)date; day++; if (day > month_days[month][is_leap(year)]) { day -= month_days[month][is_leap(year)]; month++; } if (month >= 13) { month = 1; year++; } return (year << 16) | (month << 8) | day; } uint32_t prev_day(uint32_t date) { uint16_t year = (uint16_t)(date >> 16); uint8_t month = (uint8_t)(date >> 8); uint8_t day = (uint8_t)date; uint16_t y; uint8_t m; uint8_t d = day - 1; if (d != 0) { y = year; m = month; } else { m = month - 1; y = year; if (m != 0) { d = month_days[m][is_leap(y)]; } else { y = year - 1; m = 12; d = month_days[m][is_leap(y)]; } } return (y << 16) | (m << 8) | d; } uint32_t next_month(uint32_t date) { uint16_t year = (uint16_t)(date >> 16); uint8_t month = (uint8_t)(date >> 8); month++; if (month >= 13) { month = 1; year++; } return (year << 16) | (month << 8); } uint32_t prev_month(uint32_t date) { uint16_t year = (uint16_t)(date >> 16); uint8_t month = (uint8_t)(date >> 8); month--; if (month == 0) { year = year - 1; month = 12; } return (year << 16) | (month << 8); } void time_add_secs(tm_t *dest, tm_t *src, uint32_t secs) { uint16_t days; uint32_t date; uint16_t i; memcpy(dest, src, sizeof(tm_t)); dest->sec += secs; if (dest->sec >= 60) { dest->min += (dest->sec / 60); dest->sec %= 60; if (dest->min >= 60) { dest->hour += (dest->min / 60); dest->min %= 60; if (dest->hour >= 24) { days = dest->hour / 24; dest->hour %= 24; date = (dest->year << 16) | (dest->month << 8) | dest->day; for (i = 0; i < days; i++) { date = next_day(date); } dest->year = (uint8_t)(date >> 16); dest->month = (uint8_t)(date >> 8); dest->day = (uint8_t)date; } } } } void time_sub_secs(tm_t *dest, tm_t *src, uint32_t secs) { uint16_t days; uint32_t date; uint16_t i; memcpy(dest, src, sizeof(tm_t)); // 处理减去秒数发生借位的情况 if (dest->sec < secs) { uint32_t borrow_secs = secs - dest->sec; dest->sec = 60 - (borrow_secs % 60); uint32_t borrow_mins = borrow_secs / 60; if (borrow_secs % 60 != 0) { borrow_mins++; } if (dest->min < borrow_mins) { uint32_t borrow_mins_actual = borrow_mins - dest->min; dest->min = 60 - (borrow_mins_actual % 60); uint32_t borrow_hours = borrow_mins_actual / 60; if (borrow_mins_actual % 60 != 0) { borrow_hours++; } if (dest->hour < borrow_hours) { uint32_t borrow_hours_actual = borrow_hours - dest->hour; dest->hour = 24 - (borrow_hours_actual % 24); days = borrow_hours_actual / 24; if (borrow_hours_actual % 24 != 0) { days++; } date = (dest->year << 16) | (dest->month << 8) | dest->day; for (i = 0; i < days; i++) { date = prev_day(date); } dest->year = (uint8_t)(date >> 16); dest->month = (uint8_t)(date >> 8); dest->day = (uint8_t)date; } else { dest->hour -= borrow_hours; } } else { dest->min -= borrow_mins; } } else { dest->sec -= secs; } } uint8_t check_sum(volatile uint8_t *data, uint16_t len) { uint8_t sum = 0; uint16_t i; for (i = 0; i < len; i++) { sum += data[i]; } return sum; } //add by yuewei 20260304 uint16_t check_sum_2_byte(volatile uint8_t *data, uint16_t len) { uint16_t sum = 0; uint16_t i; for (i = 0; i < len; i++) { sum += data[i]; } return sum; } //add by yuewei 20260317 /** * @brief 计算CRC16/MODBUS校验值(逐位计算法) * @param data: 待校验的数据首地址 * @param length: 数据长度 * @return 16位校验结果(高字节在前,低字节在后) */ uint16_t crc16_modbus(volatile uint8_t *data, uint16_t length) { uint16_t crc = 0xFFFF; uint8_t i; while (length--) { crc ^= *data++; for (i = 0; i < 8; i++) { if (crc & 0x0001) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; }