智能电磁流量计MODBUS通讯 C语言应用举例 (1).智能电磁流量计CRC16算法: INT16U CRC16(INT8U *puchMsg, INT16U usDataLen) { INT8U uchCRCHi = 0xFF; /* 高CRC字节初始化 */ INT8U uchCRCLo = 0xFF; /* 低CRC 字节初始化 */ INT8U uIndex; /* CRC循环中的索引 */ while (usDataLen--) /* 传输消息缓冲区 */ { uIndex = uchCRCHi ^ *puchMsg++; /* 计算CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; uchCRCLo = auchCRCLo[uIndex]; } return (uchCRCHi << 8 | uchCRCLo); } (2)智能电磁流量计发送命令程序 本例程以智能电磁流量计Mag64为核心CPU void Read_InPut(INT8U Addr,INT16U Start,INT16U Len) { INT16U CRC; SendBuffer_485[0]=Addr; //设备地址 SendBuffer_485[1]=0x04; //modbus功能码 SendBuffer_485[2]=Start/256; //Start为寄存器地址 SendBuffer_485[3]=Start%256; SendBuffer_485[4]=Len/256; //Len为读取寄存器长度 SendBuffer_485[5]=Len%256; CRC=CRC16(SendBuffer_485,6); SendBuffer_485[6]=CRC/256; //CRC校验高位 SendBuffer_485[7]=CRC%256; //CRC校验低位 R485_OUT; //使能RS485发送 SendLen_485=8; SendNum_485=0; CloseINT0(); //关闭串口接受中断 UCSR0B |= BIT(UDRIE0); //打开串口发送中断 } (3)智能电磁流量计返回数据解析(只以瞬时流量为例) 智能电磁流量计数据接收使用串口中断,ReceivedBuffer_485为接收数据组,ReceivedNum_485为接收到数据长度,ReceivedFlag_485接收到数据标志。函数float Datasum(INT8U BYTE1, INT8U BYTE2, INT8U BYTE3, INT8U BYTE4)把浮点数的4个字节转换为1个浮点数。 float Datasum(INT8U FloatByte1, INT8U FloatByte2, INT8U FloatByte3, INT8U FloatByte4) { float aa; union IntTOFP { FP INT8U T8[4]; }; union IntTOFP aa; aa.T8[0] = FloatByte1; aa.T8[1] = FloatByte2; aa.T8[2] = FloatByte3; aa.T8[3] = FloatByte4; return aa; } void Read_Lmag(INT8U Ad) { INT8U i,j; INT8U Num1[10],BIT; INT16U CRC1,CRC2; FP32 Flow; //aaa为瞬时流量数值 ReceivedFlag_485=1; Open_Time1_Ms5(20); Read_InPut(Ad,0x1010,2); //发送设备地址、寄存器地址、寄存器长度 while(ReceivedFlag_485); //等待接收结束 if((ReceivedNum_485==9)&&(ReceivedBuffer_485[0]==Ad)) // 判断数据是否正确 { CRC1=CRC16(ReceivedBuffer_485,7); CRC2=ReceivedBuffer_485[7]*256+ReceivedBuffer_485[8]; if(CRC1==CRC2) {// 转换数据为浮点数 Flow = Datasum(ReceivedBuffer_485[6], ReceivedBuffer_485[5], ReceivedBuffer_485[4] ,ReceivedBuffer_485[3]); } } } (责任编辑:admin) |