Arm STM32f091rc UART接收函数只返回数据包的最后一个字节,而不是完整的数据包

Arm STM32f091rc UART接收函数只返回数据包的最后一个字节,而不是完整的数据包,arm,stm32,uart,cmsis,stm32f0,Arm,Stm32,Uart,Cmsis,Stm32f0,我一直在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;

我一直在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));
    }
uint8_t rxd[10];
void getChar(void){
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET){//将RXNE检查为
//看看是否有数据
对于(j=0;jRDR));
}
我做错了什么?谁能告诉我正确的方向吗?谢谢你的时间。

这里:

for(j=0; j<8; j++) { 
  rxd[i] = (0xFF & (USART1->RDR));
}
for(j=0;jRDR));
}
使用
j
作为循环计数器,但在索引
i
下写入
rxd
,而不是
j
。您将覆盖同一字节8次


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

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

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

  • 轮询
定期检查
RXNE
标志,设置后准确读取
RDR
。重复此操作,直到获得整个数据包。从
RDR
读取一个字节将清除
RXNE
标志,等待再次设置后再读取下一个字节

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

  • DMA
首先设置DMA通道(
USART1
默认映射到
DMA1\U通道3
,可以重新映射,请查看参考手册了解其他信息):


然后设置串行端口,并在
USART1->CR3
中启用DMA接收。传输结束在
DMA1->ISR
寄存器中发出信号,您可以在主程序中定期检查,或在
DMA1\u通道3->CCR
中启用中断(以及在
NVIC
)。您应该通过
DMA1->IFCR
清除中断标志,否则启用时会出现无休止的中断。要开始另一次传输,请再次设置
CNDTR
寄存器。将DMA或中断处理程序涉及的所有变量声明为volatile,即逻辑完全错误

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

感谢您提供的宝贵信息。因此,现在我得出结论,只有当接收到一个字节并且读取RDR寄存器清除该标志时,才会设置RXNE标志。现在我将逻辑更改为:-uint8_t getChar(void){if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET){//检查RXNE是否有数据返回((USART1->RDR)&(0xFF));}否则{return 0xFF;}--这是我的函数getChar(),如果我在while(1)中连续运行它,在返回值时,它应该清除标志RXNE,对吗?然后我想我必须在返回值之前存储字节?要么将值存储在函数中并返回错误/成功代码,要么在函数中使用整数返回类型,在未收到任何内容时返回负值。后者类似于
getchar()
库函数;对于(k=0;kRDR)和(0x00FF));//将RDR值放入rxdata[0],准确读取一次}否则{//如果未设置标志UartTransmitPacket(“标志重置”,sizeof(“标志重置”);//打印标志已重置}}每次迭代后,我都尝试打印rxdata[0]的值。还是不明白。是的,我错写了“I”而不是“j”。谢谢我将尝试使逻辑正确:)
for(j=0; j<8; j++) 
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != SET); // wait for the data
    rxd[i] = (0xFF & (USART1->RDR));
}