dlt645_data.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*************************************************
  2. Copyright (c) 2019
  3. All rights reserved.
  4. File name: dlt645_data.c
  5. Description: DLT645 数据处理源文件
  6. History:
  7. 1. Version:
  8. Date: 2019-09-20
  9. Author: wangjunjie
  10. Modify:
  11. *************************************************/
  12. #include "dlt645_private.h"
  13. #include <string.h>
  14. #include "data_task.h"
  15. //字节位置枚举类型
  16. typedef enum
  17. {
  18. BYTE_RESET = 0, //重置
  19. BYTE_LOW_ADDRESS, //低位
  20. BYTE_HIGH_ADDRESS //高位
  21. } byte_part;
  22. /**
  23. * Name: _crc
  24. * Brief: crc和校验
  25. * Input:
  26. * @msg: 校验数据包
  27. * @len: 数据包长度
  28. * Output: 校验值
  29. */
  30. int _crc(uint8_t *msg, int len)
  31. {
  32. uint8_t crc = 0;
  33. while (len--)
  34. {
  35. crc += *msg++;
  36. }
  37. return crc;
  38. }
  39. /**
  40. * Name: dlt645_common_check
  41. * Brief: 645协议接收数据公共部分校验
  42. * Input:
  43. * @msg: 校验数据包
  44. * @len: 数据包长度
  45. * @addr: 从站地址
  46. * Output: 校验成功:0,校验失败:-1
  47. */
  48. int dlt645_common_check(uint8_t *msg, int len, uint8_t *addr)
  49. {
  50. //数据包长度校验
  51. if (len < 7)
  52. {
  53. return -1;
  54. }
  55. //数据帧标志校验
  56. if (msg[0] != DL645_START_CODE ||
  57. msg[DL645_ADDR_LEN + 1] != DL645_START_CODE ||
  58. msg[len - 1] != DL645_STOP_CODE)
  59. {
  60. DLT645_LOG("check code error!\n");
  61. return -1;
  62. }
  63. //CRC校验
  64. uint8_t crc = _crc(msg, len - 2);
  65. if (crc != msg[len - 2])
  66. {
  67. DLT645_LOG("check crc error!\n");
  68. return -1;
  69. }
  70. //控制码主从校验
  71. if ((msg[DL645_CONTROL_POS] & C_TD_MASK) == (C_TD_MASTER << C_TD_POS))
  72. {
  73. DLT645_LOG("check control direction error!\n");
  74. return -1;
  75. }
  76. //控制码应答校验
  77. if ((msg[DL645_CONTROL_POS] & C_ACK_MASK) == (C_ACK_ERR << C_ACK_POS))
  78. {
  79. DLT645_LOG("check ACK error!\n");
  80. return msg[len - 3];
  81. }
  82. //从站地址校验
  83. if (memcmp(msg + 1, addr, 6) != 0)
  84. {
  85. return -1;
  86. }
  87. return 0;
  88. }
  89. /**
  90. * Name: dec2bcd
  91. * Brief: 十进制转BCD码(目前支持32位数字大小)
  92. * Input:
  93. * @val: 十进制值
  94. * Output: BCD码值
  95. */
  96. uint32_t dec_to_bcd(uint32_t val)
  97. {
  98. uint32_t data = 0;
  99. if (val < 100)
  100. {
  101. uint8_t byte0 = val % 10;
  102. uint8_t byte1 = val / 10;
  103. data = (byte1 << 4) + byte0;
  104. }
  105. else if (val < 10000)
  106. {
  107. uint8_t byte0 = val % 10;
  108. uint8_t byte1 = (val / 10) % 10;
  109. uint8_t byte2 = (val / 100) % 10;
  110. uint8_t byte3 = (val / 1000) % 10;
  111. data = (byte3 << 12) +
  112. (byte2 << 8) +
  113. (byte1 << 4) + byte0;
  114. }
  115. else if (val < 1000000)
  116. {
  117. uint8_t byte0 = val % 10;
  118. uint8_t byte1 = (val / 10) % 10;
  119. uint8_t byte2 = (val / 100) % 10;
  120. uint8_t byte3 = (val / 1000) % 10;
  121. uint8_t byte4 = (val / 10000) % 10;
  122. uint8_t byte5 = (val / 100000) % 10;
  123. data = (byte5 << 20) +
  124. (byte4 << 16) +
  125. (byte3 << 12) +
  126. (byte2 << 8) +
  127. (byte1 << 4) + byte0;
  128. }
  129. else if (val < 100000000)
  130. {
  131. uint8_t byte0 = val % 10;
  132. uint8_t byte1 = (val / 10) % 10;
  133. uint8_t byte2 = (val / 100) % 10;
  134. uint8_t byte3 = (val / 1000) % 10;
  135. uint8_t byte4 = (val / 10000) % 10;
  136. uint8_t byte5 = (val / 100000) % 10;
  137. uint8_t byte6 = (val / 1000000) % 10;
  138. uint8_t byte7 = (val / 10000000) % 10;
  139. data = (byte7 << 28) +
  140. (byte6 << 24) +
  141. (byte5 << 20) +
  142. (byte4 << 16) +
  143. (byte3 << 12) +
  144. (byte2 << 8) +
  145. (byte1 << 4) + byte0;
  146. }
  147. return data;
  148. }
  149. /**
  150. * Name: str_to_bcd
  151. * Brief: 字符串转BCD形式
  152. * Input:
  153. * @str: 要转换的字符串
  154. * @bcd_store_address: 转换后的存储地址
  155. * @bcd_len: BCD码总长度
  156. * Output: 成功0,失败-1
  157. */
  158. int str_to_bcd(char *str, uint8_t *bcd_store_address, uint16_t bcd_len)
  159. {
  160. //字符串偏移
  161. int str_pos = bcd_len * 2 - strlen(str);
  162. //字符串比BCD码长度长
  163. if (str_pos < 0)
  164. {
  165. return -1;
  166. }
  167. memset(bcd_store_address, 0, bcd_len);
  168. for (int i = 0; i < strlen(str); i++)
  169. {
  170. if (str[i] >= '0' && str[i] <= '9')
  171. {
  172. bcd_store_address[(i + str_pos) / 2] |= (str[i] - '0') << (4 * ((i + 1 + (strlen(str) % 2)) % 2));
  173. }
  174. else
  175. {
  176. //当前字符不为数字,返回错误
  177. return -1;
  178. }
  179. }
  180. return 0;
  181. }
  182. /**
  183. * Name: data_package_translate_to_int
  184. * Brief: 将接收到的dlt645数据包中的数据转化为整数
  185. * Input:
  186. * @read_data: 数据首地址
  187. * @len: 数据长度
  188. * Output: 转化后的整数
  189. */
  190. int data_package_translate_to_int(uint8_t *read_data, uint16_t len)
  191. {
  192. //权值
  193. uint8_t number_weight = 0;
  194. //当前数组下标索引
  195. uint8_t current_index = 0;
  196. //当前解析字节位
  197. uint8_t current_byte_part = BYTE_RESET;
  198. //当前整数值
  199. int i_value = 0;
  200. while (len--)
  201. {
  202. current_byte_part = BYTE_LOW_ADDRESS;
  203. do
  204. {
  205. switch (current_byte_part)
  206. {
  207. //当前处理字节低位
  208. case BYTE_LOW_ADDRESS:
  209. i_value += ((read_data[current_index] - 0x33) & 0x0f) * my_pow(10,number_weight);
  210. number_weight++;
  211. current_byte_part = BYTE_HIGH_ADDRESS;
  212. break;
  213. //当前处理字节高位
  214. case BYTE_HIGH_ADDRESS:
  215. i_value += ((read_data[current_index] - 0x33) >> 4) * my_pow(10,number_weight);
  216. number_weight++;
  217. current_byte_part = BYTE_RESET;
  218. break;
  219. }
  220. } while (current_byte_part != BYTE_RESET);
  221. current_index++;
  222. }
  223. return i_value;
  224. }
  225. /**
  226. * Name: dlt645_data_parse_by_format_to_float
  227. * Brief: 根据数据格式将645协议读取的数据转换为真实数据并存储
  228. * !真实数据为浮点数据,需要注意的是无论读取数据长度是多少,存储数据长度都应是4字节
  229. * Input:
  230. * @read_data: 645协议读取的数据
  231. * @read_len: 读取数据的长度
  232. * @data_format: 转换的数据格式,如 XX.XX,XX.XXX
  233. * Output: 转换成功返回0,失败返回-1
  234. */
  235. int dlt645_data_parse_by_format_to_float(uint8_t *read_data, uint16_t read_len, const char *data_format, uint8_t *store_address)
  236. {
  237. //权值
  238. int num_weight = 0;
  239. int ival = data_package_translate_to_int(read_data, read_len);
  240. for (int i = 0; i < strlen(data_format); i++)
  241. {
  242. if (*(data_format + i) == '.')
  243. {
  244. num_weight = strlen(data_format) - i - 1;
  245. if (num_weight < 0)
  246. {
  247. return -1;
  248. }
  249. break;
  250. }
  251. }
  252. float fval = ival / my_pow(10,num_weight);
  253. memcpy(store_address, &fval, 4);
  254. return 0;
  255. }
  256. 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)
  257. {
  258. int num_weight = 0;
  259. int ival = data_package_translate_to_int(read_data, read_len);
  260. for (int i = 0; i < strlen(data_format); i++)
  261. {
  262. if (*(data_format + i) == '.')
  263. {
  264. num_weight = strlen(data_format) - i - 1;
  265. if (num_weight < 0)
  266. {
  267. return -1;
  268. }
  269. break;
  270. }
  271. }
  272. float fval = ival / my_pow(10,num_weight);
  273. memcpy(store_address, &fval, 4);
  274. return 0;
  275. }