c - 如何使用 UART 接收数据进行进一步处理,而不仅仅是在嵌入式 C 中回显?
问题描述
这是我的测试环境中的代码。它只是将输入的数据回复(回显)到通过串行端口连接的终端应用程序。到目前为止,一切都很好。
现在,我需要根据要求/协议使用该数据和流程。但是,我正在努力UART0Buffer
按预期使用数据。(该变量UART0Buffer
填充在 UART 中断中)
我从终端发送例如“7E0007AA010203040506CC”,代码出于某种原因分四步将其回复给终端应用程序;
1 由进程 #1
37
2 按进程 #2
00
3 按流程 #1
30 30 30 37 41 41 30 31 30 32 30 33 30 34 30
4 按流程 #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--;
}
}
}
编辑: 由于老兄已经解释了“进程#2”的错误使用,请忽略它。它以某种方式破坏了事物。但是,我的问题仍然存在。虽然我可以通过“进程#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。如果帧协议包括帧校验序列,则该层执行校验。该层不尝试解释帧的含义,而只是形成完整的帧以供下一层使用。
如果您的串行消息足够大以跨越多个帧,那么您可能在这里有一个层将帧拼接成消息。或者,如果每条消息都包含在单个帧中,那么您可能不需要这一层。
顶层是实际解释消息并执行适当操作的层。该层对 UART 或帧分隔符一无所知,因为所有这些知识都由较低层封装。
这个答案有更多提示,嵌入式 C UART 约定
推荐阅读
- python - 从订单簿绘制热图(熊猫数据框)
- java - 在 Java 中给出谷坐标的区域中查找 RGB 平均值
- javascript - 将两个数组合并为一个
- c - 如何解决 codechef 中的运行时错误“SIGSEGV”?
- guidewire - 在guidewire pcf中表示财务金额的原子小部件?
- java - “Jedis NOAUTH Authentication required”——Java 16 升级后的垃圾邮件
- ethereum - Rinkeby 智能合约
- javascript - 我在 vue 中做了一个计算器,我希望它能够输入最后一个运算符并更改前一个(js 有问题)
- html - 将功能电子表格嵌入博客
- android - Flutter中CustomScrollView的正确和有效使用是什么