搜索
bottom↓
回复: 25

特别请教,大数据量通讯,波特率很低,采用“中断+缓存+超时+重发” 仍不能确保通讯畅通的解

[复制链接]

出0入0汤圆

发表于 2008-11-22 11:55:14 | 显示全部楼层 |阅读模式
   我需要解决在低波特率(1200、2400、4800)时,通过上位机和下位机之间通讯,数量量比较大,采用“中断+缓存+超时+重发” 

仍不能解决通讯畅通,但是在9600、19200以上的波特率时,通讯质量非常好,请问解决办法。 

   (1)、协议采用MODBUS-RTU 

   (2)、通讯模式,采用RS485方式。 

   (2)、通讯结构图如下: 

 



 |-----------------------------|     |----------------------------|      |---------------------------        

 |                             |     |                            |      |                          |            

 |                             |     |       中转站               |      |   总线上子模块1          |            

 |          PC机               |     |                            |      |                          |            

 |                             |     |---------|      |-----------|      |              |-----------|            

 |                             |---->| USART0  |----->|  USART1   |------------------>  |    USART1 |    

 |                             |     |         |      |           |      |              |           |           

 |-----------------------------|     |----------------------------|      |--------------------------|   



       说明: 

      (A)PC机和“中转站”模块的USART0端口直连。 

      (B)“中转站”的USART1端口和总线上子模块的USART1端口直连,构成RS485。 

///////////////////////////////////////////////////////////////////

      (C).PC机要访问总线上的子模块1必须通过“中转站”模块,PC机访问子模块1的过程如下: 

         (C.1)PC机将访问”子模块1“的数据包发送到“中转站”的USART0端口。 

         (C.2)“中转站”平时处于“RS485接收状态”,当接收到一帧完整的数据包后,将自身置为“RS485发送状态”。 

             然后通过自身的USART1端口发布到总线上。发送完毕后,将自身置为“RS485接收状态”。    

         (C.3)总线上的“子模块1”接收到一帧完整的数据包后,将自身置为“RS485发送状态”,然后将《应答数据包》通过USART1端口 

            发布到总线上。发送完毕,将自身置为“RS485接收状态”。 

         (C.4)”中转站“的USART1端口接收到一帧完整的应答数据包后,通过自身的USART0端口,将“子模块1”的应答数据包 

            转发给PC机。 

      (D)、串口接收中断服务程序非常短,定时中断服务程序中一进入中断服务程序,就执行SEI()。 

      

 我做了如下实验:

   (1)、PC机每隔5秒钟发送一帧数据包(长度=249字节),如果中转站接收到数据包,中转站的第一排数码管上就加1。 

   (2) 子模块1接收到“中转站”转发的数据包,子模块1的数码管上就加1。 

  (3)、中转站模块接收到“子模块1”的应答数据包,中转站的第二排数码管就加1。  



  经过反复测试,当波特率=1200时,子模块90%能够接收到PC机的数据包, 

   ★★★ 然而,“中转站”却接收不到“子模块1”的应答消息(应答消息才8个字节)

出0入296汤圆

发表于 2008-11-25 20:59:42 | 显示全部楼层
你是不是偷懒只用了一个MAX232芯片连接了USART0和USART1?如果是换一个……

我以前遇到过这种歪货……气死俺了……

本贴被 Gorgon Meducer 编辑过,最后修改时间:2008-11-25,21:02:26.

出0入0汤圆

 楼主| 发表于 2008-11-25 18:29:43 | 显示全部楼层
我感觉好象是硬件的问题。

 (1)、波特率=1200时,去掉子模块后,PC机直接给中转站发送数据(中转站的USART0端口接收PC机的数据),

      中转站的USART1端口竟然产生接收中断。(中转站的USART1端口接收子模块的数据或者给子模块“转发”数据) 

 (2)、波特率=2400、4800时

    不会产生上述现象。

    此时挂上子模块,但是却会产生下述现象:

      如果PC机发送一帧数据中,包含0xFF时(整型负数转换成两个BYTE型),产生的应答数会是随机数,如果一帧数据中无0xFF,则一切正常。

    应该怀疑是RS485转换电路的原因。

        

