MODBUS调试精灵能写入单片机 但得不到正确回复 点击:3098 | 回复:3



jmlyh666

    
  • 精华:0帖
  • 求助:1帖
  • 帖子:1帖 | 0回
  • 年度积分:0
  • 历史总积分:6
  • 注册:2010年3月30日
发表于:2014-09-15 17:42:02
楼主

【描述】用MODBUS调试精灵与单片机进行通讯调试,涉及写多个寄存器(功能码10)和读定值寄存器(功能码03)两种功能。调试精灵将0xAAFF分别写入5个寄存器(十六位单片机,一共10个字节),发送指令如下:00 10 00 00 00 05 0A AA FF AA FF AA FF AA FF AA FF 95 20.第一个字节00是从机单片机地址,10为功能码,0000为寄存器首地址,0005为写入寄存器数量,95为crc低八位,20为crc告八位。
主从机波特率均为9600,数据位8位,1停止位,无校验。


【错误形式】写多数据通讯错误,让检查通讯参数和地址设置。
但是发现这条指令是可以成功写入单片机的,也能得到反馈00 10 00 00 00 05 9D.要是正确的话,得到的反馈还少一个crc的高八位。查了无数遍,都是这样的问题。


【代码】


主函数


SCI0RxIntEnable();  
EnableInterrupts;
while(1)                                                                                                                              
{
  if(cmdArrived) //定时中断中监测到3.5字节以上时间没受到数据,说明命令到达,cmdArrived=1
  {
    cmdArrived=0;//清零命令到达标志
   len=SCI0BufNum();//读取此时串口缓冲中的字节数
   if(SCI0Buf[0]==0x00)//判断第一个字节是否为从机地址,是的话进行下面的操作
   {
      crc=GetCRC16(SCI0Buf,len-2); //计算串口缓冲中除CRC高低两字节以外其它数据的CRC
      crch=crc>>8;    //获得CRC的高八位
     crcl=crc&0xFF;  //获得CRC的低八位
     if((SCI0Buf[len-2]==crch)&&(SCI0Buf[len-1]==crcl))//判断发来数据的CRC是否和自己计算的CRC一致,一致时进行下面操作
     {
        switch(SCI0Buf[1])//提取功能码  
        {
          case  0x10://功能码0x10表示主机写多个寄存器到从机
           if((SCI0Buf[2]==0x00) && (SCI0Buf[3]<=0x04))  //寄存器地址支持0x0000-0x0004
            {
              SCI0BufCopyToRegRxdGroup(); //将串口缓冲区中的数据拷贝到10个字节的RegRxdGroup寄存器中,其实是长度为5的字符数组
           }
            else//发来的寄存器地址若不在0x0000-0004当中,返回错误码
           {
              ReturnErrorCodeWhenRegAddressErrorIfWriteReg(); //错误响应0x90,错误码00000003
            }            
            calculate();//计算压差阶升幅度fai,据此给出故障信息,写入RegTxdGroup寄存器中
           break;
           
          case 0x03://功能码0x03表示主机读取从机定值寄存器
           if((SCI0Buf[2] == 0x00) && (SCI0Buf[3]<=0x04)) //判断寄存器地址是否正确
           {
              RegTxdGroupCopyToSCI0Buf(); //把RegTxdGroup寄存器中的数据写到串口缓冲区中,等待发送
           }
            else  //寄存器地址不正确时返回错误码00000003
            {
              ReturnErrorCodeWhenRegAddressErrorIfReadReg();
            }
            break;
           
          default: //其它不支持的功能码
           ReturnErrorCodeWhenDefaultFunctionCode();//返回错误码00000002
            break;
        }
      }
      else //CRC校验不正确时
     {
        ReturnErrorCodeWhenCRCCheckWrong(); //返回错误码00000004
      }
    }
    else//从机地址不正确时
   {
      ReturnErrorCodeWhenSlaveAddressWrong();//返回错误码00000001
    }
    crc = GetCRC16(SCI0Buf,len);//计算应答信息的CRC
    SCI0Buf[len++]=crc>>8;
    SCI0Buf[len++]=crc & 0xFF;
    //crch = crc>>8;
    //crcl = crc & 0xFF;
   
    for(iii=0;iii<len;iii++)  //发送应答信息主体
   {
      SCI0PutChar(SCI0Buf[iii]);
    }
    //SCI0PutChar(crcl); //发送应答信息的CRC部分
   //SCI0PutChar(crch);
   
    SCI0BufClear();//清零串口缓冲区
   DAC_Delay();//延时
  }
  }

定时器中断函数(每1ms进一次中断):


 ECT_T标志寄存器1 = 0x01U;                  
  timecnt++;
  if(timecnt>=125)
  {
    timecnt = 0;
    flag_125ms = 1;
  }
  if(SCI0BufPt>0)  /* 接收计数器大于0时开始监控总线空闲时间 */
  {
    if(SCI0BufNumTemp!=SCI0BufPt) /* 接收计数器未改变,即刚收到数据时,清零空闲计时 */
    {
       SCI0BufNumTemp=SCI0BufPt;
       FrameIdleTmr=0;
    }
    else /* 接收计数器未改变,即刚收到数据时,累积空闲时间 */
    {
      if(FrameIdleTmr<4)
        {
          FrameIdleTmr += ms;
          if(FrameIdleTmr>=4) /* 空闲时间超过3.5个字节传输时间,认为一帧命令接收完毕 */
          {
            cmdArrived=1; /* 设置命令到达标志*/
          }
        }
    }

  }
  else
  {
    SCI0BufNumTemp=0;
  }


串口接收中断函数


DisableInterrupts;
  if(SCI0SR1_RDRF==1)
 {
  if(SCI0BufPt>=SCI0_BUFNUM_MAX)
   SCI0BufPt=0;
   //SCI0BufPt=SCI0_BUFNUM_MAX-1;
  //SCI0S1;
  SCI0Buf[SCI0BufPt]=SCI0DRL;
  SCI0BufPt++;
  SCI0Clearcnt=SCI0CLEARTIME;
 }
  EnableInterrupts;


串口发送函数


void SCI0PutChar(INT8U c)
{
  while(SCI0SR1_TDRE==0);
   SCI0DRL=c;  
}





通讯网-13730920629

  • 精华:11帖
  • 求助:1帖
  • 帖子:432帖 | 10265回
  • 年度积分:0
  • 历史总积分:24711
  • 注册:2004年7月09日
发表于:2014-09-19 16:11:33
1楼

从机地址不要00,最好从01开始。怎么可能收不到呢?你先算好校验码,然后一块儿发送试试。

小韩hyp

  • 精华:0帖
  • 求助:0帖
  • 帖子:1帖 | 2回
  • 年度积分:0
  • 历史总积分:7
  • 注册:2014年4月18日
发表于:2014-10-18 09:45:07
2楼

我遇到了跟你差不多的问题,只是我是用PLC与上位机modbus通信,别的都正常,只是在读模拟量的数据,读到275时就会通信故障,别的数都可以。从发回来的数据可以看到少了二位,只是我不确定丢失的是检验码还是数据?

cain0203

  • 精华:0帖
  • 求助:0帖
  • 帖子:0帖 | 35回
  • 年度积分:0
  • 历史总积分:811
  • 注册:2012年3月23日
发表于:2014-12-31 14:35:45
3楼

modbus调试精灵不好用。。我用串口调试助手加modbuspoll


热门招聘
相关主题

官方公众号

智造工程师