quint16 Modbus::generateCLR() { quint16 sum = 0; if(code == 0x10) { sum = usMBCRC16( (UCHAR*) rawData.data(), 6 ); } else if(code == 0x03) { sum = usMBCRC16( (UCHAR*) rawData.data(), 6 ); } return sum; }
quint16 Modbus::calCLR() { quint16 sum = 0; if(code == 0x10) { sum = usMBCRC16( (UCHAR*) rawData.data(), datCount*2+7 ); } else if(code == 0x03) { sum = usMBCRC16( (UCHAR*) rawData.data(), datCount*2+3 ); } return sum; }
eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; ENTER_CRITICAL_SECTION( ); /* Check if the receiver is still in idle state. If not we where to * slow with processing the received frame and the master sent another * frame on the network. We have to abort sending the frame. */ if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usSndBufferCount += usLength; /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); /* Activate the transmitter. */ //发送状态转换,在中断中不断发送 eSndState = STATE_TX_XMIT; //使能发送状态,禁止接收状态 vMBPortSerialEnable( FALSE, TRUE ); }
eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) { BOOL xFrameReceived = FALSE; eMBErrorCode eStatus = MB_ENOERR; ENTER_CRITICAL_SECTION(); assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ); /* Length and CRC check */ if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) ) { /* Save the address field. All frames are passed to the upper layed * and the decision if a frame is used is done there. */ *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF]; /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus * size of address field and CRC checksum. */ *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); /* Return the start of the Modbus PDU to the caller. */ *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF]; xFrameReceived = TRUE; } else { eStatus = MB_EIO; } EXIT_CRITICAL_SECTION(); return eStatus; }
/************************************************************************* * eMBMasterRTUSend * отправка пакета в MODBUS *************************************************************************/ eMBErrorCode eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL; ENTER_CRITICAL_SECTION( ); // Если приемник в режиме ожидания. if( eRcvState == STATE_M_RX_IDLE ) { // Первый байт до PDU это slave address. pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1; usMasterSndBufferCount = 1; // Добавляем к пакету SlaveAddress pucMasterSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usMasterSndBufferCount += usLength; // считаем CRC16 usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ); ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); // Режим предачи. eSndState = STATE_M_TX_XMIT; xMBMasterPortSerialPutBUF(( CHAR *)pucMasterSndBufferCur,usMasterSndBufferCount); // передадим в порт весь блок сразу xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; // определяем широковещательный ли ? }
/************************************************************************* * eMBMasterRTUReceive * Функция приёма данных и проверка их целосности. *************************************************************************/ eMBErrorCode eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) { eMBErrorCode eStatus = MB_ENOERR; ENTER_CRITICAL_SECTION( ); assert_param( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ); // Проверка длинны пакета и его CRC if( ( usMasterRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) && ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) ) { // Save the address field. All frames are passed to the upper layed and the decision if a frame is used is done there. *pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF]; // Общая длина данных(Modbus-PDU) без поля адреса и CRC. *pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); // Адрес начала данных(Modbus-PDU) *pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF]; } else { eStatus = MB_EIO; } EXIT_CRITICAL_SECTION( ); return eStatus; }
/** * Send a ModBus frame. * @param ucSlaveAddress - Slave address to send to * @param pucFrame - Pointer to frame * @param usLength - Frame length * @return */ eMBErrorCode eMBRTUSend(UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; //printf ("Sending addr=%d cmd=%d len=%d\n", ucSlaveAddress, pucFrame[0], usLength); //printf ("rxstate = %d txstate = %d\n",eRcvState, eSndState); ENTER_CRITICAL_SECTION( ); /* Check if the receiver is still in idle state. If not, some slave * sent an unsolicited or late frame on the network. We have to abort * sending the frame. */ if(( eRcvState == STATE_RX_IDLE ) && ( eSndState == STATE_TX_IDLE )) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usSndBufferCount += usLength; /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); //printf ("CRC=%04x\n", usCRC16); pucSndBufferCur[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); pucSndBufferCur[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); /* Activate the transmitter. */ eSndState = STATE_TX_XMIT; vMBPortSerialEnable( FALSE, TRUE ); }
/** ----------------------------------------------------------------------------------------------------------------------- eMBRTUSend ----------------------------------------------------------------------------------------------------------------------- * Send RTU Frame * * @date DEC/02/2013 * @author FW_DEV_2 * @pre None * @return None ************************************************************************************************************************ */ eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; int i =0; ENTER_CRITICAL_SECTION( ); printf("Inside eMBRTUSend\n"); /*for(i=0;i<usLength;i++) { printf("Sending data is %x\n",*pucFrame++); }*/ /* Check if the receiver is still in idle state. If not we where to * slow with processing the received frame and the master sent another * frame on the network. We have to abort sending the frame. */ if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; //printf("pucSndBufferCur data is %x\n",*pucSndBufferCur); usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ //pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; //pucSndBufferCur[MB_SER_PDU_PDU_OFF] = pucFrame[0]; //pucSndBufferCur[MB_SER_PDU_PDU_OFF+1] = pucFrame[1]; //pucSndBufferCur[MB_SER_PDU_PDU_OFF+2] = pucFrame[2]; usSndBufferCount += (usLength); /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); //ucRTUBuf[usSndBufferCount] = '\0'; //usSndBufferCount = 8; //printf("Buffer count is %d\n",usSndBufferCount); /* Activate the transmitter. */ eSndState = STATE_TX_XMIT; //vMBPortSerialEnable( FALSE, TRUE ); vMBPortSerialEnable( FALSE, FALSE ); xMBRTUTransmitFSM(); }
void holding_deal(UCHAR *point_RX)//point_rx带校验码 { USHORT addr0 = 0,count0 = 0; USHORT i = 0,CRC = 0; UCHAR HIGH = 0,LOW = 0; UCHAR NUM=0; // addr0 = point_RX[2]; // addr0 = addr0<<8+point_RX[3]; // count0 = point_RX[4]; //寄存器数 // count0 = count0<<8+point_RX[5]; // count0 = count0*2; //字节数 //for(i=0;i<8;i++) //{ // send(point_RX[i]); //} if(read_hold == point_RX[1]) { holding[0] = point_RX[0]; holding[1] = point_RX[1]; holding[2] = count0; NUM=sizeof(save1); for(i=0;i<NUM;i++) { holding[i+3] = read_random(area1+point_RX[3]*NUM+i); } // for(i=0;i<15;i++) // holding[i+3] = i+1; // for(i=9;i<56;i++) // { // holding[2*i] = 0; // holding[2*i+1] = 1+i; // } CRC = usMBCRC16(holding,sizeof(save1)+3); HIGH = CRC>>8; LOW = CRC; for(i=0;i<NUM+3;i++) { send(holding[i]); } send(LOW); send(HIGH); // tx_count = count0 + 3; }
int8u ModbusSendDataSerial(void) { int16u i; int16u crc; g_modbusSendBufSerial[0] = modbusTerminalID; g_modbusSendBufNumberSerial++; crc = usMBCRC16(g_modbusSendBufSerial, g_modbusSendBufNumberSerial); for(i = 0; i < g_modbusSendBufNumberSerial; i++) { QueueWrite((void *)UART1SendBuf, g_modbusSendBufSerial[i]); } QueueWrite((void *)UART1SendBuf, crc & 0xff); QueueWrite((void *)UART1SendBuf, crc >> 8); return MODBUS_OK; }
int8u ModbusReportErrorSerial(int data) { uint8_t reportData[5]; uint16_t crc; uint8_t i; reportData[0] = modbusTerminalID; reportData[1] = 0x80 + data; reportData[2] = 0x01; crc = usMBCRC16(reportData, 3); reportData[4] = crc >> 8; reportData[3] = crc & 0xff; for (i = 0; i < 5; i++) QueueWrite((void *)UART1SendBuf, reportData[i]); return MODBUS_OK; }
uint8_t ModbusInput(uint8_t *pIn, uint32_t inSize, uint8_t * g_modbusReceiveBuf, uint8_t * g_modbusSendBuf, int16u* g_modbusReceiveBufNumber, uint16_t * g_modbusSendBufNumber, uint8_t type, uint16_t * longth, uint16_t * address) { uint16_t i = 0; uint16_t receiveSize = 0; uint8_t tempbuf[4] = {0}; while (receiveSize < inSize) { if (*g_modbusReceiveBufNumber >= MODBUS_BUFFER_SIZE) InitModbus(type); g_modbusReceiveBuf[*g_modbusReceiveBufNumber] = *((pIn) + receiveSize); (*g_modbusReceiveBufNumber)++; receiveSize++; if (g_modbusReceiveBuf[0] == 0x03) {//read if (*g_modbusReceiveBufNumber > 4) { *address = g_modbusReceiveBuf[2] + ((uint16_t)(g_modbusReceiveBuf[1]) << 8); *longth = g_modbusReceiveBuf[4] + ((uint16_t)(g_modbusReceiveBuf[3]) << 8); if (type == 1) { if (*g_modbusReceiveBufNumber > 6) { if (usMBCRC16(&g_modbusReceiveBuf[0] - 1, 8)) { InitModbus(type); ModbusReportError(0x3, type); continue; } } else continue; } if ((((*address + *longth) << 1) > MODBUS_REG4_SIZE) || (*longth > 125)) { InitModbus(type); ModbusReportError(0x3, type); } else { if (type == 1) { g_modbusSendBuf++; } g_modbusSendBuf[0] = 0x03; g_modbusSendBuf[1] = *longth << 1; memcpy(g_modbusSendBuf+2, g_modbusReg4+(*address << 1), (*longth << 1)); tempbuf[0] = g_modbusSendBuf[2]; tempbuf[1] = g_modbusSendBuf[3]; tempbuf[2] = g_modbusSendBuf[4]; tempbuf[3] = g_modbusSendBuf[5]; g_modbusSendBuf[2] = tempbuf[1]; g_modbusSendBuf[3] = tempbuf[0]; g_modbusSendBuf[4] = tempbuf[3]; g_modbusSendBuf[5] = tempbuf[2]; *g_modbusSendBufNumber = (*longth << 1) + 2; // ModbusSendData(type); TcpSendData(g_modbusSendBuf, *g_modbusSendBufNumber); // InitModbus(type); InitModbusTcp(); } } continue; } // 最多接收5个 if (g_modbusReceiveBuf[0] == 0x06) {//write single if (*g_modbusReceiveBufNumber > 4) { if (type == 1) { if (*g_modbusReceiveBufNumber > 6) { if (usMBCRC16(g_modbusReceiveBuf - 1, 8)) { InitModbus(type); ModbusReportError(0x6, type); continue; } } else continue; } *address = g_modbusReceiveBuf[2] + ((int16u)(g_modbusReceiveBuf[1]) << 8); if ((*address << 1) >= MODBUS_REG4_SIZE) { InitModbus(type); ModbusReportError(0x6, type); } else { if (type == 1) { g_modbusSendBuf++; } // 更新寄存器数据,MODBUS 寄存器显示的是高位在后 需要逆转一下 g_modbusReg4[((*address) << 1)] = g_modbusReceiveBuf[4]; g_modbusReg4[((*address) << 1) + 1] = g_modbusReceiveBuf[3]; TcpSendData(g_modbusReceiveBuf, 5); // InitModbus(type); InitModbusTcp(); } } continue; } // 写多个寄存器 if (g_modbusReceiveBuf[0] == 0x10) {//write mul if (*g_modbusReceiveBufNumber > 4 && *longth == 0) { *address = g_modbusReceiveBuf[2] + ((int16u)(g_modbusReceiveBuf[1]) << 8); *longth = g_modbusReceiveBuf[4] + ((int16u)(g_modbusReceiveBuf[3]) << 8); if (((*address + *longth) << 1) > MODBUS_REG4_SIZE || *longth > 0x7d) { InitModbus(type); ModbusReportError(0x10, type); } } else { if (*g_modbusReceiveBufNumber >= ((*longth << 1) + 6)) { if (type == 1) { if (*g_modbusReceiveBufNumber >= ((*longth << 1) + 8)) { if (usMBCRC16(g_modbusReceiveBuf - 1, *g_modbusReceiveBufNumber + 3)) { InitModbus(type); ModbusReportError(0x10, type); continue; } } else continue; } tempbuf[0] = g_modbusReceiveBuf[6]; tempbuf[1] = g_modbusReceiveBuf[7]; tempbuf[2] = g_modbusReceiveBuf[8]; tempbuf[3] = g_modbusReceiveBuf[9]; g_modbusReceiveBuf[7] = tempbuf[0]; g_modbusReceiveBuf[6] = tempbuf[1]; g_modbusReceiveBuf[9] = tempbuf[2]; g_modbusReceiveBuf[8] = tempbuf[3]; for(i = 0; i < (*longth << 1); i++) { g_modbusReg4[(*address << 1) + i] = g_modbusReceiveBuf[6 + i]; } if (type == 1) g_modbusSendBuf++; TcpSendData(g_modbusReceiveBuf, 5); InitModbusTcp(); // InitModbus(type); } } continue; } // 扩展指令 if (g_modbusReceiveBuf[0] == 0x41) { if (*g_modbusReceiveBufNumber > 4) { *address = g_modbusReceiveBuf[2] + ((int16u)(g_modbusReceiveBuf[1]) << 8); *longth = g_modbusReceiveBuf[4] + ((int16u)(g_modbusReceiveBuf[3]) << 8); //sprintf(tempbuf, "%d %d %d %d\r\n", address, longth, ((int16u)(g_modbusReceiveBuf[1]) << 8), ((int16u)(g_modbusReceiveBuf[3]) << 8)); //DebugLog(tempbuf); if (((*address + *longth) << 1) > MODBUS_REG5_SIZE || *longth > 0x7d) { InitModbus(type); ModbusReportError(0x41, type); } else { if (type == 1) { g_modbusSendBuf++; } g_modbusSendBuf[0] = 0x41; g_modbusSendBuf[1] = *longth << 1; for(i = 0; i < (*longth << 1); i++) { g_modbusSendBuf[i + 2] = g_modbusReg5[(*address << 1) + i]; } *g_modbusSendBufNumber = (*longth << 1) + 2; ModbusSendData(type); InitModbus(type); } } continue; } if (g_modbusReceiveBuf[0] == 0x42) { if (*g_modbusReceiveBufNumber > 4 && *longth == 0) { *address = g_modbusReceiveBuf[2] + ((int16u)(g_modbusReceiveBuf[1]) << 8); *longth = g_modbusReceiveBuf[4] + ((int16u)(g_modbusReceiveBuf[3]) << 8); if (((*address + *longth) << 1) > MODBUS_REG5_SIZE || *longth > 0x7d) { InitModbus(type); ModbusReportError(0x42, type); } } else if (*g_modbusReceiveBufNumber == ((*longth << 1) + 6)) { for(i = 0; i < (*longth << 1); i++) { g_modbusReg5[(*address << 1) + i] = g_modbusReceiveBuf[6 + i]; } if (type == 1) { g_modbusSendBuf++; } g_modbusSendBuf[0] = 0x42; g_modbusSendBuf[1] = g_modbusReceiveBuf[1]; g_modbusSendBuf[2] = g_modbusReceiveBuf[2]; g_modbusSendBuf[3] = g_modbusReceiveBuf[3]; g_modbusSendBuf[4] = g_modbusReceiveBuf[4]; *g_modbusSendBufNumber = 5; ModbusSendData(type); InitModbus(type); } continue; } if (g_modbusReceiveBuf[0] == 0x43) { if (*g_modbusReceiveBufNumber > 4) { *address = g_modbusReceiveBuf[2] + ((int16u)(g_modbusReceiveBuf[1]) << 8); *longth = g_modbusReceiveBuf[4] + ((int16u)(g_modbusReceiveBuf[3]) << 8); if (((*address + *longth) << 1) > MODBUS_REG6_SIZE || *longth > 0x7d) { InitModbus(type); ModbusReportError(0x43, type); } else { if (type == 1) { g_modbusSendBuf++; } g_modbusSendBuf[0] = 0x43; g_modbusSendBuf[1] = *longth << 1; for(i = 0; i < (*longth << 1); i++) { g_modbusSendBuf[i + 2] = g_modbusReg6[(*address << 1) + i]; } *g_modbusSendBufNumber = (*longth << 1) + 2; ModbusSendData(type); InitModbus(type); } } continue; } if (g_modbusReceiveBuf[0] == 0x44) { if (*g_modbusReceiveBufNumber > 4 && *longth == 0) { *address = g_modbusReceiveBuf[2] + ((int16u)(g_modbusReceiveBuf[1]) << 8); *longth = g_modbusReceiveBuf[4] + ((int16u)(g_modbusReceiveBuf[3]) << 8); if (((*address + *longth) << 1) > MODBUS_REG6_SIZE || *longth > 0x7d) { InitModbus(type); ModbusReportError(0x44, type); } } else if (*g_modbusReceiveBufNumber == ((*longth << 1) + 6)) { for(i = 0; i < (*longth << 1); i++) { g_modbusReg6[(*address << 1) + i] = g_modbusReceiveBuf[6 + i]; } if (type == 1) { g_modbusSendBuf++; } g_modbusSendBuf[0] = 0x44; g_modbusSendBuf[1] = g_modbusReceiveBuf[1]; g_modbusSendBuf[2] = g_modbusReceiveBuf[2]; g_modbusSendBuf[3] = g_modbusReceiveBuf[3]; g_modbusSendBuf[4] = g_modbusReceiveBuf[4]; *g_modbusSendBufNumber = 5; ModbusSendData(type); InitModbus(type); } continue; } ModbusReportError(g_modbusReceiveBuf[0], type); InitModbus(type); continue; } return MODBUS_OK; }