出0入296汤圆

发表于 2008-11-25 14:19:26 | 显示全部楼层
to 【22楼】 ba_wang_mao  

    去掉数据帧的解析部分,收到上位机数据以后直接回发。看看效果。

出0入0汤圆

发表于 2008-11-25 09:29:47 | 显示全部楼层
PC机固定发送129字节是没秒发送的数据个数吗?



17楼说的很有可能



你在1200、2400波特率时减少数据发送的个数,先减少到10个字节,看看还会不会出现问题

出0入0汤圆

 楼主| 发表于 2008-11-25 08:42:37 | 显示全部楼层
 去掉从机也一样,

   当波特率高于4800时,一切正常。  

   当波特率=1200、2400,发现  

      PC机固定发送129字节时,中转站接收的数据个数竟然是随机的,不是129字节,到底是什么原因造成的呢? 

出0入296汤圆

发表于 2008-11-24 18:19:46 | 显示全部楼层
建议楼主隔离测试……就是去掉从机,只保留中转站和PC用1200波特率通讯看看……

是否有丢数据的现象

出0入0汤圆

发表于 2008-11-24 17:19:38 | 显示全部楼层
你pc到中转站也出问题?怀疑你中转站波特率设置不正确

出0入0汤圆

 楼主| 发表于 2008-11-24 16:46:40 | 显示全部楼层
favr:

  1、PC机--->中转站速度很快(中转站的中断服务程序非常短,只是判断1.5字符的静止时间,打断串口的时间基本不用考虑)

  2、子模块1的定时中断服务程序也很短,而且我在一进入定时中断后,就开放了全局中断(SEI()),

  3、PC机等待应答数据包的时间,我根据不同的波特率,存储了一张超时时间表,该时间充分考虑了上述时间(从PC--->中转站--->子模块)、然后从(子模块1--->中转站--->PC机),该超时时间是正常计算时间的2倍。

  4、只有超时结束后,还没有收到应答数据包,PC机才会重发该帧数据。

出0入0汤圆

发表于 2008-11-24 16:35:31 | 显示全部楼层
先做一个简单的计算:

当使用1200Bit的速率时;以1个起始位,8个数据位一个停止位的格式传递一个字节,传递一个字节至少需要10个位,即每秒最多可以传递120个Byte,249Byte需要249/120=2.075(s),大概2秒左右。按照你的传输方式,pc->中转站需要2s,中转站->子模块需要2s;最少需要4s时间,加上中间转换、计算、判断、总线等待等,5s/帧原理上没问题,但如果软件没做好,例如中间的计算、总线等待等没做好就可能不行,[对C不在行,不能从你的代码判断整个接收/发送过程时间消耗情况]。

如果实际出现你描述的情况:不稳定。则十有八九通讯已经出差了,例如PC当前收到的应答是前一、二、个数据包的回应,你应该用能反映不同数据包返回信息判断是否出现这样的情况,如果2400bit速率还出现这种情况,而4800以上就没问题,则出现套帧的可能性就n大了。

出0入0汤圆

 楼主| 发表于 2008-11-24 16:23:37 | 显示全部楼层
两个帧解析函数在“主程序”调用



void main(void)

