281229961 发表于 2012-12-6 23:14:43

485多机通信 通信不正常,请帮助查问题。。。

现在连接 模式是 PC->无源232转485模块--->从机1---->从机2
从机上用485芯片。
现在问题是 只接一个从机通信非常稳定,接上第二个从机通信就不正常了,现象是上电只有一个从机能通信上,断电再上电可能变成另一只从机通信上了,断电再上电还可能会变。反正就是只有一个从机可以通信的上。用的modbus协议。
不知道从何查起?
硬件?软件?

281229961 发表于 2012-12-6 23:22:38

本帖最后由 281229961 于 2012-12-6 23:29 编辑

代码如下void USART1_IRQHandler(void)                        //串口1中断服务程序
        {
        u8 Res;
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收中断
                {
                Res =USART_ReceiveData(USART1);//(USART1->DR);        //读取接收到的数据
                   if(Res==addr&USART_RX_STA==0)      //接收到起始信号
                {
                  USART_RX_BUF=Res;
                  USART_RX_STA=1;
                }               
              else if (USART_RX_STA!=0)
                {   
                  USART_RX_BUF=Res;
                  USART_RX_STA++;
                }
                }                  
if ( USART_RX_STA>7)
checkComm0Modbus();
}

voidreadRegisters(void)
{
    unsigned int regaddr,byteCount,i;
    unsigned int num;
    unsigned int Data;
       regaddr=USART_RX_BUF+(USART_RX_BUF<<8);//要读取的寄存器起始地址
      num=USART_RX_BUF+(USART_RX_BUF<<8);//要读取的寄存器数量
      USART_TX_BUF=addr;
      USART_TX_BUF=0x03;
      USART_TX_BUF=2*num; //字节数=寄存器数量*2
      for(i=0;i<num;i++)
      {
            USART_TX_BUF=buf>>8;
            USART_TX_BUF=buf;
                        //addr+1+i:       解释如下
                        //由于上位机读写没有0号地址        上位机读写的起始地址为 读写4WB0001对应于下位机的0号地址
                        //为了便于上下位机读写地址对应, 所以下位机地址在收发的时候加 1
                        // 比如上位机读写4WB0001->00        16位读写
                        // 则下位机           反馈 buf                16位数组       
                        // 这样的话    读写4WB0001->buf       读写4WB0002->buf。。。。。
                        // (buf就再也用不到了)
                  //否则不加 1 的 话       读写4WB0001->buf       读写4WB0002->buf。。。。。
                        //纯属个人习惯!!!
      }
      byteCount=3+2*num;//CRC校验的字节数
      Data = CRCC16(USART_TX_BUF,byteCount);
      USART_TX_BUF=Data>>8;   
      USART_TX_BUF=Data&0xff;
      Uart_send_n(USART_TX_BUF,byteCount+2);
      //IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80);//接收中断使能
}

void presetMultipleRegisters(void)//多寄存器设置
{   
    unsigned int regaddr,num,i;
    unsigned int crcData;
    //unsigned int tempData;
    regaddr=USART_RX_BUF+(USART_RX_BUF<<8);
    num=USART_RX_BUF+(USART_RX_BUF<<8);
    for(i=0;i<num;i++)
      {
            buf=USART_RX_BUF+(USART_RX_BUF<<8);
                        //addr+1+i:       解释如下
                        //由于上位机读写没有0号地址        上位机读写的起始地址为 读写4WB0001对应于下位机的0号地址
                        //为了便于上下位机读写地址对应, 所以下位机地址在收发的时候加 1
                        // 比如上位机读写4WB0001->00        16位读写
                        // 则下位机           反馈 buf                16位数组       
                        // 这样的话    读写4WB0001->buf       读写4WB0002->buf。。。。。
                        // (buf就再也用不到了)
                  //否则不加 1 的 话       读写4WB0001->buf       读写4WB0002->buf。。。。。
                        //纯属个人习惯!!!
      }
      USART_TX_BUF=addr;
      USART_TX_BUF=0x10;
      USART_TX_BUF=USART_RX_BUF;
      USART_TX_BUF=USART_RX_BUF;
      USART_TX_BUF=USART_RX_BUF;
      USART_TX_BUF=USART_RX_BUF;
      crcData = CRCC16(USART_RX_BUF,6);
      USART_TX_BUF=crcData>>8;   
      USART_TX_BUF=crcData;
      Uart_send_n(USART_TX_BUF,8);
       // Recover();
       // IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80);//接收中断使能
}

