CJT188.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include "CJT188.h"
  2. #include "string.h"
  3. #include "timer.h"
  4. #include "gateway_message.h"
  5. #include "tcp_server.h"
  6. #include "data_task.h"
  7. CTJBus_t ctjData;
  8. void cjt_callback(UART_HandleTypeDef *husart)
  9. {
  10. if(__HAL_UART_GET_FLAG(husart, UART_FLAG_RXNE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_RXNE))
  11. {
  12. if (ctjData.rxIndex < _CJT_RXSIZE - 1)
  13. {
  14. ctjData.rxBuf[ctjData.rxIndex] = husart->Instance->DR;
  15. ctjData.rxIndex++;
  16. }
  17. else
  18. {
  19. uint8_t data = husart->Instance->DR;
  20. }
  21. }
  22. if ((ctjData.rxIndex > 0) && RESET != __HAL_UART_GET_FLAG(husart, USART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_IDLE))
  23. {
  24. uint8_t i;
  25. ctjData.done = 1;
  26. i = husart->Instance->SR;
  27. i = husart->Instance->DR;
  28. return;
  29. }
  30. ctjData.rxTime = gettick();
  31. }
  32. // ##################################################################################################
  33. bool cjt_sendRaw(uint8_t *data, uint16_t size, uint32_t timeout)
  34. {
  35. GATEWAY_PARAMS *get;
  36. get= get_gateway_config_params();
  37. while(ctjData.txBusy == 1)
  38. delay_ms(1);
  39. ctjData.txBusy = 1;
  40. memset(ctjData.rxBuf, 0, _CJT_RXSIZE);
  41. ctjData.rxIndex = 0;
  42. ctjData.done = 0;
  43. uint32_t startTime = gettick();
  44. portENTER_CRITICAL();
  45. if(get->comProtocol){ // get->protocol 1:232 0:485
  46. USART_232_Send(data,size);
  47. }else{
  48. USART_485_Send(data,size);
  49. }
  50. portEXIT_CRITICAL();
  51. ctjData.done=0;
  52. ctjData.txBusy = 0;
  53. return true;
  54. }
  55. // ##################################################################################################
  56. uint16_t cjt_receiveRaw(uint32_t timeout)
  57. {
  58. uint32_t startTime = gettick();
  59. while (1)
  60. {
  61. if (gettick() - startTime> timeout * 1000)
  62. return 0;
  63. if (ctjData.done == 1)
  64. {
  65. return ctjData.rxIndex;
  66. }
  67. delay_ms(5);
  68. }
  69. }
  70. bool cjt_init(uint32_t timeout)
  71. {
  72. // HAL_GPIO_WritePin(_MMODBUS_CTRL_GPIO, _MMODBUS_CTRL_PIN, GPIO_PIN_RESET); 此处初始化在485 init过
  73. HAL_GPIO_WritePin(_CTJ_CTRL_GPIO, _CTJ_CTRL_PIN,GPIO_PIN_RESET);
  74. memset(&ctjData, 0, sizeof(ctjData));
  75. ctjData.timeout = timeout;
  76. return true;
  77. }
  78. /*
  79. *********************************************************************************************************
  80. * 函 数 名: bool cjt_read_meter_data(uint8_t* slaveAddress, uint8_t *data, uint8_t protocol)
  81. * 功能说明: 读取仪表上的数据
  82. * 形 参1: slaveAddress:读取的地址
  83. * 形 参2: data:接收的内存地址
  84. * 形 参3: protocol:读取的仪表类型 0x10(水表) 0x30(燃气表) 0x40(电表)
  85. * 返 回 值: true: 成功 false:失败
  86. *********************************************************************************************************
  87. */
  88. bool cjt_read_meter_data(uint8_t* slaveAddress, double* data, uint8_t protocol)
  89. {
  90. uint8_t txData[19];
  91. txData[0] = 0xFE;
  92. txData[1] = 0xFE;
  93. txData[2] = 0xFE; // 引导符
  94. txData[3] = 0x68; // 起始帧
  95. if(protocol == 0x10) // 水表
  96. txData[4] = 0x10;
  97. else if(protocol == 0x30) // 燃气表
  98. txData[4] = 0x30;
  99. else if(protocol == 0x40) // 电表
  100. txData[4] = 0x40;
  101. txData[5] = slaveAddress[0]; // 地址 生产流水号最低字节
  102. txData[6] = slaveAddress[1]; // 地址 生产流水号次高字节
  103. txData[7] = slaveAddress[2]; // 地址 生产流水号最高字节
  104. txData[8] = slaveAddress[3]; // 地址 表计生产月份
  105. txData[9] = slaveAddress[4]; // 地址 表计生产年份
  106. txData[10] = slaveAddress[5]; // 地址 生产厂商代码低字节
  107. txData[11] = slaveAddress[6]; // 地址 生产厂商代码高字节
  108. txData[12] = 0x01; // 控制码 CTR_0
  109. txData[13] = 0x03; // 数据域长度
  110. txData[14] = 0x90; // 数据标识DI0
  111. txData[15] = 0x1F; // 数据标识DI1
  112. txData[16] = 0x01; // 序列号
  113. uint8_t crc = 0;
  114. for(uint8_t i = 0; i < 14; i++)
  115. {
  116. crc += txData[i + 3];
  117. }
  118. txData[17] = crc;
  119. txData[18] = 0x16; // 结束帧
  120. cjt_sendRaw(txData, 19, 100);
  121. uint16_t recLen = cjt_receiveRaw(ctjData.timeout);
  122. if (recLen == 0)
  123. return false;
  124. for(uint8_t i = 0; i < 12; i++)
  125. {
  126. if(ctjData.rxBuf[i] != txData[i])
  127. return false;
  128. }
  129. if (ctjData.rxBuf[12] != txData[12] + 0x80)
  130. return false;
  131. if (ctjData.rxBuf[14] != txData[14])
  132. return false;
  133. if (ctjData.rxBuf[15] != txData[15])
  134. return false;
  135. crc = 0;
  136. for(uint8_t i = 0; i < 20; i++)
  137. {
  138. crc += ctjData.rxBuf[i + 3];
  139. }
  140. if (ctjData.rxBuf[23] != crc)
  141. return false;
  142. if (ctjData.rxBuf[24] != txData[18])
  143. return false;
  144. if(TransparentModeFlag) return true;
  145. *data = data_translate_to_float(ctjData.rxBuf);
  146. return true;
  147. }
  148. /*
  149. *********************************************************************************************************
  150. * 函 数 名: bool cjt_set_addr(uint8_t *addr)
  151. * 功能说明: 设置仪表地址
  152. * 形 参: addr:需要设置的新地址
  153. * 返 回 值: true: 成功 false:失败
  154. *********************************************************************************************************
  155. */
  156. bool cjt_set_addr(uint8_t *addr)
  157. {
  158. uint8_t txData[26];
  159. txData[0] = 0xFE;
  160. txData[1] = 0xFE;
  161. txData[2] = 0xFE; // 引导符
  162. txData[3] = 0x68; // 起始帧
  163. txData[4] = 0xAA; // 水表、燃气表、电表
  164. txData[5] = 0xAA;
  165. txData[6] = 0xAA;
  166. txData[7] = 0xAA;
  167. txData[8] = 0xAA;
  168. txData[9] = 0xAA;
  169. txData[10] = 0xAA;
  170. txData[11] = 0xAA;
  171. txData[12] = 0x15; // 控制码 CTR_3
  172. txData[13] = 0x0A; // 数据域长度
  173. txData[14] = 0x18; // 数据标识DI0
  174. txData[15] = 0xA0; // 数据标识DI1
  175. txData[16] = 0x00; // 序列号
  176. txData[17] = addr[6]; // 新地址
  177. txData[18] = addr[5]; // 新地址
  178. txData[19] = addr[4]; // 新地址
  179. txData[20] = addr[3]; // 新地址
  180. txData[21] = addr[2]; // 新地址
  181. txData[22] = addr[1]; // 新地址
  182. txData[23] = addr[0]; // 新地址
  183. uint8_t crc = 0;
  184. for(uint8_t i = 0; i < 21; i++)
  185. {
  186. crc += txData[i + 3];
  187. }
  188. txData[24] = crc;
  189. txData[25] = 0x16;
  190. cjt_sendRaw(txData, 26, 100);
  191. uint16_t recLen = cjt_receiveRaw(ctjData.timeout);
  192. if (recLen == 0)
  193. return false;
  194. if (ctjData.rxBuf[3] != txData[3])
  195. return false;
  196. for(uint8_t i = 0; i < 7; i++)
  197. {
  198. if(ctjData.rxBuf[i + 5] != txData[23 - i])
  199. return false;
  200. }
  201. if(ctjData.rxBuf[12] != txData[12] + 0x80)
  202. return false;
  203. if(ctjData.rxBuf[14] != txData[14] && ctjData.rxBuf[15] != txData[15] )
  204. return false;
  205. crc = 0;
  206. for(uint8_t i = 0; i < 14; i++)
  207. {
  208. crc += ctjData.rxBuf[i + 3];
  209. }
  210. if(ctjData.rxBuf[17] != crc)
  211. return false;
  212. if(ctjData.rxBuf[18] != txData[25])
  213. return false;
  214. return true;
  215. }
  216. /*
  217. *********************************************************************************************************
  218. * 函 数 名: bool cjt_read_addr(uint8_t *add)
  219. * 功能说明: 读取仪表地址
  220. * 形 参: data:读取地址的存放地址
  221. * 返 回 值: true: 成功 false:失败
  222. *********************************************************************************************************
  223. */
  224. bool cjt_read_addr(uint8_t *add)
  225. {
  226. uint8_t txData[19];
  227. txData[0] = 0xFE;
  228. txData[1] = 0xFE;
  229. txData[2] = 0xFE; // 引导符
  230. txData[3] = 0x68; // 起始帧
  231. txData[4] = 0xAA; // 水表、燃气表、电表
  232. txData[5] = 0xAA;
  233. txData[6] = 0xAA;
  234. txData[7] = 0xAA;
  235. txData[8] = 0xAA;
  236. txData[9] = 0xAA;
  237. txData[10] = 0xAA;
  238. txData[11] = 0xAA;
  239. txData[12] = 0x03; // 控制码
  240. txData[13] = 0x03; // 数据域长度
  241. txData[14] = 0x81; // 数据标识DI0
  242. txData[15] = 0x0A; // 数据标识DI1
  243. txData[16] = 0x00; // 序列号
  244. uint8_t crc = 0;
  245. for(uint8_t i = 0; i < 14; i++)
  246. {
  247. crc += txData[i + 3];
  248. }
  249. txData[17] = crc; // crc
  250. txData[18] = 0x16; // 结束帧
  251. cjt_sendRaw(txData, 19, 100);
  252. uint16_t recLen = cjt_receiveRaw(ctjData.timeout);
  253. if (recLen == 0)
  254. return false;
  255. if (ctjData.rxBuf[3] != txData[3])
  256. return false;
  257. if (ctjData.rxBuf[12] != txData[12] + 0x80)
  258. return false;
  259. for(uint8_t i = 0; i < 4; i++)
  260. {
  261. if(ctjData.rxBuf[i + 13] != txData[i + 13])
  262. return false;
  263. }
  264. crc = 0;
  265. for(uint8_t i = 0; i < 14; i++)
  266. {
  267. crc += ctjData.rxBuf[i + 3];
  268. }
  269. if(ctjData.rxBuf[17] != crc)
  270. return false;
  271. if(ctjData.rxBuf[18] != txData[18])
  272. return false;
  273. if(add != NULL)
  274. {
  275. for(uint8_t i = 0; i < 7; i++)
  276. {
  277. add[6 - i] = ctjData.rxBuf[i + 5];
  278. }
  279. }
  280. return true;
  281. }
  282. // 将读取的数据转换成double型
  283. double data_translate_to_float(uint8_t* msg)
  284. {
  285. int val;
  286. val += ((0xff & (msg[17]>>4))*10 +(0xf & msg[17]));
  287. val += ((0xff & (msg[18]>>4))*10 +(0xf & msg[18])) * my_pow(10,2);
  288. val += ((0xff & (msg[19]>>4))*10 +(0xf & msg[19])) * my_pow(10,4);
  289. val += ((0xff & (msg[20]>>4))*10 +(0xf & msg[20])) * my_pow(10,6);
  290. return (double)(val)/100.0;
  291. }