//===================================== //modbus 命令发送 //===================================== void SendModbusCmd(void) { unsigned int regaddr; unsigned char devaddr; int uartchannel; unsigned char modbus_bag[22]; unsigned short crc; unsigned char len; uartchannel = MODBUS_COM; devaddr = Com_Param.mb_var[MBCurrentDev].devid; regaddr = Com_Param.mb_var[MBCurrentDev].regaddr - 1; //设备地值 modbus_bag[0] = devaddr; //命令号 modbus_bag[1] = 0x03; //modbus起始地址 //高位地址 modbus_bag[2] = (regaddr & 0xFF00) >> 8; //低位地址 modbus_bag[3] = regaddr & 0x00FF; //字节个数 if (Com_Param.mb_var[MBCurrentDev].type == 0) { modbus_bag[4] = 0x00; modbus_bag[5] = 0x01; MBRcvDataLen = 7; } else { modbus_bag[4] = 0x00; modbus_bag[5] = 0x02; MBRcvDataLen = 9; } //数据段校验码 crc = CRC16_Modbus(modbus_bag, 6); modbus_bag[6] = (crc & 0xFF00) >> 8; //高字节 modbus_bag[7] = crc & 0x00FF; //低字节 len = 8; //发送协议包 Uart_ClearRcvBuf(uartchannel); Uart_SendData(modbus_bag, len, uartchannel); MbOtCnt = 0; MBRcved = 0; }
//===================================== //modbus 命令应答解析函数, 返回-1表示数据错误,0表示数据已正确处理 //===================================== int AnalystModbusRsp(void) { unsigned char devaddr; unsigned short crc, crc2; INT32U d1, d2; INT32U data; union { unsigned char byte[4]; float data; } pfdata; devaddr = Com_Param.mb_var[MBCurrentDev].devid; if (MBRcvDataBuf[0] != devaddr) return -1; if (MBRcvDataBuf[1] != 0x03) return -1; crc = CRC16_Modbus(MBRcvDataBuf, 3 + MBRcvDataBuf[2]); crc2 = (MBRcvDataBuf[MBRcvDataLen - 2] << 8) + MBRcvDataBuf[MBRcvDataLen - 1]; if (crc != crc2) return -1; if (Com_Param.mb_var[MBCurrentDev].type == INTEGER) { if (MBRcvDataBuf[2] != 0x02) { return -1; } d1 = MBRcvDataBuf[3]; d2 = MBRcvDataBuf[4]; INT16U val = (d1 << 8) + d2; if (val > Com_Param.mb_var[MBCurrentDev].ulv) { Com_Val[MBCurrentDev] = Com_Param.mb_var[MBCurrentDev].ulv; } else if (val < Com_Param.mb_var[MBCurrentDev].llv) { Com_Val[MBCurrentDev] = Com_Param.mb_var[MBCurrentDev].llv; } else { Com_Val[MBCurrentDev] = val; } } else { if (MBRcvDataBuf[2] != 0x04) { return -1; } pfdata.byte[0] = MBRcvDataBuf[4]; pfdata.byte[1] = MBRcvDataBuf[3]; pfdata.byte[2] = MBRcvDataBuf[6]; pfdata.byte[3] = MBRcvDataBuf[5]; float val_upper = Com_Param.mb_var[MBCurrentDev].ulv; float val_lower = Com_Param.mb_var[MBCurrentDev].llv; if (pfdata.data > val_upper) { Com_Val[MBCurrentDev] = val_upper; } else if (pfdata.data < val_lower) { Com_Val[MBCurrentDev] = val_lower; } else { Com_Val[MBCurrentDev] = pfdata.data; } } Com_Err[MBCurrentDev] = 0; return 0; }
//写数据 bool CTemperHumiCtrl::WriteData(const char *pbuf, const int len, const uint8 timeout) { static uint8 send_buf[1024] = {0}; // 存储待发送的十六进制命令 static char temp_buf[1024] = {0}; // 临时存放去除空格的命令字符串 int left_len = 0; // 待发送的命令长度 int nfds = 0; // 可写句柄数量 fd_set write_fds; // 句柄集合 struct timeval tv; // select 等待时间 if (len > sizeof(send_buf)) { MainApp.m_log.WriteLog("%s:%d 发送命令的长度必须小于 1024", __FILE__, __LINE__); return -1; } memset(temp_buf, 0x00, sizeof(temp_buf)); int temp_len = TrimSpace(temp_buf, pbuf, len); if (temp_len % 2 != 0) { MainApp.m_log.WriteLog("%s:%d 命令的长度必须是2的整数倍", __FILE__, __LINE__); return false;; } //fprintf(stdout, "len=%d, cmd=%s\n", temp_len, temp_buf); memset(send_buf, 0x00, sizeof(send_buf)); StrToHex(send_buf, temp_buf, temp_len); uint8 CRC[2]; memset(CRC, 0, sizeof(CRC)); CRC16_Modbus(send_buf, (uint16)(temp_len/2), CRC); //fprintf(stdout, "CRC[0]=%02X, CRC[1]=%02X\n", CRC[0], CRC[1]); // 待发送缓冲区加上两个字节的CRC码 send_buf[temp_len/2] = CRC[0]; send_buf[temp_len/2 + 1] = CRC[1]; left_len = temp_len/2 + 2; uint8 *p = send_buf; while (left_len > 0) { tv.tv_sec = 0; tv.tv_usec = 500000; FD_ZERO(&write_fds); FD_SET(m_fd, &write_fds); nfds = select(m_fd + 1, NULL, &write_fds, NULL, &tv); if (nfds < 0) { break; } else if(0 == nfds) { //printf("no fd use write!\n"); break; } int nwrite = write(m_fd, p, left_len); if (nwrite > 0) { left_len -= nwrite; p += nwrite; } else { break; } } if (left_len != 0) { return false; } return true; }