void checkComm0Modbus(void)
{
    unsigned int crcData;
    unsigned int tempData;//数据个数
    if(USART_RX_STA > 4)
    {switch(USART_RX_BUF)
      {
            case 3://读取保持寄存器(一个或多个)
                  if(USART_RX_STA >= 8)
                  {//接收完成一组数据
                        //应该关闭接收中断
                      //IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x0);//关闭接收中断
                        if(USART_RX_BUF==addr)    // && checkoutError==0)
                        {
                            crcData = CRCC16(USART_RX_BUF,6);
                            if(crcData == USART_RX_BUF+(USART_RX_BUF<<8))
                            {//校验正确
                                 if(USART_RX_BUF == 3)
                              {//读取保持寄存器(一个或多个)
                                    readRegisters();
                              }
                           }
                         }            
                      USART_RX_STA = 0;      
                     // checkoutError = 0;
                  } break;
            case 16://设置多个寄存器
                  tempData = (USART_RX_BUF<<8) + USART_RX_BUF;
                  tempData = tempData * 2;    //数据个数计算=寄存器数*2+9
                  tempData += 9;            //数据个数
                  if(USART_RX_STA >= tempData)
                  {// IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x0);//关闭接收中断
                        if(USART_RX_BUF==addr)
                        {
                            crcData = CRCC16(USART_RX_BUF,tempData-2);
                            if(crcData == (USART_RX_BUF<<8)+ USART_RX_BUF)
                            {
                              presetMultipleRegisters();         
                            }
                        }   
                        USART_RX_STA = 0;
                  }
                  break;
                  
            default:
                  break;         
      }
    }
}

zml 发表于 2012-12-6 23:22:55

从机的modbus地址设置成不一样了吗?
485通讯线上有加匹配电阻吗?

281229961 发表于 2012-12-6 23:30:47

zml 发表于 2012-12-6 23:22 static/image/common/back.gif
从机的modbus地址设置成不一样了吗?
485通讯线上有加匹配电阻吗?

地址设置成不一样的了

通信线只有2m长 没有加匹配电阻

sarcophile 发表于 2012-12-6 23:54:54

从现象上看,像是软件问题。这么长的程序,不一定有人帮你找bug,自己仔细检查一下吧
硬件方面,所有端点,包括所有主机从机的地线连起来试一下

wthzack 发表于 2012-12-7 00:01:42

用串口监视 (模式是 PC->无源232转485模块) 接到AB端 看收发资料就可确定
你那485程式 应该没错 跟我使用的一样 我用再PIC上

zml 发表于 2012-12-7 18:51:03

有个软件,叫modbus poll,可以用来测试。要先分开是软件问题还是硬件问题。

281229961 发表于 2012-12-7 19:06:46

zml 发表于 2012-12-7 18:51 static/image/common/back.gif
有个软件,叫modbus poll,可以用来测试。要先分开是软件问题还是硬件问题。 ...

谢谢 周一再测试了

gaolf_2012 发表于 2012-12-7 20:40:27

收发控制脚在作怪,话说没有看到是如何控制这个管脚的

281229961 发表于 2012-12-7 22:45:35

gaolf_2012 发表于 2012-12-7 20:40 static/image/common/back.gif
收发控制脚在作怪,话说没有看到是如何控制这个管脚的

在Uart_send_n 这个函数里面的

一对一通信完全正常 测试一整天 都很好

gaolf_2012 发表于 2012-12-8 07:43:43

一对一帧间隔是多少?丢帧不?如果从机程序的控制脚处于发送状态太长,并且超过帧间隔的话会影响总线。另外你的Uart_send_n 函数我真的没找到啊

pursuer99 发表于 2012-12-13 17:06:17

说的有道理 注意帧间距离
页: [1]
查看完整版本: 485多机通信 通信不正常,请帮助查问题。。。