WaterMeter.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /********************************************************************************
  2. * File Name: WaterMeter.c
  3. * Function Describe: 水表数据接口
  4. 采用RS485通讯,基于Mobus协议
  5. * Explain:
  6. * Writer: ShiLiangWen
  7. * Date: 2019-2-14
  8. 1、0361-0362 2 总是读出 361.00 参见注 2 IEEE754
  9. TX: 01 03 01 68 00 02 44 2B
  10. RX: 01 03 04 80 00 43 B4 E2 B4
  11. Display: 40361 = 361.000000
  12. 2、0363-0364 2 总是读出 363348858 long
  13. TX:01 03 01 6A 00 02 E5 EB
  14. RX:01 03 04 43 7A 15 A8 C1 40
  15. Display: 40363 = 363348858
  16. 3、0365-0366 2 总是读出 -987654321 long
  17. TX: 01 03 01 6C 00 02 05 EA
  18. RX: 01 03 04 97 4F C5 21 74 D8
  19. Display: 40365 = -987654321
  20. 4、1439 1 累积流量被乘因子 Integer n:(-4..3), 参见注 1
  21. TX: 01 03 05 9E 00 01 E5 28
  22. RX: 01 03 02 00 03 F8 45
  23. Display: 41439 = 3
  24. *******************************************************************************/
  25. #include "includes.h"
  26. #include "WaterMeter.h"
  27. SUT_METER sutMeter;
  28. /*******************************************************************************
  29. 封装成Modbus命令包
  30. pBuf 至少要有足够8个字节的空间
  31. ********************************************************************************/
  32. int PackagingModbusCmd(unsigned char *pBuf,unsigned char slave,unsigned char Cmd,unsigned short addr,unsigned short len)
  33. {
  34. int i=0;
  35. unsigned short crc;
  36. pBuf[i++]=slave;
  37. pBuf[i++]=Cmd;
  38. pBuf[i++]=(addr>>8)&0xff;
  39. pBuf[i++]=addr&0xff;
  40. pBuf[i++]=(len>>8)&0xff;
  41. pBuf[i++]=len&0xff;
  42. crc=crc16_calc(0xffff,pBuf,i);
  43. pBuf[i++]=crc&0xff;
  44. pBuf[i++]=(crc>>8)&0xff;
  45. return i;
  46. }
  47. /*
  48. 发送读取命令
  49. */
  50. void SendReadCmd(unsigned short addr,unsigned short len)
  51. {
  52. unsigned char txbuf[20];
  53. int l;
  54. l=PackagingModbusCmd(txbuf,METER_SLAVE,METER_READ_CMD,addr-METER_ADDR_BASE,len);
  55. sutMeter.SendCmd=METER_READ_CMD;
  56. sutMeter.SendAddr=addr;
  57. sutMeter.SendTimeCt=0;
  58. Uart1Send((char *)txbuf,l);
  59. }
  60. /*
  61. 解码Modbus协议
  62. 输入:rxbuf/rxlen
  63. 输出:
  64. 返回>0 解码成功,返回有效数据长度,有效数据存放在pData
  65. 返回<0 解码失败
  66. */
  67. int DecodeModbus(unsigned char *rxbuf,unsigned short rxlen,unsigned char *pData,unsigned char DataLenMax)
  68. {
  69. unsigned short len;
  70. unsigned short crc;
  71. if(rxbuf[0]!=METER_SLAVE)return -1;
  72. if(rxbuf[1]!=METER_READ_CMD)return -2;
  73. if(rxbuf[2]!=(rxlen-5))return -3;
  74. if(rxbuf[2]>DataLenMax)return -4;
  75. crc=crc16_calc(0xffff,rxbuf,rxlen-2);
  76. if((crc>>8)!=rxbuf[rxlen-1])return -5;
  77. if((crc&0xff)!=rxbuf[rxlen-2])return -6;
  78. memcpy(pData,&rxbuf[3],rxbuf[2]);
  79. return rxbuf[2];
  80. }
  81. /*
  82. 处理Modebus接收
  83. */
  84. void ModebusRecvHandle(unsigned short addr,unsigned char *pData)
  85. {
  86. char buf[40];
  87. SUTDS ds;
  88. SUTDL dl;
  89. float f;
  90. long TotalFlow1;
  91. static float TotalFlow2=0.0;
  92. switch(addr)
  93. {
  94. case METER_INSTANT_FLOW_ADDR://瞬时流量
  95. dl.Data.ucData.b1=pData[1];
  96. dl.Data.ucData.b2=pData[0];
  97. dl.Data.ucData.b3=pData[3];
  98. dl.Data.ucData.b4=pData[2];
  99. f=*(float *)&dl;
  100. f*=1000.0;
  101. tsk_lock();
  102. sutMeter.InstantFlow=f;
  103. tsk_unlock();
  104. // if(sutDeviceConfig.DebugPrintEn != 0){
  105. // printf("\r\nInstantFlow=%d\r\n",sutMeter.InstantFlow);
  106. // }
  107. break;
  108. case METER_TOTAL_FLOW_ADDR://累计流量 整数部分
  109. dl.Data.ucData.b1=pData[1];
  110. dl.Data.ucData.b2=pData[0];
  111. dl.Data.ucData.b3=pData[3];
  112. dl.Data.ucData.b4=pData[2];
  113. TotalFlow1 =dl.Data.ulData;
  114. TotalFlow1*=1000;
  115. TotalFlow1+=(int)TotalFlow2;
  116. tsk_lock();
  117. sutMeter.TotalFlow=TotalFlow1;
  118. tsk_unlock();
  119. // if(sutDeviceConfig.DebugPrintEn != 0){
  120. // printf("\r\nTotalFlow=%d\r\n",sutMeter.TotalFlow);
  121. // }
  122. break;
  123. case METER_TOTAL_FLOW_F_ADDR://累计流量 小数部分
  124. g_ucUart1Activated=1;
  125. dl.Data.ucData.b1=pData[1];
  126. dl.Data.ucData.b2=pData[0];
  127. dl.Data.ucData.b3=pData[3];
  128. dl.Data.ucData.b4=pData[2];
  129. TotalFlow2=*(float *)&dl;
  130. TotalFlow2*=1000.0;
  131. break;
  132. case METER_TOTAL_FLOW_N_ADDR:
  133. ds.Data.ucData.b1=pData[1];
  134. ds.Data.ucData.b2=pData[0];
  135. tsk_lock();
  136. sutMeter.TotalFlowN=ds.Data.usData;
  137. tsk_unlock();
  138. //printf("\r\nN=%d\r\n",sutMeter.TotalFlowN);
  139. break;
  140. case METER_TEST1_ADDR:
  141. dl.Data.ucData.b1=pData[1];
  142. dl.Data.ucData.b2=pData[0];
  143. dl.Data.ucData.b3=pData[3];
  144. dl.Data.ucData.b4=pData[2];
  145. //printf("\r\nTest1=%02X %02X %02X %02X ",pData[0],pData[1],pData[2],pData[3]);
  146. //f=*(float *)&dl;
  147. //printf("Test1=%f\r\n",f);
  148. break;
  149. case METER_TEST2_ADDR:
  150. dl.Data.ucData.b1=pData[1];
  151. dl.Data.ucData.b2=pData[0];
  152. dl.Data.ucData.b3=pData[3];
  153. dl.Data.ucData.b4=pData[2];
  154. //printf("\r\nTest2=%02X %02X %02X %02X ",pData[0],pData[1],pData[2],pData[3]);
  155. //printf("Test2=%ld\r\n",dl.Data.ulData);
  156. break;
  157. case METER_TEST3_ADDR:
  158. dl.Data.ucData.b1=pData[1];
  159. dl.Data.ucData.b2=pData[0];
  160. dl.Data.ucData.b3=pData[3];
  161. dl.Data.ucData.b4=pData[2];
  162. //printf("\r\nTest3=%02X %02X %02X %02X ",pData[0],pData[1],pData[2],pData[3]);
  163. //printf("Test3=%ld\r\n",dl.Data.ulData);
  164. break;
  165. }
  166. }
  167. /*
  168. *控制定时发送命令给水表,读取瞬时流量、累计流量、累计流量因子
  169. *每个系统tick调用一次
  170. */
  171. void WaterMeterLoop(void)
  172. {
  173. static unsigned char ct=0;
  174. static unsigned char step=0;
  175. unsigned char data[30];
  176. int len;
  177. if(g_ucUARTSel!=COM_SEL_MCU)return;
  178. if(sutMeter.SendTimeCt<0xffff)sutMeter.SendTimeCt++;
  179. if(g_usUart1RecvLen>0){
  180. #if 0
  181. printf("\r\nRx[%d]<< ",g_usUart1RecvLen);
  182. for(len=0;len<g_usUart1RecvLen;len++){
  183. printf("%02X ",ModbusBuf[len]);
  184. }
  185. printf("\r\n");
  186. #endif
  187. len=DecodeModbus(ModbusBuf,g_usUart1RecvLen,data,sizeof(data));
  188. if(len>0){
  189. if(sutMeter.SendTimeCt<METER_READ_TIMEOUT){
  190. ModebusRecvHandle(sutMeter.SendAddr,data);
  191. }else{
  192. //SlwTrace(DEBUG,"DecodeModbus Timeout!\r\n");
  193. }
  194. }else{
  195. sprintf((char *)data,"DecodeModbus err=%d\r\n",len);
  196. SlwTrace(DEBUG,(char *)data);
  197. }
  198. g_usUart1RecvLen=0;
  199. }
  200. //控制每秒调用一次
  201. static U32 os_old_time=0;
  202. U32 os_cur_time=os_time_get();
  203. if((os_cur_time-os_old_time)>100)os_old_time=os_cur_time;
  204. else return;
  205. //控制每轮读取频率
  206. if(++ct>4){// 默认每5秒读一轮
  207. ct=0;
  208. step=3;
  209. }
  210. //每轮分3步,每部间隔1秒
  211. switch(step){
  212. case 3://第一步,读取瞬时值
  213. SendReadCmd(METER_INSTANT_FLOW_ADDR,2);
  214. //SendReadCmd(METER_TEST1_ADDR,2);
  215. step--;
  216. break;
  217. case 2://第二步,读取累计流量
  218. SendReadCmd(METER_TOTAL_FLOW_ADDR,2);
  219. //SendReadCmd(METER_TEST2_ADDR,2);
  220. step--;
  221. break;
  222. case 1://第三步,读取累计流量小数部分
  223. //SendReadCmd(METER_TOTAL_FLOW_N_ADDR,1);
  224. SendReadCmd(METER_TOTAL_FLOW_F_ADDR,2);
  225. //SendReadCmd(METER_TEST3_ADDR,2);
  226. step--;
  227. break;
  228. }
  229. }