{



        CLI();

         PORT_Init();

        POST_Delay();

        QUEUE_Init();

        TIMER2_Init();

        PROC_Init();

        SEI();

        while (1)

        {

//                 _StackCheck();                                //        测试堆栈

                USART0_Modbus_Analyze();

                USART1_Modbus_Analyze();

                MSCOMM_ID_Switch();//上位机身份切换子程序

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//广播设置总线波特率时要占用USART1端口,通讯模块扫描总线上的监视模块时,也要占用USART1端口,因此应该避开这种情况。防止总线//数据混乱,同时由于广播设置总线的波特率的优先级最高,因此USART1端口应该等发送完广播消息后,再发送扫描消息。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                if (MSCOMM_send_mark && MSCOMM_ID == enum_DCS_SOFTWARE && !BoardCast_mark)

                {

                        MSCOMM_send_mark = FALSE;

                        switch (MSCOMM_scan_Func)

                        {

                                case enum_SEND_CoilRegisters:

                                        MODBUS_Read_CoilRegisters();

                                        break;

                                case enum_SEND_DiscreteRegisters:

                                        MODBUS_Read_DiscreteRegisters();

                                        break;

                                case enum_SEND_InputRegisters:

                                        MODBUS_Read_InputRegisters();

                                        break;

                        }

                }

                Watch_Dog();

        }

}

出0入0汤圆

 楼主| 发表于 2008-11-24 16:21:16 | 显示全部楼层
问题终于找到了。现象如下:



  在波特率=1200、2400,发现 

  PC机固定发送129字节时,中转站接收的数据个数竟然是随机的,不是129字节,到底是什么原因造成的呢?

出0入296汤圆

发表于 2008-11-24 16:18:38 | 显示全部楼层
这种通讯系统按道理基本不错才对……

你的两个帧解析函数在什么地方调用的?

出0入0汤圆

 楼主| 发表于 2008-11-24 16:17:04 | 显示全部楼层
在定时中断服务程序的开头,我加了SEI()。

出0入0汤圆

 楼主| 发表于 2008-11-24 16:16:01 | 显示全部楼层
不同的波特率,超时时间我计算过的,对于1200波特率来说,每传送一个字节需要11位(1个起始位+8个数据位+2位停止位)

   1200            11

 --------------   =  -----   ===>  x=1000*11/1200=9.2毫秒

      1000             x

 也就是说在波特率=1200时,传输1个字节至少需要9.2毫秒,而我的超时时间设置=50毫秒,应该足够了。



void USART1_Modbus_Analyze(void)

