为什么 samd21 正在读取 modbus 自己的响应作为主请求?
Why samd21 is reading modbus own response as a master request?
我正在将通过 RS-485(通过芯片 ADM2587EBRWZ)的从属 MODBUS RTU 通信添加到 SAMD21 现有程序中。只实现读取保持寄存器和写入单个寄存器命令,因为我不需要更多。
为了测试它,我使用 Microcom 的 PLC 作为主机。我让它 运行 几个小时,但日志显示一些 -3333 值(Microcom 使用 -3333 来显示读取该寄存器时发生错误)。检查 plc 终端我注意到如果应答消息以“00 00 CRC_lo 00”结尾,则下一个请求是错误的。
如果在 Atmelstudio 上调试,ATSAMD21 会读取相同的答案并将其检测为请求,从而向 PLC 提供非法数据地址响应。
回答后我在端口上做了一个 usart_reset 并清理消息数组,知道它是什么吗?
2 条注意事项:我对 C 编程还很陌生,英语不是我的第一语言。
编辑:添加了更多代码,如果还需要什么我可以 post。
这部分在主循环中:
while(ReceivedCommand_MODBUS() ==false)
{
UartReadJob_MODBUS();
}
AnalyzeReceiveCommand_MODBUS();
第一个函数是:
bool ReceivedCommand_MODBUS()
{
uint16_t CRC=0;
CRC = CRC16(CommandReadBuffer_MODBUS,6);
if ((CommandReadBuffer_MODBUS[CommandReadLength-1] == ((CRC & 0xFF00)>>8)) && (CommandReadBuffer_MODBUS[CommandReadLength-2]) == (CRC & 0x00FF) )
{
return true;
}
if ((CommandReadLength - 1 )>= RS485_COMMAND_LENGTH)
{
CommandReadLength = 0;
memset(CommandReadBuffer_MODBUS, 0, sizeof(CommandReadBuffer_MODBUS));
}
return false;
}
最后一个:
void AnalyzeReceiveCommand_MODBUS()
{
uint32_t receiveLength = 0;
uint8_t receiveCommand[COMMAND_READ_BUFFER_LENGTH_MODBUS];
memset(receiveCommand, 0, COMMAND_READ_BUFFER_LENGTH_MODBUS);
ReadCommand_MODBUS(receiveCommand, &receiveLength);
uint16_t CRC = 0;
//Modbus request is read and response generated here
SendMaster_MODBUS(messageData,MessageSize);
delay_ms(10); //delays are for breakpoints
UartReset(&UART1);
for (char i=0;i<=MessageSize+1;i++)
{
UartReceiveBuffer_MODBUS[i]=0;
UartSendBuffer_MODBUS[i]=0;
messageData[i]=0;
}
void ResetBuffer_MODBUS ();
delay_ms(10);
}
ReadCommand_MODBUS 函数:
void ReadCommand_MODBUS(uint8_t* command, uint32_t* length)
{
*length = CommandReadLength;
memcpy(command, CommandReadBuffer_MODBUS, CommandReadLength);
CommandReadLength = 0;
memset(CommandReadBuffer_MODBUS, 0, sizeof(CommandReadBuffer_MODBUS));
}
现在好像可以了,发送响应消息后调用这个:
void ResetBuffer_MODBUS ()
{
memset(CommandReadBuffer_MODBUS, 0, sizeof(CommandReadBuffer_MODBUS));
}
到目前为止没有错误,将暂时保留 运行,但在此之前它会失败几次。
我正在将通过 RS-485(通过芯片 ADM2587EBRWZ)的从属 MODBUS RTU 通信添加到 SAMD21 现有程序中。只实现读取保持寄存器和写入单个寄存器命令,因为我不需要更多。
为了测试它,我使用 Microcom 的 PLC 作为主机。我让它 运行 几个小时,但日志显示一些 -3333 值(Microcom 使用 -3333 来显示读取该寄存器时发生错误)。检查 plc 终端我注意到如果应答消息以“00 00 CRC_lo 00”结尾,则下一个请求是错误的。 如果在 Atmelstudio 上调试,ATSAMD21 会读取相同的答案并将其检测为请求,从而向 PLC 提供非法数据地址响应。
回答后我在端口上做了一个 usart_reset 并清理消息数组,知道它是什么吗?
2 条注意事项:我对 C 编程还很陌生,英语不是我的第一语言。
编辑:添加了更多代码,如果还需要什么我可以 post。 这部分在主循环中:
while(ReceivedCommand_MODBUS() ==false)
{
UartReadJob_MODBUS();
}
AnalyzeReceiveCommand_MODBUS();
第一个函数是:
bool ReceivedCommand_MODBUS()
{
uint16_t CRC=0;
CRC = CRC16(CommandReadBuffer_MODBUS,6);
if ((CommandReadBuffer_MODBUS[CommandReadLength-1] == ((CRC & 0xFF00)>>8)) && (CommandReadBuffer_MODBUS[CommandReadLength-2]) == (CRC & 0x00FF) )
{
return true;
}
if ((CommandReadLength - 1 )>= RS485_COMMAND_LENGTH)
{
CommandReadLength = 0;
memset(CommandReadBuffer_MODBUS, 0, sizeof(CommandReadBuffer_MODBUS));
}
return false;
}
最后一个:
void AnalyzeReceiveCommand_MODBUS()
{
uint32_t receiveLength = 0;
uint8_t receiveCommand[COMMAND_READ_BUFFER_LENGTH_MODBUS];
memset(receiveCommand, 0, COMMAND_READ_BUFFER_LENGTH_MODBUS);
ReadCommand_MODBUS(receiveCommand, &receiveLength);
uint16_t CRC = 0;
//Modbus request is read and response generated here
SendMaster_MODBUS(messageData,MessageSize);
delay_ms(10); //delays are for breakpoints
UartReset(&UART1);
for (char i=0;i<=MessageSize+1;i++)
{
UartReceiveBuffer_MODBUS[i]=0;
UartSendBuffer_MODBUS[i]=0;
messageData[i]=0;
}
void ResetBuffer_MODBUS ();
delay_ms(10);
}
ReadCommand_MODBUS 函数:
void ReadCommand_MODBUS(uint8_t* command, uint32_t* length)
{
*length = CommandReadLength;
memcpy(command, CommandReadBuffer_MODBUS, CommandReadLength);
CommandReadLength = 0;
memset(CommandReadBuffer_MODBUS, 0, sizeof(CommandReadBuffer_MODBUS));
}
现在好像可以了,发送响应消息后调用这个:
void ResetBuffer_MODBUS ()
{
memset(CommandReadBuffer_MODBUS, 0, sizeof(CommandReadBuffer_MODBUS));
}
到目前为止没有错误,将暂时保留 运行,但在此之前它会失败几次。