打印

MC9S12XEP100单片机与串口232通信问题 MODBUS协议

[复制链接]
2936|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jmlyh666|  楼主 | 2014-9-15 17:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
【描述】用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;
  }



相关帖子

沙发
jmlyh666|  楼主 | 2014-9-15 17:27 | 只看该作者
在下单片机方面完全是一新手,还请大神们帮忙看看是什么问题,跪谢啦

使用特权

评论回复
板凳
多多娃娃| | 2015-12-23 15:28 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