{

         UCHAR i; 

        SHORT tempData;

        USHORT crcData;

        

        if (USART1_receCount> 2)

        {

                switch (USART1_mscomm_buffer[1])

                {

                        case 1:

                                if (USART1_checkoutError == 0 && USART1_mscomm_buffer[0] != 0)

                                {

                                        tempData = (SHORT)(USART1_mscomm_buffer[2]) + 5;

                                        if (USART1_receCount>= tempData && USART1_receCount < MSCOMM_BUFFER_LENGTH)

                                        {

                                                UCSR1B &= ~BIT(7);

                                                crcData = CRC16(USART1_mscomm_buffer,tempData - 2);

                                                if (crcData == (USHORT)(USART1_mscomm_buffer[tempData - 2] << 8) + (USHORT)USART1_mscomm_buffer[tempData - 1])

                                                {

                                                        switch (MSCOMM_ID)

                                                        {

                                                                case enum_POS3000:

                                                                case enum_CONFIG_SOFTWARE:

                                                                        USART0_sendCount = tempData;

                                                                        for (i = 0 ; i < tempData ; i++)

                                                                                USART0_send_buffer = USART1_mscomm_buffer;

                                                                        USART0_Begin_Send();

                                                                        break;

                                                                case enum_DCS_SOFTWARE:

                                                                        MSCOMM_Cache[MSCOMM_scan_ID].DO = USART1_mscomm_buffer[3];

                                                                        MSCOMM_Cache[MSCOMM_scan_ID].OnLine_Type = enum_OnLine;

                                                                        MSCOMM_ack_type = enum_ACK_OK;



/*                                                                        #ifdef __DEBUG_COUNT__

                                                                                if (MSCOMM_scan_type == enum_ONLINE_SCAN)

                                                                                        CHB++;

                                                                        #endif*/

                                                                        break;

                                                        }

                                                }

                                                USART1_receCount = 0;

                                                USART1_checkoutError = 0;

                                                UCSR1B |= BIT(7);

                                        }

                                }

                                break;

                         case 2:

                                if (USART1_checkoutError == 0 && USART1_mscomm_buffer[0] != 0)

                                {

                                        tempData = (SHORT)(USART1_mscomm_buffer[2]) + 5;

                                        if (USART1_receCount>= tempData && USART1_receCount < MSCOMM_BUFFER_LENGTH)

                                        {

                                                UCSR1B &= ~BIT(7);

                                                crcData = CRC16(USART1_mscomm_buffer,tempData - 2);

                                                if (crcData == (USHORT)(USART1_mscomm_buffer[tempData - 2] << 8) + (USHORT)USART1_mscomm_buffer[tempData - 1])

                                                {

                                                        switch (MSCOMM_ID)

                                                        {

                                                                case enum_POS3000:

                                                                case enum_CONFIG_SOFTWARE:

                                                                        USART0_sendCount = tempData;

                                                                        for (i = 0 ; i < tempData ; i++)

                                                                                USART0_send_buffer = USART1_mscomm_buffer;

                                                                        USART0_Begin_Send();

                                                                        break;

                                                                case enum_DCS_SOFTWARE:

                                                                        MSCOMM_Cache[MSCOMM_scan_ID].DI = USART1_mscomm_buffer[3];

                                                                        MSCOMM_Cache[MSCOMM_scan_ID].OnLine_Type = enum_OnLine;

                                                                        MSCOMM_ack_type = enum_ACK_OK;



/*                                                                        #ifdef __DEBUG_COUNT__

                                                                                if (MSCOMM_scan_type == enum_ONLINE_SCAN)

                                                                                        CHB++;

                                                                        #endif*/

                                                                        break;

                                                        }

                                                }

                                                USART1_receCount = 0;

                                                USART1_checkoutError = 0;

                                                UCSR1B |= BIT(7);

                                        }

                                }

                                break;

                        case 3:

                                if (USART1_checkoutError == 0 && USART1_mscomm_buffer[0] != 0)

                                {

                                        tempData = (SHORT)(USART1_mscomm_buffer[2]) + 5;

                                        if (USART1_receCount>= tempData && USART1_receCount < MSCOMM_BUFFER_LENGTH)

                                        {

                                                UCSR1B &= ~BIT(7);

                                                crcData = CRC16(USART1_mscomm_buffer,tempData - 2);

                                                if (crcData == (USHORT)(USART1_mscomm_buffer[tempData - 2] << 8) + (USHORT)USART1_mscomm_buffer[tempData - 1])

                                                {

                                                        switch (MSCOMM_ID)

                                                        {

                                                                case enum_POS3000:

                                                                case enum_CONFIG_SOFTWARE:

                                                                        USART0_sendCount = tempData;

                                                                        for (i = 0 ; i < tempData ; i++)

                                                                                USART0_send_buffer = USART1_mscomm_buffer;

                                                                        USART0_Begin_Send();

                                                                        break;

                                                        }

                                                }

                                                USART1_receCount = 0;

                                                USART1_checkoutError = 0;

                                                UCSR1B |= BIT(7);

                                        }

                                }

                                break;

                        case 4:

                                if (USART1_checkoutError == 0 && USART1_mscomm_buffer[0] != 0)

                                {

                                        tempData = (SHORT)(USART1_mscomm_buffer[2]) + 5;

                                        if (USART1_receCount>= tempData && USART1_receCount < MSCOMM_BUFFER_LENGTH)

                                        {

                                                UCSR1B &= ~BIT(7);

                                                crcData = CRC16(USART1_mscomm_buffer,tempData - 2);

                                                if (crcData == (USHORT)(USART1_mscomm_buffer[tempData - 2] << 8) + (USHORT)USART1_mscomm_buffer[tempData - 1])

                                                {

                                                        switch (MSCOMM_ID)

                                                        {

                                                                case enum_POS3000:

                                                                case enum_CONFIG_SOFTWARE:

                                                                        USART0_sendCount = tempData;

                                                                        for (i = 0 ; i < tempData ; i++)

                                                                                USART0_send_buffer = USART1_mscomm_buffer;

                                                                        USART0_Begin_Send();

                                                                        break;

                                                                case enum_DCS_SOFTWARE:

                                                                        for (i = 0 ; i < 4 ; i++)

                                                                                MSCOMM_Cache[MSCOMM_scan_ID].Input_Buffer = (SHORT)(USART1_mscomm_buffer[3 + 2*i] << 8) + (SHORT)(USART1_mscomm_buffer[3 + 2*i+1]);

                                                                        MSCOMM_Cache[MSCOMM_scan_ID].OnLine_Type = enum_OnLine;

                                                                        MSCOMM_ack_type = enum_ACK_OK;



/*                                                        #ifdef __DEBUG_COUNT__

                                                                                if (MSCOMM_scan_type == enum_ONLINE_SCAN)

                                                                                        CHB++;

                                                                                #endif*/

                                                                        break;

                                                        }

                                                }

                                                USART1_receCount = 0;

                                                USART1_checkoutError = 0;

                                                UCSR1B |= BIT(7);

                                        }

                                }

                                break;

                        case 6:

                                if (USART1_receCount>= 8 && USART1_checkoutError == 0 && USART1_mscomm_buffer[0] != 0)

                                {

                                        UCSR1B &= ~BIT(7);

                                        crcData = CRC16(USART1_mscomm_buffer,6);

                                        if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7])

                                        {

                                                switch (MSCOMM_ID)

                                                {

                                                        case enum_POS3000:

                                                        case enum_CONFIG_SOFTWARE:

                                                                USART0_sendCount = 8;

                                                                for (i = 0 ; i < 8 ; i++)

                                                                        USART0_send_buffer = USART1_mscomm_buffer;

                                                                USART0_Begin_Send();

                                                                break;

                                                }

                                        }

                                        USART1_receCount = 0;

                                        USART1_checkoutError = 0;        

                                        UCSR1B |= BIT(7);                                                                                        

                                }

                                break;

                        case 16:

                                if (USART1_receCount>= 8 && USART1_checkoutError == 0 && USART1_mscomm_buffer[0] != 0)

                                {

                                        UCSR1B &= ~BIT(7);

                                        crcData = CRC16(USART1_mscomm_buffer,6);

                                        if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7])

                                        {

                                                switch (MSCOMM_ID)

                                                {

                                                        case enum_POS3000:

                                                        case enum_CONFIG_SOFTWARE:

                                                                USART0_sendCount = 8;

                                                                for (i = 0 ; i < 8 ; i++)

                                                                        USART0_send_buffer = USART1_mscomm_buffer;

                                                                USART0_Begin_Send();

                                                                break;

                                                }

                                       &nbsp

出0入296汤圆

发表于 2008-11-24 16:09:25 | 显示全部楼层
在每一个中断处理程序的开头都加SEI看看。

不过需要注意,对于接收完成中断,SEI要放在读取UDR寄存器以后……

出0入0汤圆

 楼主| 发表于 2008-11-24 16:09:14 | 显示全部楼层
(3)中转站的定时中断服务程序

   只是检测1.5字符的静止时间,没有其它代码。

出0入0汤圆

 楼主| 发表于 2008-11-24 16:05:55 | 显示全部楼层
(1)、中转站的USART0部分



void USART0_Begin_Send(void)

{

        USART0_RS485_SEND();

        NOP();                                                //        --------|        

        NOP();                                                //                        |

        NOP();                                                //                        |-----------等待总线释放

        NOP();                                                //                        |

        NOP();                                                //        --------|

        NOP();                                                //        --------|        

        NOP();                                                //                        |

        NOP();                                                //                        |-----------等待总线释放

        NOP();                                                //                        |

        NOP();                                                //        --------|

        USART0_sendPosi = 0;

        UCSR0B |= BIT(5);   //加快发送速度,用空中断发送

}





#pragma interrupt_handler USART0_RI_ISR:iv_USART0_RX

void USART0_RI_ISR(void)

{

        UCHAR ch;

        UCHAR status;



        status = UCSR0A;

        ch = UDR0;

        if (USART0_receCount < MSCOMM_BUFFER_LENGTH)

                 USART0_mscomm_buffer[USART0_receCount++] = ch;

        else

                USART0_receCount = 0;

        if (status & 0x1c)

                USART0_checkoutError = 2;

        USART0_receTimeOut = 3;

}





#pragma interrupt_handler USART0_UDRE_ISR:iv_USART0_UDRE

void USART0_UDRE_ISR(void) 

{

        UDR0 = USART0_send_buffer[USART0_sendPosi++];

        if (USART0_sendPosi>= USART0_sendCount)

        {

                UCSR0B &= ~BIT(5);

                UCSR0B |= BIT(6);

        } 

}





#pragma interrupt_handler USART0_TX_ISR:iv_USART0_TX

void USART0_TX_ISR(void) 

{

        USART0_checkoutError = 0;

        USART0_receCount = 0;

        USART0_RS485_RECIVE();

}





(2)、中转站的USART1部分



void USART1_Begin_Send(void)

{

        USART1_RS485_SEND();

        NOP();                                                //        --------|        

        NOP();                                                //                        |

        NOP();                                                //                        |-----------等待总线释放

        NOP();                                                //                        |

        NOP();                                                //        --------|

        NOP();                                                //        --------|        

        NOP();                                                //                        |

        NOP();                                                //                        |-----------等待总线释放

        NOP();                                                //                        |

        NOP();                                                //        --------|

        USART1_sendPosi = 0;

        UCSR1B |= BIT(5);//加快发送速度,用空中断发送

}



#pragma interrupt_handler USART1_RI_ISR:iv_USART1_RX

void USART1_RI_ISR(void)

{

        UCHAR ch;

        UCHAR status;



        status = UCSR1A;

        ch = UDR1;

        if (USART1_receCount < MSCOMM_BUFFER_LENGTH)

                 USART1_mscomm_buffer[USART1_receCount++] = ch;

        else

                USART1_receCount = 0;

        if (status & 0x1c)

                USART1_checkoutError = 2;

        USART1_receTimeOut = 5;

}





#pragma interrupt_handler USART1_UDRE_ISR:iv_USART1_UDRE

void USART1_UDRE_ISR(void) 

{

        UDR1 = USART1_send_buffer[USART1_sendPosi++];

        if (USART1_sendPosi>= USART1_sendCount)

        {

                UCSR1B &= ~BIT(5);

                UCSR1B |= BIT(6);

        } 

}





#pragma interrupt_handler USART1_TX_ISR:iv_USART1_TX

void USART1_TX_ISR(void) 

{

        USART1_checkoutError = 0;

        USART1_receCount = 0;

        USART1_RS485_RECIVE();

        if (BoardCast_mark)  //如果PC机通过广播修改总线上其它模块的波特率时,必须待中转站将当前帧数据发送完毕后

        {           //(发送给总线上的子模块后),才能修改中转站USART1端口的波特率

                BoardCast_mark = FALSE;

                USART1_Init(set_buffer[BAUD_NO - 1]);

        }

}

出0入296汤圆

发表于 2008-11-24 15:57:22 | 显示全部楼层
楼主你的程序问题主要体现在中转模块上了。

看一下你的代码结构?

出0入0汤圆

发表于 2008-11-24 15:49:58 | 显示全部楼层
另外这个超时时间的设置要合理,得保证中转站能及时响应PC机的请求。不然在工控应用中,中转站会缓冲区不够用的

出0入0汤圆

发表于 2008-11-24 15:47:12 | 显示全部楼层
中转站和子模块都属slave,关键是要保证对总路线访问权的串行控制。对响应需要设置一定的超时时间

出0入0汤圆

发表于 2008-11-24 14:43:50 | 显示全部楼层
还有你的中转站的发送接收状态转换部分再查查看

出0入0汤圆

发表于 2008-11-24 14:41:50 | 显示全部楼层
波特率低出问题说明还是时序上的问题。你的中转站发送完以后等待应答,多长时间算超时?

出0入0汤圆

 楼主| 发表于 2008-11-24 14:33:04 | 显示全部楼层
(1)PC机发送249字节的请求包给子模块1(预置120个保持寄存器),传输路线如下: 

   

 |-----------------------------|     |----------------------------|      |---------------------------         

 |                             |     |                            |      |                          |             

 |                             |     |       中转站               |      |   总线上子模块1          |             

 |          PC机               |     |                            |      |                          |             

 |                  |----------|     |---------         |---------|      |              |----------                                     |        |         |         |      |              |           | 

 |                  |          |---->| USART0 | ------> |  USART1 |-------------------->|    USART1 |     

 |                  |  USART0  |     |        |         |         |      |              |           |            

 |-----------------------------|     |----------------------------|      |--------------------------|    



(2)子模块1接收到请求包数据,然后发送8个字节的应答包给PC机,传输路线如下: 



    

 |-----------------------------|     |----------------------------|      |---------------------------         

 |                             |     |                            |      |                          |             

 |                             |     |       中转站               |      |   总线上子模块1          |             

 |          PC机               |     |                            |      |                          |             

 |                  |----------|     |---------         |---------|      |              |----------                                     |        |         |         |      |              |           | 

 |                  |          |<----| USART0 | <------ |  USART1 |<--------------------|    USART1 |     

 |                  |  USART0  |     |        |         |         |      |              |           |            

 |-----------------------------|     |----------------------------|      |--------------------------|    



  我的试验过程如下(波特率=1200、2400时):

    (A)、中转站模块有两排数码管

        第一排数码管显示接收到PC机请求包的“次数”(通过了CRC16校验)

        第二排数码管显示接收到到子模块1应答数据包的“字节数”,应该是8的倍数(“应答数据包”=8字节)

    (B)、子模块1有两排数码管

        第一排数码管显示接收到“中转站”转发的请求包的“次数”(通过了CRC16校验)

        第二排数码管显示子模块1发送“应答数据包”给“中转站”的次数。

     (C)、PC机用VB程序仿真

       制作一个按钮,每按一下,发送一帧“预置多个寄存器指令”的数据包,长度=249字节。



  经过大量试验,得出如下结果:



  (1)中转站模块每次都能够正确收到PC机发送的“预置多个寄存器指令” 

  (2)总线上的子模块1每次都能够正确收到“中转站”转发的“预置多个寄存器指令”数据包。 

  (3)子模块的USART1发送完成中断中,设置一个计数器,记录发送了多少次“应答数据包”。

       实验证明,子模块1只要接收到一帧请求包,就能够将应答包发送出去

  (4)中转站的USART1接收中断中,设置一个计数器,记录读取了子模块1应答数据包的字节数。(如果正确,一定是8的倍数) 

       第二排数码管应该显示8的倍数,实验证明,USART1接收中断中读取的字节数是随机的,每次接收的应答包的字节数

       却至少是50-80字节。  

  相同的程序,用波特率4800,却完全正确,到底是什么原因。

出0入296汤圆

发表于 2008-11-24 11:41:21 | 显示全部楼层
1、在1200低速模式下,先精简系统为一个PC,一个中转,一个子模块

看看中转站是否能收到应答信号。

2、逐渐提高PC机发送频率从5秒一次到1秒一次……观察通讯状况。

3、反馈以上的测试情况。好让大家继续分析……

出0入0汤圆

发表于 2008-11-22 12:04:23 | 显示全部楼层
不太懂你这个通讯方面的东西,你不妨用示波器看一下是子模块没有应答,还是应答了没有收到?用二分法找故障很快的。



你有多个子模块并联吗? 那要看相应的书籍资料,查找一下485连线的具体规定,匹配电阻什么的也要搞好。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-8 11:34

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

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