搜索
bottom↓
回复: 4

MODBUS 中转模块的通讯问题(主站发送请求包给“中转”模块,中转模块翻译后送给从站)。

[复制链接]

出0入0汤圆

发表于 2010-8-19 17:38:58 | 显示全部楼层 |阅读模式
问题如下:
     主站A和从站B之间通过标准的MODBUS协议进行通讯。
     我目前要做的工作是:在主站和从站之间强行接入一个“自己开发的MODBUS设备X”, 称之为中转站。

       (a)、主站到从站的请求包,必须通过设备X(中转站)翻译后,再送给(从站)
       (b)、从站到主站的应答包,必须通过设备X(中转站)翻译后,再送给(主站)


                       主站                            自己开发的中转站                                  从站
                  |------------------    翻译       ----------------------                      ----------------------
                  |     设备A       | --------->   |    设备X            |  --------------->   |       设备B         |
                  |                 | <----------- |                     |  <--------------    |                     |  
                  |------------------    翻译      -----------------------                     -----------------------
                                                
                                                       数据流向示意图


            注:由于特殊原因,主站的寄存器地址和从站的寄存器“不是一一对应的”,因此中转站主要的工作是翻译寄存器地址。   
  
            例如:主站上0X寄存器数量 = 5 , 地址为 0:0012,0:0013,0:0014,0:0015,0:0016
                  从站上0X寄存器数量 = 5 , 地址为 0:0001,0:0002,0:0003,0:0004,0:0005

                  主站读取0X寄存器的请求包为:  

                                 1        1        00  0B         00  05       CRCHi  CRCLo
                              设备地址  功能码    起始地址=12   寄存器数量       CRC16

                  中转站接收到上述请求包后, 翻译成如下的包,然后发送给从站
     
                                 1        1        00  00         00  05       CRCHi  CRCLo
                              设备地址  功能码    起始地址=1    寄存器数量       CRC16

                                   
   

    程序构架如下:

          使用外部晶体振荡器=11.0592MHZ,波特率=38400,主站每隔150ms给中转站发送一帧请求包。


          (1). 定义两个定时器T0和T2
                T0中断用做“中转站”接收到“主站”请求包的3.5字符溢出中断,中断时间=1.25ms(1.25ms对应38400波特率的3.5字符静止时间足够了)
                T2中断用做“中转站”接收到“从站”应答包的3.5字符溢出中断,中断时间=1.25ms

         (2)、串口0
                 中转站的“串口0”接收“主站”的请求包
                 中转站的“串口0”发送“从站”的应答包
                 串口0 发送采用“空中断”方式,接收采用“中断”方式

                 当进入串口0接收中断后,开启T0中断,当T0溢出后,“中转接”收到“主站”一帧完整的请求数据包。

         (3)、串口1
                 中转站的“串口1”发送“中断站”接收到的请求包
                 中转站的“串口1”接收“从站”发送的应答包
                 串口1 发送采用“空中断”方式,接收采用“中断”方式

                 当进入串口1接收中断后,开启T2中断,当T2溢出后,,“中转接”收到“从站”一帧完整的应答数据包。


        现在存在的问题是:

                中转站接收“从站”的应答包偶而有问题,大约30分钟左右才会出现。 即“中转站”偶而接收到1个字节后,即进入T2溢出中断。

               为什么会出现:中转站接收从站返回的应答包导致T2溢出后,接收计数 = 1 呢?
                      (1)、确实是从站发送了一个字节  (这种情况不可能,因为主站和从站直连时,当设置主站和从站的寄存器地址一一对应时,没有任何问题)
                      (2)、从站正确给主转站返回的应答包,但是由于其它原因,导致中转站只接收了一个字节后,T2就溢出了。
                               这种原因,如何解决?
                      (3)、其它原因
                               这种原因,如何解决?

               注:中转站接收“主站”的请求包完全正确。

出0入0汤圆

发表于 2010-8-19 18:40:59 | 显示全部楼层
这个问题很不好查。   需要注意的地方
1.中转站接收数据。把接收到的数据一个一个移到MCU中处理也需要时间。 这些是硬件必须使用的时间。需要考虑。

