我一直在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));
}