2011-01-28 60 views
3

因此,我开始在编写串行通信方案时出现一个重复出现的问题,而且这似乎是由于时序问题。我的嵌入式平台是Rabbit半导体公司的BL2600,在这种情况下,它正在与RS232设备通话。它向设备发出命令,设备将回复发送回BL2600,然后处理。什么使嵌入式设备上的RS232串行通信方案强大?

虽然我的问题是,当我发出命令,然后等待响应,我没有得到一个。但是,如果我在正确的位置设置断点,并单步执行代码,我通常会得到响应。我已将计算机置于BL2600和设备之间以监听RS232流(在看到最初的问题后),并且无论是否断点都会发送回复,但BL2600仅在其缓冲区中看到它如果我在解析代码的部分之前停止并尝试找到它的开始位。如果我断断续续地读完整个字符串,它就不会找到它。因此,这听起来像我没有足够的等待,所以现在只是为了荒谬,我已经设置了检查缓冲区的时间长达1秒(并且波特率为38400,它最好显示在那个窗口中),然而我仍然没有得到任何东西,除非我断断续续地单步执行。

下面是我的代码的显著部分:

//clear the buffers 
serCwrFlush(); 
while(serCwrUsed()) 
{ 
    ; 
} 
startwait = MS_TIMER; 
while((serCrdUsed() > 1) && (device_timeout_check < 1000)) 
{ 
    if (MS_TIMER < startwait) 
    {         // fix the rollover 
    device_timeout_check = MS_TIMER + (ULONG_MAX - startwait); 
    } 

    else 
    {         //set it like normal 
    device_timeout_check = MS_TIMER - startwait;  
    } 

    serCrdFlush(); 
} 
serCputs("mpcal=d\r");  //This is what requests the response from the device 
while(serCwrUsed()) 
{ 
    ; 
} 
startwait = MS_TIMER; 
while((serCrdUsed() < 11) && (device_timeout_check < 1000)) 
{ 
    if (MS_TIMER < startwait) 
    {      // fix the rollover 
    device_timeout_check = MS_TIMER + (ULONG_MAX - startwait); 
    } 
    else 
    {      //set it like normal 
    device_timeout_check = MS_TIMER - startwait;  
    } 
} 
//grab it 
temp=serCpeek(); 
i=0; 
     //It expects a response like "H0V0M00.0 /r" 
     //So I am looking for the first character. 
while((temp != 'H') && (i<100)) 
{ 
    serCgetc();  //breakpoint works here 
    temp=serCpeek(); 
    i++; 
} 
c=serCread(comp_cal_string,20, 20); //breakpoint doesn't work here 

我有一种感觉,我重新发明轮子,并且已经有人在我之前大概做到了这一点,至少在另一个平台上,所以它延迟了足够长的时间才能收到数据,但速度足够快以至于它实际上捕获了数据。

+0

你用示波器看过信号吗?没有适当的范围,你不能做这样的事情。如果你在UART线路上有毛刺等,你可能会得到错误的输入。在开始编码之前,始终先验证实际信号是否正常。 – Lundin 2011-01-30 20:22:30

回答

3

是不是有没有使用中断驱动的RS-232通信的原因?通常发生的情况是中断在RS-232电路的边缘转换时触发,并且您设置了一个中断服务例程(ISR)来处理它 - 这样,您总是可以处理信息,因为中断是硬件驱动的。从RS-232电路的脉冲可能足够短,以至于您的轮询循环(上图)只是看不到它。

如果你的BL2600是相同的设备如下所述:

http://ftp1.digi.com/support/documentation/019-0113_N.pdf

该手册列出了中断所有四个串行端口矢量设备上 - 见476页

上setVectIntern此外,较旧的RS-232电路仅支持16字节的内部缓冲区。如果您希望提高波特率,您可能需要使用BL2600上似乎存在的DMA功能。 (DMA功能应能自动将大块数据从内存传输到串口,反之亦然。)

2

鲁棒性的关键在于错误处理。

有两个循环可以超时,但在发生超时时不会有任何不同。有些函数的返回值没有检查错误。不处理错误的代码永远不会健壮。

超时循环在三个方面,可能会影响你的阅读破:

  • 之前它的值设置在循环内的device_timeout_check值测试。
  • MS_TIMER是不稳定的,可以在测试和使用时间之间进行更改,以计算device_timeout_check
  • 发生超时时不做任何事情。

要解决这些问题,首先改变startwait的声明,以避免翻车问题: unsigned long startwait;。然后实现超时循环是这样的:

startwait = MS_TIMER; 
do { 
    device_timeout_check = (MS_TIMER - startwait >= 1000); 
} while((serCrdUsed() > 1) && !device_timeout_check); 

if (device_timeout_check) { 
    /* Handle the timeout error here */ 
} 

如果device_timeout_check大于999时,达到你的代码,这将解决这个问题。

尝试检测第一个“H”字符的循环存在另一个问题。它之前的代码只能确保有11个可用的字符。检测循环运行100次,但不允许额外的时间接收字符。如果缓冲区中已经有11个或更多非'H'字符,它们将立即消耗,并且将等待'H'。

先等待'H'然后等待11个字符会更好。如果希望的输入前面有不需要的输入,这将解决问题。

0

我认为丁戈有他的第一个发现正确的答案。 device_timeout_check未初始化,至少在此处介绍的代码中。如果它没有被初始化,那只是在调用堆栈上留下的垃圾,所以它可能很容易超过1000.在这种情况下,while循环会立即通过(tsk tsk),而while循环等待'H'会通过100次迭代迅速运行(很可能)没有从串口拉。

顺便说一句,为什么100?一旦你清空缓冲区,那些额外的读取很可能会发生得如此之快,以至于他们不会找到任何新的东西。

这也很好地解释了调试器的行为。你的延迟循环从来没有真正拖延过任何事情,当你在serCgetc()中放置一个断点时,你允许串口赶上程序。

一个简单的方法来查看是否真的是这种情况是在尝试从串口读取数据之前设置某种外部通知。闪烁LED或通过串口发送“收到消息”数据包。然后使用便宜的O型示波器,您应该在接收数据之前轻松看到“收到消息”数据包(或LED闪烁)。

这些查看和读取函数不返回错误状态,因为它们返回数据,但它们可以很容易地放入包装中,至少检查FIFO中的奇偶校验错误或字节,并将数据返回到指针中,可以退货。像这样的东西

STATUS myCpeek(unsigned char *data) 
{ 
    if (0 == serCrdUsed()) 
    return ERROR_NO_DATA; 
    *data = serCpeek(); 
    if (serCParityError()) //Just guessing at a function name here 
    { 
    return ERROR_PARITY_BAD; 
    } 
    return OK; 
} 

或类似的东西。

相关问题