📄 dlmstp.c
字号:
if (reply_pdu[offset] & BIT3)
reply.service_choice = reply_pdu[offset + 5];
else
reply.service_choice = reply_pdu[offset + 3];
break;
case PDU_TYPE_SIMPLE_ACK:
reply.invoke_id = reply_pdu[offset + 1];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_COMPLEX_ACK:
reply.invoke_id = reply_pdu[offset + 1];
/* segmented message? */
if (reply_pdu[offset] & BIT3)
reply.service_choice = reply_pdu[offset + 4];
else
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_ERROR:
reply.invoke_id = reply_pdu[offset + 1];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_REJECT:
case PDU_TYPE_ABORT:
reply.invoke_id = reply_pdu[offset + 1];
break;
default:
return false;
}
if (request.invoke_id != reply.invoke_id) {
return false;
}
/* these services don't have service choice included */
if ((reply.pdu_type != PDU_TYPE_REJECT) &&
(reply.pdu_type != PDU_TYPE_ABORT)) {
if (request.service_choice != reply.service_choice) {
return false;
}
}
if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
return false;
}
if (request.npdu_data.priority != reply.npdu_data.priority) {
return false;
}
if (!bacnet_address_same(&request.address, &reply.address)) {
return false;
}
return true;
}
/* MS/TP Frame Format */
/* All frames are of the following format: */
/* */
/* Preamble: two octet preamble: X`55', X`FF' */
/* Frame Type: one octet */
/* Destination Address: one octet address */
/* Source Address: one octet address */
/* Length: two octets, most significant octet first, of the Data field */
/* Header CRC: one octet */
/* Data: (present only if Length is non-zero) */
/* Data CRC: (present only if Length is non-zero) two octets, */
/* least significant octet first */
/* (pad): (optional) at most one octet of padding: X'FF' */
static void MSTP_Send_Frame(
uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */
uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */
uint16_t data_len)
{ /* number of bytes of data (up to 501) */
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
uint8_t buffer[8]; /* stores the header and data crc */
uint16_t i = 0; /* used to calculate CRC for data */
/* create the MS/TP header */
buffer[0] = 0x55;
buffer[1] = 0xFF;
buffer[2] = frame_type;
crc8 = CRC_Calc_Header(buffer[2], crc8);
buffer[3] = destination;
crc8 = CRC_Calc_Header(buffer[3], crc8);
buffer[4] = source;
crc8 = CRC_Calc_Header(buffer[4], crc8);
buffer[5] = data_len / 256;
crc8 = CRC_Calc_Header(buffer[5], crc8);
buffer[6] = data_len % 256;
crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8;
RS485_Turnaround_Delay();
RS485_Transmitter_Enable(true);
RS485_Send_Data(buffer, 8);
/* send any data */
if (data_len) {
/* calculate CRC for any data */
for (i = 0; i < data_len; i++) {
crc16 = CRC_Calc_Data(data[i], crc16);
}
crc16 = ~crc16;
buffer[0] = (crc16 & 0x00FF);
buffer[1] = ((crc16 & 0xFF00) >> 8);
RS485_Send_Data(data, data_len);
RS485_Send_Data(buffer, 2);
}
RS485_Transmitter_Enable(false);
}
static void MSTP_Receive_Frame_FSM(
void)
{
/* stores the latest received data octet */
uint8_t DataRegister = 0;
/* Used to accumulate the CRC on the data field of a frame. */
static uint16_t DataCRC = 0;
/* Used to accumulate the CRC on the header of a frame. */
static uint8_t HeaderCRC = 0;
/* Used as an index by the Receive State Machine,
up to a maximum value of the MPDU */
static uint8_t Index = 0;
switch (Receive_State) {
case MSTP_RECEIVE_STATE_IDLE:
/* In the IDLE state, the node waits
for the beginning of a frame. */
if (RS485_ReceiveError()) {
/* EatAnError */
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
} else if (RS485_DataAvailable(&DataRegister)) {
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
if (DataRegister == 0x55) {
/* Preamble1 */
/* receive the remainder of the frame. */
Receive_State = MSTP_RECEIVE_STATE_PREAMBLE;
}
}
break;
case MSTP_RECEIVE_STATE_PREAMBLE:
/* In the PREAMBLE state, the node waits for the
second octet of the preamble. */
if (Timer_Silence() > Tframe_abort) {
/* Timeout */
/* a correct preamble has not been received */
/* wait for the start of a frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else if (RS485_ReceiveError()) {
/* Error */
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
/* wait for the start of a frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else if (RS485_DataAvailable(&DataRegister)) {
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
if (DataRegister == 0xFF) {
/* Preamble2 */
Index = 0;
HeaderCRC = 0xFF;
/* receive the remainder of the frame. */
Receive_State = MSTP_RECEIVE_STATE_HEADER;
} else if (DataRegister == 0x55) {
/* ignore RepeatedPreamble1 */
/* wait for the second preamble octet. */
Receive_State = MSTP_RECEIVE_STATE_PREAMBLE;
} else {
/* NotPreamble */
/* wait for the start of a frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
}
}
break;
case MSTP_RECEIVE_STATE_HEADER:
/* In the HEADER state, the node waits
for the fixed message header. */
if (Timer_Silence() > Tframe_abort) {
/* Timeout */
/* indicate that an error has occurred
during the reception of a frame */
MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of a frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else if (RS485_ReceiveError()) {
/* Error */
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
/* indicate that an error has occurred
during the reception of a frame */
MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of a frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else if (RS485_DataAvailable(&DataRegister)) {
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
if (Index == 0) {
/* FrameType */
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
FrameType = DataRegister;
Index = 1;
} else if (Index == 1) {
/* Destination */
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
DestinationAddress = DataRegister;
Index = 2;
} else if (Index == 2) {
/* Source */
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
SourceAddress = DataRegister;
Index = 3;
} else if (Index == 3) {
/* Length1 */
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
DataLength = DataRegister * 256;
Index = 4;
} else if (Index == 4) {
/* Length2 */
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
DataLength += DataRegister;
Index = 5;
} else if (Index == 5) {
/* HeaderCRC */
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
/* In the HEADER_CRC state, the node validates the CRC
on the fixed message header. */
if (HeaderCRC != 0x55) {
/* BadCRC */
/* indicate that an error has occurred during
the reception of a frame */
MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of the next frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else {
/* Note: proposed change to BACnet MSTP state machine!
If we don't decode data that is not for us, we could
get confused about the start if the Preamble 55 FF
is part of the data. */
if ((DataLength) && (DataLength <= InputBufferSize)) {
/* Data */
Index = 0;
DataCRC = 0xFFFF;
/* receive the data portion of the frame. */
Receive_State = MSTP_RECEIVE_STATE_DATA;
} else {
if (DataLength == 0) {
/* NoData */
if ((DestinationAddress == This_Station) ||
(DestinationAddress ==
MSTP_BROADCAST_ADDRESS)) {
/* ForUs */
/* indicate that a frame with
no data has been received */
MSTP_Flag.ReceivedValidFrame = true;
} else {
/* NotForUs - drop */
}
} else {
/* FrameTooLong */
/* indicate that a frame with an illegal or */
/* unacceptable data length has been received */
MSTP_Flag.ReceivedInvalidFrame = true;
}
/* wait for the start of the next frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
}
}
} else {
/* indicate that an error has occurred during */
/* the reception of a frame */
MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of a frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
}
}
break;
case MSTP_RECEIVE_STATE_DATA:
/* In the DATA state, the node waits
for the data portion of a frame. */
if (Timer_Silence() > Tframe_abort) {
/* Timeout */
/* indicate that an error has occurred
during the reception of a frame */
MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of the next frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else if (RS485_ReceiveError()) {
/* Error */
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
/* indicate that an error has occurred during
the reception of a frame */
MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of the next frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
} else if (RS485_DataAvailable(&DataRegister)) {
Timer_Silence_Reset();
INCREMENT_AND_LIMIT_UINT8(EventCount);
if (Index < DataLength) {
/* DataOctet */
DataCRC = CRC_Calc_Data(DataRegister, DataCRC);
InputBuffer[Index] = DataRegister;
Index++;
} else if (Index == DataLength) {
/* CRC1 */
DataCRC = CRC_Calc_Data(DataRegister, DataCRC);
Index++;
} else if (Index == (DataLength + 1)) {
/* CRC2 */
DataCRC = CRC_Calc_Data(DataRegister, DataCRC);
/* STATE DATA CRC - no need for new state */
/* indicate the complete reception of a valid frame */
if (DataCRC == 0xF0B8) {
if ((DestinationAddress == This_Station) ||
(DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
/* ForUs */
/* indicate that a frame with no data
has been received */
MSTP_Flag.ReceivedValidFrame = true;
}
} else {
MSTP_Flag.ReceivedInvalidFrame = true;
}
Receive_State = MSTP_RECEIVE_STATE_IDLE;
}
}
break;
default:
/* shouldn't get here - but if we do... */
Receive_State = MSTP_RECEIVE_STATE_IDLE;
break;
}
return;
}
/* returns true if we need to transition immediately */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -