/******************************************************************************** * 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;len0){ if(sutMeter.SendTimeCt100)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; } }