编写的Modbus程序,调试的过程中遇到了BUG

2019-07-20 10:08发布

我设置的寄存器地址是0-6,一开始发过去的请求报文是01 04 00 00 00 06 70 08,响应报文是01 04 0c 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 54 2c,能够正常响应
但是我把寄存器的地址改大到8,发过去的报文是01 04 00 00 00 08 f1 cc,但响应报文就很奇怪,有两个不同的响应,一个是01 82 02 c1 61,另一个是01 04 10 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 36 a1,而且两个是交叉响应回来的,但正常的话应该是第一个响应才是正确的,寄存器的地址超出了我设置的范围。以下是源码。
[mw_shl_code=c,true]PARSEERROR ModbusRtu_DatParse(Modbus_ParameterTypeDef* pModbus_Msg)
{
        uchar8_t i;
        MODBUSDAT id = 0,func = 1,Reg = 2;
        volatile uint16_t  regAddr;
        MODBUSDAT crcDataLo,crcDataHi,usDataLen;                                                                                //crc校验低位,高位
        MODBUSDAT dat[30];
       
        if(pModbus_Msg->IsComplete != True)                                                                                                //判断数据是否接收完成
                return PARError_RecErr;                                                                                                                //接收未完成,则返回接收错误
        pModbus_Msg->IsComplete = False;                                                                                                //接收完成,清除标志
       
        if(pModbus_Msg->pRecBuf[id] != ARM_ADDRESS)                                                                                //判断设备地址,非本机地址,则不处理数据
        {
                pModbus_Msg->RxCount = 0;
                return PARError_AddrErr;                                                                                                        //返回错误码
        }       
       
        //CRC校验,检查数据的完整性
        usDataLen = pModbus_Msg->RxCount - 2;                                                                                        //获取数据长度
        pModbus_Msg->crcData = crc16(pModbus_Msg->pRecBuf,usDataLen);                                        //计算CRC
        crcDataHi = pModbus_Msg->crcData / 256;                                                                                        //CRC高位
        crcDataLo = pModbus_Msg->crcData % 256;                                                                                        //CRC低位
        if(!(crcDataHi == pModbus_Msg->pRecBuf[usDataLen] && crcDataLo == pModbus_Msg->pRecBuf[usDataLen + 1]))//CRC校验
        {
                pModbus_Msg->RxCount = 0;                                                                                                        //接收区清空
                return PARError_crcErr;                                                                                                                //如果CRC校验错误,则返回错误码
        }       
       
        regAddr = (pModbus_Msg->pRecBuf[Reg] << 8) + pModbus_Msg->pRecBuf[Reg + 1];                //获取寄存器起始地址
        if( pModbus_Msg->pSendBuf[func] == ModbusFunc_04 || pModbus_Msg->pSendBuf[func] == ModbusFunc_16)//判断是否为读或写多个寄存器
                regAddr = regAddr + ((pModbus_Msg->pRecBuf[Reg + 2] << 8) + pModbus_Msg->pRecBuf[Reg + 3]);
        if(regAddr > REGALL)                                                                                                                        //判断寄存器地址是否超出范围
        {
                pModbus_Msg->RxCount = 0;                                                                                                        //接收区清空
                ModbusRtu_Error(pModbus_Msg->pSendBuf,ErrorFunc_RegAddr);                                        //非法数据地址
                pModbus_Msg->TxCount = 5;
                pModbus_Msg->pSend(pModbus_Msg->pSendBuf,pModbus_Msg->TxCount);
                return PARError_ErrFunc;
        }
       
        //数据解析
        switch(pModbus_Msg->pRecBuf[func])
        {
                case ModbusFunc_04:                                                                                                                        //4号功能码,读输入寄存器
                {
                        //应答报文
                        pModbus_Msg->pSendBuf[id] = ARM_ADDRESS;                                                                //设备地址
                        pModbus_Msg->pSendBuf[func] = ModbusFunc_04;                                                        //功能码
                        usDataLen = pModbus_Msg->pSendBuf[2] = pModbus_Msg->pRecBuf[5] * 2;                //字节数
                        pModbus_Msg->pfunc_04(dat,usDataLen);
                        for(i = 0;i < pModbus_Msg->pRecBuf[5] * 2;i++)
                                pModbus_Msg->pSendBuf[i + 2] = dat;
                        usDataLen += 3;                                                                                                                        //数据长度
                }break;
                case ModbusFunc_06:                                                                                                                        //6号功能码,写单个寄存器
                {
                        pModbus_Msg->pfunc_06((REGAddr)regAddr,((pModbus_Msg->pRecBuf[4] << 8) + pModbus_Msg->pRecBuf[5]));
                        //应答报文
                        usDataLen = 6;                                                                                                                        //数据长度
                        for(i = 0;i < usDataLen;i++)
                                pModbus_Msg->pSendBuf = pModbus_Msg->pRecBuf;
                }break;
                case ModbusFunc_16:                                                                                                                        //16号功能码,写多个寄存器
                {
                        pModbus_Msg->pfunc_16();
                        //应答报文
                        usDataLen = 6;                                                                                                                        //数据长度
                        for(i = 0;i < usDataLen;i++)
                                pModbus_Msg->pSendBuf = pModbus_Msg->pRecBuf;
                }break;
                default :
                {
                        pModbus_Msg->RxCount = 0;                                                                                                //接收区清空
                        ModbusRtu_Error(pModbus_Msg->pSendBuf,ErrorFunc_Func);                                        //不是本设备支持的功能码
                        pModbus_Msg->TxCount = 5;
                        pModbus_Msg->pSend(pModbus_Msg->pSendBuf,pModbus_Msg->TxCount);
                        return PARError_ErrFunc;
                }
        }
       
        pModbus_Msg->crcData = crc16(pModbus_Msg->pSendBuf,usDataLen);                                        //计算CRC
        pModbus_Msg->pSendBuf[usDataLen] = pModbus_Msg->crcData / 256;                                        //CRC高位
        pModbus_Msg->pSendBuf[usDataLen + 1] = pModbus_Msg->crcData % 256;                                //CRC低位
        pModbus_Msg->TxCount = usDataLen + 2;                                                                                        //发送数据长度
        pModbus_Msg->RxCount = 0;                                                                                                                //清除接收缓存
        pModbus_Msg->pSend(pModbus_Msg->pSendBuf,pModbus_Msg->TxCount);
       
        return PARError_OK;                                                                                                                                //如果没有错误,则返回无错误值
}[/mw_shl_code]这一段是判断寄存器范围的(从上面的源码抽出来的)
[mw_shl_code=applescript,true]regAddr = (pModbus_Msg->pRecBuf[Reg] << 8) + pModbus_Msg->pRecBuf[Reg + 1];        //获取寄存器起始地址
if( pModbus_Msg->pSendBuf[func] == ModbusFunc_04 || pModbus_Msg->pSendBuf[func] == ModbusFunc_16)//判断是否为读或写多个寄存器
regAddr = regAddr + ((pModbus_Msg->pRecBuf[Reg + 2] << 8) + pModbus_Msg->pRecBuf[Reg + 3]);
if(regAddr > REGALL)        //判断寄存器地址是否超出范围
{
pModbus_Msg->RxCount = 0;        //接收区清空
ModbusRtu_Error(pModbus_Msg->pSendBuf,ErrorFunc_RegAddr);        //非法数据地址
pModbus_Msg->TxCount = 5;
pModbus_Msg->pSend(pModbus_Msg->pSendBuf,pModbus_Msg->TxCount);
return PARError_ErrFunc;
}[/mw_shl_code]

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。