123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /*************************************************
- Copyright (c) 2019
- All rights reserved.
- File name: dlt645_data.c
- Description: DLT645 数据处理源文件
- History:
- 1. Version:
- Date: 2019-09-20
- Author: wangjunjie
- Modify:
- *************************************************/
- #include "dlt645_private.h"
- #include <string.h>
- #include "data_task.h"
- //字节位置枚举类型
- typedef enum
- {
- BYTE_RESET = 0, //重置
- BYTE_LOW_ADDRESS, //低位
- BYTE_HIGH_ADDRESS //高位
- } byte_part;
- /**
- * Name: _crc
- * Brief: crc和校验
- * Input:
- * @msg: 校验数据包
- * @len: 数据包长度
- * Output: 校验值
- */
- int _crc(uint8_t *msg, int len)
- {
- uint8_t crc = 0;
- while (len--)
- {
- crc += *msg++;
- }
- return crc;
- }
- /**
- * Name: dlt645_common_check
- * Brief: 645协议接收数据公共部分校验
- * Input:
- * @msg: 校验数据包
- * @len: 数据包长度
- * @addr: 从站地址
- * Output: 校验成功:0,校验失败:-1
- */
- int dlt645_common_check(uint8_t *msg, int len, uint8_t *addr)
- {
- //数据包长度校验
- if (len < 7)
- {
- return -1;
- }
- //数据帧标志校验
- if (msg[0] != DL645_START_CODE ||
- msg[DL645_ADDR_LEN + 1] != DL645_START_CODE ||
- msg[len - 1] != DL645_STOP_CODE)
- {
- DLT645_LOG("check code error!\n");
- return -1;
- }
- //CRC校验
- uint8_t crc = _crc(msg, len - 2);
- if (crc != msg[len - 2])
- {
- DLT645_LOG("check crc error!\n");
- return -1;
- }
- //控制码主从校验
- if ((msg[DL645_CONTROL_POS] & C_TD_MASK) == (C_TD_MASTER << C_TD_POS))
- {
- DLT645_LOG("check control direction error!\n");
- return -1;
- }
- //控制码应答校验
- if ((msg[DL645_CONTROL_POS] & C_ACK_MASK) == (C_ACK_ERR << C_ACK_POS))
- {
- DLT645_LOG("check ACK error!\n");
- return msg[len - 3];
- }
- //从站地址校验
- if (memcmp(msg + 1, addr, 6) != 0)
- {
- return -1;
- }
- return 0;
- }
- /**
- * Name: dec2bcd
- * Brief: 十进制转BCD码(目前支持32位数字大小)
- * Input:
- * @val: 十进制值
- * Output: BCD码值
- */
- uint32_t dec_to_bcd(uint32_t val)
- {
- uint32_t data = 0;
- if (val < 100)
- {
- uint8_t byte0 = val % 10;
- uint8_t byte1 = val / 10;
- data = (byte1 << 4) + byte0;
- }
- else if (val < 10000)
- {
- uint8_t byte0 = val % 10;
- uint8_t byte1 = (val / 10) % 10;
- uint8_t byte2 = (val / 100) % 10;
- uint8_t byte3 = (val / 1000) % 10;
- data = (byte3 << 12) +
- (byte2 << 8) +
- (byte1 << 4) + byte0;
- }
- else if (val < 1000000)
- {
- uint8_t byte0 = val % 10;
- uint8_t byte1 = (val / 10) % 10;
- uint8_t byte2 = (val / 100) % 10;
- uint8_t byte3 = (val / 1000) % 10;
- uint8_t byte4 = (val / 10000) % 10;
- uint8_t byte5 = (val / 100000) % 10;
- data = (byte5 << 20) +
- (byte4 << 16) +
- (byte3 << 12) +
- (byte2 << 8) +
- (byte1 << 4) + byte0;
- }
- else if (val < 100000000)
- {
- uint8_t byte0 = val % 10;
- uint8_t byte1 = (val / 10) % 10;
- uint8_t byte2 = (val / 100) % 10;
- uint8_t byte3 = (val / 1000) % 10;
- uint8_t byte4 = (val / 10000) % 10;
- uint8_t byte5 = (val / 100000) % 10;
- uint8_t byte6 = (val / 1000000) % 10;
- uint8_t byte7 = (val / 10000000) % 10;
- data = (byte7 << 28) +
- (byte6 << 24) +
- (byte5 << 20) +
- (byte4 << 16) +
- (byte3 << 12) +
- (byte2 << 8) +
- (byte1 << 4) + byte0;
- }
- return data;
- }
- /**
- * Name: str_to_bcd
- * Brief: 字符串转BCD形式
- * Input:
- * @str: 要转换的字符串
- * @bcd_store_address: 转换后的存储地址
- * @bcd_len: BCD码总长度
- * Output: 成功0,失败-1
- */
- int str_to_bcd(char *str, uint8_t *bcd_store_address, uint16_t bcd_len)
- {
- //字符串偏移
- int str_pos = bcd_len * 2 - strlen(str);
- //字符串比BCD码长度长
- if (str_pos < 0)
- {
- return -1;
- }
- memset(bcd_store_address, 0, bcd_len);
- for (int i = 0; i < strlen(str); i++)
- {
- if (str[i] >= '0' && str[i] <= '9')
- {
- bcd_store_address[(i + str_pos) / 2] |= (str[i] - '0') << (4 * ((i + 1 + (strlen(str) % 2)) % 2));
- }
- else
- {
- //当前字符不为数字,返回错误
- return -1;
- }
- }
- return 0;
- }
- /**
- * Name: data_package_translate_to_int
- * Brief: 将接收到的dlt645数据包中的数据转化为整数
- * Input:
- * @read_data: 数据首地址
- * @len: 数据长度
- * Output: 转化后的整数
- */
- int data_package_translate_to_int(uint8_t *read_data, uint16_t len)
- {
- //权值
- uint8_t number_weight = 0;
- //当前数组下标索引
- uint8_t current_index = 0;
- //当前解析字节位
- uint8_t current_byte_part = BYTE_RESET;
- //当前整数值
- int i_value = 0;
- while (len--)
- {
- current_byte_part = BYTE_LOW_ADDRESS;
- do
- {
- switch (current_byte_part)
- {
- //当前处理字节低位
- case BYTE_LOW_ADDRESS:
- i_value += ((read_data[current_index] - 0x33) & 0x0f) * my_pow(10,number_weight);
- number_weight++;
- current_byte_part = BYTE_HIGH_ADDRESS;
- break;
- //当前处理字节高位
- case BYTE_HIGH_ADDRESS:
- i_value += ((read_data[current_index] - 0x33) >> 4) * my_pow(10,number_weight);
- number_weight++;
- current_byte_part = BYTE_RESET;
- break;
- }
- } while (current_byte_part != BYTE_RESET);
- current_index++;
- }
- return i_value;
- }
- /**
- * Name: dlt645_data_parse_by_format_to_float
- * Brief: 根据数据格式将645协议读取的数据转换为真实数据并存储
- * !真实数据为浮点数据,需要注意的是无论读取数据长度是多少,存储数据长度都应是4字节
- * Input:
- * @read_data: 645协议读取的数据
- * @read_len: 读取数据的长度
- * @data_format: 转换的数据格式,如 XX.XX,XX.XXX
- * Output: 转换成功返回0,失败返回-1
- */
- int dlt645_data_parse_by_format_to_float(uint8_t *read_data, uint16_t read_len, const char *data_format, uint8_t *store_address)
- {
- //权值
- int num_weight = 0;
- int ival = data_package_translate_to_int(read_data, read_len);
- for (int i = 0; i < strlen(data_format); i++)
- {
- if (*(data_format + i) == '.')
- {
- num_weight = strlen(data_format) - i - 1;
- if (num_weight < 0)
- {
- return -1;
- }
- break;
- }
- }
- float fval = ival / my_pow(10,num_weight);
- memcpy(store_address, &fval, 4);
- return 0;
- }
- int dlt645_data_parse_by_format_to_float_and_DATE(uint8_t *read_data, uint16_t read_len, const char *data_format, uint8_t *store_address)
- {
- int num_weight = 0;
- int ival = data_package_translate_to_int(read_data, read_len);
- for (int i = 0; i < strlen(data_format); i++)
- {
- if (*(data_format + i) == '.')
- {
- num_weight = strlen(data_format) - i - 1;
- if (num_weight < 0)
- {
- return -1;
- }
- break;
- }
- }
- float fval = ival / my_pow(10,num_weight);
- memcpy(store_address, &fval, 4);
- return 0;
- }
|