Uart 接收到正确的字节,但顺序混乱

Posted

技术标签:

【中文标题】Uart 接收到正确的字节,但顺序混乱【英文标题】:Uart receives correct Bytes but in chaotic order 【发布时间】:2017-03-23 12:59:18 【问题描述】:

使用 Atmel studio 7,搭配 STK600 和 32UC3C MCU

我正在为此烦恼。 我每 5 秒通过 UART 发送一次可变大小的字符串。该字符串由一个作为操作码的字母组成,然后是两个字符,它们告诉后面的数据字符串的长度(没有零,任何这些字符串的末尾都不会有零)。在大多数情况下,字符串大小为 3 个字符,因为它没有数据(“p00”)。

经过调查,我发现应该是“p00”实际上是“0p0”或“00p”或(仅在重新启动微型“p00”后第一次尝试)。我在调试器的内存视图中查找了它。然后我启动 hTerm 并确认数据实际上是“p00”。所以过了一会儿,hTerm 向我显示“p00p00p00p00p00p00p00...”,而我的循环 uart 缓冲区的内存显示为“p000p000p0p000p0p000p0p0...”

编辑:实际上“0p0”和“00p”是交替的。

波特率为 9600。过去我只发送单个字母。所以一切都运行良好。

这是接收器中断的代码: 我尝试了不同的代码变体,它们都以不同的方式做同样的事情。但他们都表现出完全相同的行为。

lastWebCMDWritePtr 是 uint8_t* 类型,lastWebCMDRingstartPtr 也是。 lastWebCMDRingRXLen 是一个 uint8_t 类型。

__attribute__((__interrupt__))
void UartISR_forWebserver()

    *(lastWebCMDWritePtr++) = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
    lastWebCMDRingRXLen++;
    if(lastWebCMDWritePtr - lastWebCMDRingstartPtr > lastWebCMDRingBufferSIZE)
    
        lastWebCMDWritePtr = lastWebCMDRingstartPtr;
    
// Variation 2:
//  advanceFifo((uint8_t)((&AVR32_USART0)->rhr & 0x1ff));

// Variation 3:
//  if(usart_read_char(&AVR32_USART0, getReadPointer()) == USART_RX_ERROR)
//  
//      usart_reset_status(&AVR32_USART0);
//  
//      

;

我欢迎您的任何想法和建议。

向某某致敬

附:我放了 Atmel studio 标签,以防这与 AS 的无数调试器错误有关。

【问题讨论】:

if(lastWebCMDWritePtr - lastWebCMDRingstartPtr > lastWebCMDRingBufferSIZE) ----> if(lastWebCMDWritePtr - lastWebCMDRingstartPtr > lastWebCMDRingBufferSIZE-1) 谢谢,但我猜这不是我要寻找的错误... ;) 嗯,你试过了吗?您的代码访问循环缓冲区超出了 1 的范围,因此从基地址开始的队列将被“移动”一个值。 发送的 strings 没有终止标识符,可以是空字符或'\n' 等。接收者不知道其中一个 string开始,另一个 string 结束。 Minor:@LPs的好主意可以写成if(lastWebCMDWritePtr - lastWebCMDRingstartPtr >= lastWebCMDRingBufferSIZE) 【参考方案1】:

要获得完整的图片,您必须显示 lastWebCMDWritePtrlastWebCMDRingRXLenlastWebCMDRingstartPtrlastWebCMDRingBufferSIZE 的位置和方式在其他地方使用(在消费端)

另外我会首先尝试一个更简单的 ISR,它不依赖于其他软件模块来排除硬件响应。注册处理问题。

方法:

#define USART_DEBUG
#define DEBUG_BUF_SIZE 30

__attribute__((__interrupt__))
void UartISR_forWebserver()
 
  uint8_t rec_byte;
#ifdef USART_DEBUG  
  static volatile uint8_t usart_debug_buf[DEBUG_BUF_SIZE]; //circular buffer for debugging
  static volatile int usart_debug_buf_index = 0;
#endif      

  rec_byte = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);

#ifdef USART_DEBUG  
  usart_debug_buf_index = usart_debug_buf_index % DEBUG_BUF_SIZE; 
  usart_debug_buf[usart_debug_buf_index] = rec_byte;
  usart_debug_buf_index++

  if (!(usart_debug_buf_index < DEBUG_BUF_SIZE)) 
    usart_debug_buf_index = 0; //candidate for a breakpoint to see what happened in the past
  
#endif
  //uart_recfifo_enqueue(rec_byte);

;

【讨论】:

我现在才发现,是硬件故障。用新的 MCU 切换后,它按预期工作。我希望我早点想到这一点。

以上是关于Uart 接收到正确的字节,但顺序混乱的主要内容,如果未能解决你的问题,请参考以下文章

AVR UART 接收到错误的字节

TCP可靠传输机制

swift for循环数据顺序不正确

解析时限 UART 数据

uart接收和发送数据

导入到sql server后,数据行顺序混乱