3.5T只是推荐值。建议使用5ms左右。
150ms一帧建议增大到500ms
注意连接线的距离。

出0入0汤圆

 楼主| 发表于 2010-8-20 14:36:23 | 显示全部楼层
主站是一台PC机上的组态监控软件,上面显示的有:请求次数和应答次数和超时次数。
       请求次数 = 应答次数 + 超时次数

    在程序中跟踪超时时产生的原因,代码片段如下:

         经过长期运行发现,当上位机组态监控软件发生超时时,是因为中转站接收的当前应答包的个数=1时,产生了T2溢出中断。即这个应答包中转站只收到了1个字节。(面板上有两个指示灯用于跟踪错误)
      
  

(原文件名:未命名.JPG)




#define TIMER0_START()  (TCCR0 = (0 << WGM00) | (0 << WGM01) | (1 << CS02) | (1 << CS01) | (0 << CS00)) // 256 分频
#define TIMER0_STOP()   (TCCR0 = 0x00)       

#define TIMER2_START()  (TCCR2 = (0 << WGM20) | (0 << WGM21) | (1 << CS22) | (0 << CS21) | (0 << CS20)) // 256 分频       
#define TIMER2_STOP()   (TCCR2 = 0x00)       

//====================================================================================================
//TIMER0 initialize - prescale:256
// WGM: Normal
// desired value: 1.25mSec
// actual value:  1.250mSec (0.0%)
//====================================================================================================
void TIMER0_Init(void)
{
        TCCR0 = 0x00;
        ASSR  = 0x00;
        TCNT0 = 0xCA;
          OCR0 = 0x35;
        TIMSK |= (1 << TOIE0);
}

//====================================================================================================
//TIMER2 initialize - prescale:256
// WGM: Normal
// desired value: 1.25mSec
// actual value:  1.250mSec (0.0%)
//====================================================================================================
void TIMER2_Init(void)
{
        TCCR2 = 0x00;
        ASSR  = 0x00;
        TCNT2 = 0xCA;
         OCR0 = 0x35;
          TIMSK |= (1 << TOIE2);
}

#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
    TIMER0_STOP();
    USART0_OK_mark = TRUE;
}


#pragma interrupt_handler timer2_ovf_isr:iv_TIM2_OVF
void timer2_ovf_isr(void)
{
    TIMER2_STOP();
    USART1_OK_mark = TRUE;
}


#pragma interrupt_handler USART0_RI_ISR:iv_USART0_RX
void USART0_RI_ISR(void)
{
        INT8U ch;

        ch = UDR0;
        if (USART0_receCount < 255)
                USART0_mscomm_buffer[USART0_receCount++] = ch;
        TCNT0 = 0xCA;
        TIMER0_START();       
}

#pragma interrupt_handler USART1_RI_ISR:iv_USART1_RX
void USART1_RI_ISR(void)
{
        INT8U ch;

        ch = UDR1;
        if (USART1_receCount < 255)
           USART1_mscomm_buffer[USART1_receCount++] = ch;
        
        TCNT2 = 0xCA;
        TIMER2_START();              
}




void main(void)
{  
   CLI();
   PORT_Init();
   TIMER0_Init();
   TIMER2_Init();
   USART0_Init();
   USART1_Init();
   SEI();
   while (1)
   {                   
      if (USART0_OK_mark)        // 如果T0溢出,则认为中转站已经完整的接收了一帧主站的请求包
      {
                USART0_OK_mark = FALSE;
        USART0_Modbus_Analyze();
       }
                    
       if (USART1_OK_mark)      // 如果T2溢出,则认为中转站已经完整的接收了一帧从站的应答包
       {
                 USART1_OK_mark = FALSE;
         USART1_Modbus_Analyze();
        }      
     }
}

出0入0汤圆

 楼主| 发表于 2010-10-6 13:24:53 | 显示全部楼层
俺已经解决了。
   现在双向通讯没有任何问题。 连续通电3天,通讯次数达到1000000(1百万)次,通讯成功率100%。

出0入0汤圆

发表于 2010-10-6 15:09:35 | 显示全部楼层
请LZ应该分享一下解决问题的方法,谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-4 23:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表