c - 如何使用 UART 接收数据进行进一步处理,而不仅仅是在嵌入式 C 中回显?

标签 c embedded

这是我的测试环境中的代码。它只是将输入的数据回复(回显)到通过串行端口连接的终端应用程序。到目前为止一切顺利。

现在,我需要根据要求/协议(protocol)使用该数据和流程。 但是,我正在努力按照我的预期消耗数据UART0Buffer。 (变量 UART0Buffer 填充在 UART 中断中)

我发送例如来自终端的“7E0007AA010203040506CC” 由于某种原因,代码按顺序分四步将其回复给终端应用程序;

1 by Process #1

37

2 by Process #2

00

3 by Process #1

30 30 30 37 41 41 30 31 30 32 30 33 30 34 30

4 by Process #2

A1

您还可以注意到,回复(回显)的数据与我从终端发送的数据不同。

此外,如果我完全删除“Process #2”行, 我可以获得正确的回声;

37 45 30 30 30 37 41 41 30 31 30 32 30 33 30 34 30 35 30 36 43 43

我在这里真正缺少什么?

int main()
{
    SystemInit();       /* Clock and PLL configuration */   
    UARTInit(0, 57600); /* baud rate setting */

    while(1)
    {
        if ( UART0Count != 0 )
        {
            LPC_UART0->IER = IER_THRE | IER_RLS;            /* Disable RBR */

            UARTSend( 0, (uint8_t *)UART0Buffer, UART0Count ); // Process #1

            UART0Count = 0;

// I need to call a function here in order to process data in UART0Buffer
// like checking/using STX, CHKSUM and DATA.

            // A test, if I can manage to use the data in pieces
            UARTSend( 0, (uint8_t *)UART0Buffer[0], 1); // Process #2

            LPC_UART0->IER = IER_THRE | IER_RLS | IER_RBR;  /* Re-enable RBR */
        }
    }
}

void UARTSend( uint32_t portNum, uint8_t *BufferPtr, uint32_t Length )
{
  if ( portNum == 0 )
  {
    while ( Length != 0 )
    {
      /* THRE status, contain valid data */
      while ( !(UART0TxEmpty & 0x01) ); 
      LPC_UART0->THR = *BufferPtr;
      UART0TxEmpty = 0; /* not empty in the THR until it shifts out */
      BufferPtr++;
      Length--;
    }
  }
}

编辑: 由于老兄已经解释了“Process #2”的错误使用,请忽略它。它以某种方式破坏了东西。但是,我的问题仍然存在。虽然我可以通过“Process #1”得到回显,但我无法读取和使用数据!?!任何指示将不胜感激。

编辑:

接收:

void UART0_IRQHandler (void) 
{
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;

  IIRValue = LPC_UART0->IIR;

  IIRValue >>= 1;           /* skip pending bit in IIR */
  IIRValue &= 0x07;         /* check bit 1~3, interrupt identification */
  if ( IIRValue == IIR_RLS )        /* Receive Line Status */
  {
    LSRValue = LPC_UART0->LSR;
    /* Receive Line Status */
    if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
    {
      /* There are errors or break interrupt */
      /* Read LSR will clear the interrupt */
      UART0Status = LSRValue;
      Dummy = LPC_UART0->RBR;       /* Dummy read on RX to clear 
                            interrupt, then bail out */
      return;
    }
    if ( LSRValue & LSR_RDR )   /* Receive Data Ready */            
    {
      /* If no error on RLS, normal ready, save into the data buffer. */
      /* Note: read RBR will clear the interrupt */
      UART0Buffer[UART0Count] = LPC_UART0->RBR;
      UART0Count++;
      if ( UART0Count == BUFSIZE )
      {
        UART0Count = 0;     /* buffer overflow */
      } 
    }
  }
  else if ( IIRValue == IIR_RDA )   /* Receive Data Available */
  {
    /* Receive Data Available */
    UART0Buffer[UART0Count] = LPC_UART0->RBR;
    UART0Count++;
    if ( UART0Count == BUFSIZE )
    {
      UART0Count = 0;       /* buffer overflow */
    }
  }
  else if ( IIRValue == IIR_CTI )   /* Character timeout indicator */
  {
    /* Character Time-out indicator */
    UART0Status |= 0x100;       /* Bit 9 as the CTI error */
  }
  else if ( IIRValue == IIR_THRE )  /* THRE, transmit holding register empty */
  {
    /* THRE interrupt */
    LSRValue = LPC_UART0->LSR;      /* Check status in the LSR to see if
                                    valid data in U0THR or not */
    if ( LSRValue & LSR_THRE )
    {
      UART0TxEmpty = 1;
    }
    else
    {
      UART0TxEmpty = 0;
    }
  }

}

最佳答案

您基本上是在设计一个串行消息驱动程序。将设计分为几层。

最底层是 UART 驱动程序,用于将字符移入和移出硬件 UART。 UART 驱动程序封装了有关如何连接 UART 硬件的所有知识。该层不知道帧或消息,只知道字符。当发送字符可用且 UART 准备发送时,它将发送字符复制到 TX 寄存器。当 UART RX 寄存器可用时,它会复制接收到的字符。这些操作通常在 UART 中断服务程序中实现。通常,RAM 循环缓冲区用于存储 TX 和 RX 字符。

下一层是框架字符。该层负责识别界定帧的字符。该层封装了所有关于字符的知识被分隔成帧。这通常被实现为一个状态机,当 RX 缓冲区中有可用字符时,该状态机会被重复调用。状态机从 RX 缓冲区获取下一个字符,并根据当前状态对其进行处理。状态可以包括例如 waiting_for_start_of_frame、copying_body_of_frame 和 waiting_for_end_of_frame。如果帧协议(protocol)包括帧检查序列,则该层执行检查。该层不会尝试解释帧的含义,而只是形成完整的帧以供下一层使用。

如果您的串行消息足够大,可以跨越多个帧,那么您可能在这里有一个层将帧缝合在一起形成消息。或者,如果每条消息都包含在单个框架内,那么您可能不需要此层。

顶层是实际解释消息并执行适当操作的层。该层不知道有关 UART 或帧定界符的任何信息,因为所有这些知识都由较低层封装。

这个答案有更多提示,Embedded C UART conventions

关于c - 如何使用 UART 接收数据进行进一步处理,而不仅仅是在嵌入式 C 中回显?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58972665/

相关文章:

c - Microsoft 编译器和 GNU 编译器在输出可执行文件大小方面的差异

c - 全局变量是否被视为语句?

c - C 中的指针和数组

c - printf() 导致乱码

python - pyserial 2.7,python 3.3,发送回车

C - 应用于矩阵的函数指针。段错误

c++ - 将调试语句重定向到 stderr 时出现奇怪的情况

c++ - 如何释放 Kiss FFT 分配的内存?

将 uint8 数组转换为结构数组而不是 memcpy

c - 无法将字符串写入 *char[]