1

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

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));
    }

我究竟做错了什么?谁能指出我正确的方向?谢谢你的时间。

4

3 回答 3

1

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

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

  • 轮询

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

  • 打断

RXNEIE位 inCR1并启用对应于 UART in 的中断NVIC。每次接收到一个字节时都会调用中断处理程序。处理程序一开始可以非常简单,只需将其读取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

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

于 2018-03-29T18:15:03.550 回答
0

这里:

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

您用作循环计数器,但您在 index 下j写入,而不是. 您覆盖相同的字节 8 次。rxdij

另一件事是您等待USART_FLAG_RXNE设置标志,然后从RDR寄存器中读取 8 次。当接收到第一个字节时设置此标志,然后您读取它 8 次 - 您很可能读取速度比发送数据的速度快得多。如果您想通过轮询来做到这一点 - 这似乎是您的意图 - 您应该在分别读取每个字节后等待USART_FLAG_RXNE标志被设置,因为该 MCU 中的 USART 外设没有 FIFO,只能为您保存一个接收到的字节读(提到RDR的寄存器)。

于 2018-03-29T15:25:09.090 回答
0

你的逻辑是完全错误的。

for(j=0; j<8; j++) 
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != SET); // wait for the data
    rxd[i] = (0xFF & (USART1->RDR));
}
于 2018-03-29T20:55:59.583 回答