123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /********************************************************************************
- * File Name: WaterMeter.c
- * Function Describe: 水表数据接口
- 采用RS485通讯,基于Mobus协议
- * Explain:
- * Writer: ShiLiangWen
- * Date: 2019-2-14
-
- 1、0361-0362 2 总是读出 361.00 参见注 2 IEEE754
- TX: 01 03 01 68 00 02 44 2B
- RX: 01 03 04 80 00 43 B4 E2 B4
- Display: 40361 = 361.000000
- 2、0363-0364 2 总是读出 363348858 long
- TX:01 03 01 6A 00 02 E5 EB
- RX:01 03 04 43 7A 15 A8 C1 40
- Display: 40363 = 363348858
- 3、0365-0366 2 总是读出 -987654321 long
- TX: 01 03 01 6C 00 02 05 EA
- RX: 01 03 04 97 4F C5 21 74 D8
- Display: 40365 = -987654321
- 4、1439 1 累积流量被乘因子 Integer n:(-4..3), 参见注 1
- TX: 01 03 05 9E 00 01 E5 28
- RX: 01 03 02 00 03 F8 45
- Display: 41439 = 3
- *******************************************************************************/
- #include "includes.h"
- #include "WaterMeter.h"
- SUT_METER sutMeter;
- /*******************************************************************************
- 封装成Modbus命令包
- pBuf 至少要有足够8个字节的空间
- ********************************************************************************/
- int PackagingModbusCmd(unsigned char *pBuf,unsigned char slave,unsigned char Cmd,unsigned short addr,unsigned short len)
- {
- int i=0;
- unsigned short crc;
- pBuf[i++]=slave;
- pBuf[i++]=Cmd;
- pBuf[i++]=(addr>>8)&0xff;
- pBuf[i++]=addr&0xff;
- pBuf[i++]=(len>>8)&0xff;
- pBuf[i++]=len&0xff;
- crc=crc16_calc(0xffff,pBuf,i);
- pBuf[i++]=crc&0xff;
- pBuf[i++]=(crc>>8)&0xff;
- return i;
- }
- /*
- 发送读取命令
- */
- void SendReadCmd(unsigned short addr,unsigned short len)
- {
- unsigned char txbuf[20];
- int l;
- l=PackagingModbusCmd(txbuf,METER_SLAVE,METER_READ_CMD,addr-METER_ADDR_BASE,len);
- sutMeter.SendCmd=METER_READ_CMD;
- sutMeter.SendAddr=addr;
- sutMeter.SendTimeCt=0;
- Uart1Send((char *)txbuf,l);
- }
- /*
- 解码Modbus协议
- 输入:rxbuf/rxlen
- 输出:
- 返回>0 解码成功,返回有效数据长度,有效数据存放在pData
- 返回<0 解码失败
- */
- int DecodeModbus(unsigned char *rxbuf,unsigned short rxlen,unsigned char *pData,unsigned char DataLenMax)
- {
- unsigned short len;
- unsigned short crc;
- if(rxbuf[0]!=METER_SLAVE)return -1;
- if(rxbuf[1]!=METER_READ_CMD)return -2;
- if(rxbuf[2]!=(rxlen-5))return -3;
- if(rxbuf[2]>DataLenMax)return -4;
- crc=crc16_calc(0xffff,rxbuf,rxlen-2);
- if((crc>>8)!=rxbuf[rxlen-1])return -5;
- if((crc&0xff)!=rxbuf[rxlen-2])return -6;
- memcpy(pData,&rxbuf[3],rxbuf[2]);
- return rxbuf[2];
- }
- /*
- 处理Modebus接收
- */
- void ModebusRecvHandle(unsigned short addr,unsigned char *pData)
- {
- char buf[40];
- SUTDS ds;
- SUTDL dl;
- float f;
- long TotalFlow1;
- static float TotalFlow2=0.0;
- switch(addr)
- {
- case METER_INSTANT_FLOW_ADDR://瞬时流量
- dl.Data.ucData.b1=pData[1];
- dl.Data.ucData.b2=pData[0];
- dl.Data.ucData.b3=pData[3];
- dl.Data.ucData.b4=pData[2];
- f=*(float *)&dl;
- f*=1000.0;
- tsk_lock();
- sutMeter.InstantFlow=f;
- tsk_unlock();
- // if(sutDeviceConfig.DebugPrintEn != 0){
- // printf("\r\nInstantFlow=%d\r\n",sutMeter.InstantFlow);
- // }
- break;
- case METER_TOTAL_FLOW_ADDR://累计流量 整数部分
- dl.Data.ucData.b1=pData[1];
- dl.Data.ucData.b2=pData[0];
- dl.Data.ucData.b3=pData[3];
- dl.Data.ucData.b4=pData[2];
- TotalFlow1 =dl.Data.ulData;
- TotalFlow1*=1000;
- TotalFlow1+=(int)TotalFlow2;
- tsk_lock();
- sutMeter.TotalFlow=TotalFlow1;
- tsk_unlock();
- // if(sutDeviceConfig.DebugPrintEn != 0){
- // printf("\r\nTotalFlow=%d\r\n",sutMeter.TotalFlow);
- // }
- break;
- case METER_TOTAL_FLOW_F_ADDR://累计流量 小数部分
- g_ucUart1Activated=1;
- dl.Data.ucData.b1=pData[1];
- dl.Data.ucData.b2=pData[0];
- dl.Data.ucData.b3=pData[3];
- dl.Data.ucData.b4=pData[2];
- TotalFlow2=*(float *)&dl;
- TotalFlow2*=1000.0;
- break;
- case METER_TOTAL_FLOW_N_ADDR:
- ds.Data.ucData.b1=pData[1];
- ds.Data.ucData.b2=pData[0];
- tsk_lock();
- sutMeter.TotalFlowN=ds.Data.usData;
- tsk_unlock();
- //printf("\r\nN=%d\r\n",sutMeter.TotalFlowN);
- break;
- case METER_TEST1_ADDR:
- dl.Data.ucData.b1=pData[1];
- dl.Data.ucData.b2=pData[0];
- dl.Data.ucData.b3=pData[3];
- dl.Data.ucData.b4=pData[2];
- //printf("\r\nTest1=%02X %02X %02X %02X ",pData[0],pData[1],pData[2],pData[3]);
- //f=*(float *)&dl;
- //printf("Test1=%f\r\n",f);
- break;
- case METER_TEST2_ADDR:
- dl.Data.ucData.b1=pData[1];
- dl.Data.ucData.b2=pData[0];
- dl.Data.ucData.b3=pData[3];
- dl.Data.ucData.b4=pData[2];
- //printf("\r\nTest2=%02X %02X %02X %02X ",pData[0],pData[1],pData[2],pData[3]);
- //printf("Test2=%ld\r\n",dl.Data.ulData);
- break;
- case METER_TEST3_ADDR:
- dl.Data.ucData.b1=pData[1];
- dl.Data.ucData.b2=pData[0];
- dl.Data.ucData.b3=pData[3];
- dl.Data.ucData.b4=pData[2];
- //printf("\r\nTest3=%02X %02X %02X %02X ",pData[0],pData[1],pData[2],pData[3]);
- //printf("Test3=%ld\r\n",dl.Data.ulData);
- break;
- }
- }
- /*
- *控制定时发送命令给水表,读取瞬时流量、累计流量、累计流量因子
- *每个系统tick调用一次
- */
- void WaterMeterLoop(void)
- {
- static unsigned char ct=0;
- static unsigned char step=0;
- unsigned char data[30];
- int len;
- if(g_ucUARTSel!=COM_SEL_MCU)return;
- if(sutMeter.SendTimeCt<0xffff)sutMeter.SendTimeCt++;
- if(g_usUart1RecvLen>0){
- #if 0
- printf("\r\nRx[%d]<< ",g_usUart1RecvLen);
- for(len=0;len<g_usUart1RecvLen;len++){
- printf("%02X ",ModbusBuf[len]);
- }
- printf("\r\n");
- #endif
- len=DecodeModbus(ModbusBuf,g_usUart1RecvLen,data,sizeof(data));
- if(len>0){
- if(sutMeter.SendTimeCt<METER_READ_TIMEOUT){
- ModebusRecvHandle(sutMeter.SendAddr,data);
- }else{
- //SlwTrace(DEBUG,"DecodeModbus Timeout!\r\n");
- }
- }else{
- sprintf((char *)data,"DecodeModbus err=%d\r\n",len);
- SlwTrace(DEBUG,(char *)data);
- }
- g_usUart1RecvLen=0;
- }
-
- //控制每秒调用一次
- static U32 os_old_time=0;
- U32 os_cur_time=os_time_get();
- if((os_cur_time-os_old_time)>100)os_old_time=os_cur_time;
- else return;
- //控制每轮读取频率
- if(++ct>4){// 默认每5秒读一轮
- ct=0;
- step=3;
- }
- //每轮分3步,每部间隔1秒
- switch(step){
- case 3://第一步,读取瞬时值
- SendReadCmd(METER_INSTANT_FLOW_ADDR,2);
- //SendReadCmd(METER_TEST1_ADDR,2);
- step--;
- break;
- case 2://第二步,读取累计流量
- SendReadCmd(METER_TOTAL_FLOW_ADDR,2);
- //SendReadCmd(METER_TEST2_ADDR,2);
- step--;
- break;
- case 1://第三步,读取累计流量小数部分
- //SendReadCmd(METER_TOTAL_FLOW_N_ADDR,1);
- SendReadCmd(METER_TOTAL_FLOW_F_ADDR,2);
- //SendReadCmd(METER_TEST3_ADDR,2);
- step--;
- break;
- }
- }
|