STM32F091RC UART接收功能仅返回数据包的最后一个字节,而不是完整的数据包



我一直在STM32F091RC板上工作,试图获得UART1和UART2工作。我尝试将8个字节从控制器发送到STM板。由于某些原因,我的功能只是显示数据包的最后一个字节。我的接收功能如下: -

uint8_t rxd[10];
void getChar (void) {
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) { // Check RXNE to 
//see if there is data
    for(j=0; j<8; j++) { 
        rxd[i] = (0xFF & (USART1->RDR));
    }

我在做什么错?有人可以指向我正确的方向吗?感谢您的时间。

UART->RDR寄存器没有缓冲区,它仅保留最后一个完全接收的字节。如果收到另一个字节,它将被覆盖。

您应确保每次在字节到达后的每次读取RDR中的值,以及在接收下一个字节之前。有3种基本方法可以做到。

  • 轮询

定期检查RXNE标志,并在设置时准确读取RDR 。重复直到拥有整个数据包。从RDR读取一个字节清除RXNE标志,等到再次设置为止,然后读取下一个字节。

  • 中断

CR1中设置RXNEIE位,并启用与NVIC中UART相对应的中断。每次收到字节时,中断处理程序都会被称为。刚开始读取RDR并将其存储在缓冲区中,因此处理程序可能非常简单。稍后,您可以添加错误检查和恢复。不要忘记声明每个变量中断处理程序触摸为 volatile

  • DMA

首先设置DMA频道(默认情况下,USART1映射到DMA1_Channel3,可以重新映射,检查其他人的参考手册(:

DMA1_Channel3->CPAR = (uint32_t)&USART1->RDR;
DMA1_Channel3->CMAR = (uint32_t)rxd;            // start of receive array
DMA1_Channel3->CNDTR = 8;                       // 8 bytes to receive
DMA1_Channel3->CCR = DMA_CCR_MINC | DMA_CCR_EN; // Memory increment, enable

然后设置串行端口,并在USART1->CR3中启用DMA接收。转移的结束在DMA1->ISR寄存器中发出信号,您可以在主程序中定期检查它,或在DMA1_Channel3->CCR中启用中断(以及NVIC(。您应该通过DMA1->IFCR清除中断标志,否则在启用时将无尽的中断。要启动另一个传输,请再次设置CNDTR寄存器。将DMA或中断处理程序触摸的所有变量声明为volatile

在这里:

for(j=0; j<8; j++) { 
  rxd[i] = (0xFF & (USART1->RDR));
}

您将j用作循环计数器,但在索引i下写给rxd,而不是j。您覆盖相同的字节8次。

另一件事是您等待设置USART_FLAG_RXNE标志,然后从RDR寄存器中阅读8次。当收到第一个字节时设置此标志,然后您阅读8次 - 您的阅读速度可能比发送数据的速度快得多。如果您想通过民意调查(这似乎是您的意图(进行的,那么您应该等待单独读取每个字节后设置的USART_FLAG_RXNE标志,因为此MCU中的Usart外围没有FIFO,并且只能为您保留单个字节读取(上述RDR寄存器(。

您的逻辑是完全错误的。

for(j=0; j<8; j++) 
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != SET); // wait for the data
    rxd[i] = (0xFF & (USART1->RDR));
}

最新更新