ST意法半导体
直播中

发生的方式

9年用户 1325经验值
擅长:处理器/DSP
私信 关注
[问答]

如何接收UART数组缓冲区的长度呢?有何解决方案?

STM32F746 Disco,UART1 连接到集成 ST-Link,Windows 10,STM32CubeIDE 1.7.0,PC 上的 Putty
我正在用 C 语言在寄存器上编写自己的 UART 实现,这里有数据表和参考手册。我发送一个字符或一组字符没有问题,我接收一个字符也没有问题(这意味着我已经设置好了)。但是我无法接收字符数组,而且我不明白为什么,因为从算法上讲我认为我做对了(在有人指出错误之前总是如此)。阅读参考手册已经好几个小时了。
这是一个最基本的驱动程序,没有中断,没有噪音标志,使用了超限标志,只是学习的东西。基本发送接收。波特率 9600。
现在,我的接收器方法的特点如下:
  • 该方法接收一个数组指针和数组长度作为两个参数
  • 在通话中,它启用接收器。
  • 它无限期地等待接收传输的开始
  • 当新值进来时,它会填满(应该填满)缓冲区数组。
  • 如果在缓冲区数组满之前传输结束,则检测到它并且不等待更多数据,禁用接收器并返回。
  • 如果缓冲区数组已满,但传输仍在继续,只需等待传输结束,然后禁用接收器并返回。
代码:
  • void uart1_receiveArray(uint8_t *arraypointer, uint32_t length) {
  •         USART1->CR1 |= USART_CR1_RE; //USART Receiver enabled, line idle
  •         uint32_t pointer = 0;
  •         while ((((USART1->ISR) >> USART_ISR_RXNE_Pos) & 1U) == 0);         //wait while first data comes from shift register
  •         arraypointer[pointer] = USART1->RDR;
  •         pointer++;
  •         while ((((USART1->ISR >> USART_ISR_IDLE_Pos) & 1U) == 0) && (pointer < length)) { //if line not idle and buffer array not full
  •                 while ((((USART1->ISR) >> USART_ISR_RXNE_Pos) & 1U) == 0);         //wait while data comes from shift register
  •                 arraypointer[pointer] = USART1->RDR;
  •                 pointer++;
  •         }
  •         while (((USART1->ISR >> USART_ISR_IDLE_Pos) & 1U) == 0); //if buffer is full, but transmission is still going, wait for it to end
  •         USART1->CR1 &= ~USART_CR1_RE; //Receiver disabled
  • }
我在 Putty 中输入要发送的内容。数组缓冲区的长度为 8,我输入了一些更短的内容。
在调试中,我在所提供代码的第 13 行设置了一个断点并查看了 UART1 ISR。它的内容是:
  • 10000000000000011111000
所以所有与接收相关的有趣位。它发出溢出错误、空闲线(好吧,这是有道理的)和读取数据寄存器 (RDR) 不为空的信号。同时,我的“指针”变量的值为 1。就好像传输在“While Line Not Idle”循环之前发送了所有 4 (2 3 5 6) 个字节。
谁能提出解决方案?如何接收 UP TO 缓冲区长度?


回帖(1)

付雯瑶

2022-12-14 09:32:06
找到解决方案!我使用 Receiver Timeout 重写了整个东西!
编辑(错误修正)


  • void uart1_receiveArray(uint8_t *arraypointer, uint32_t length) {
  •         uint8_t *currentpointer = arraypointer;
  •         for (uint32_t k = 0; k < length; k++) { //fill the buffer with nulls so that it doesn't retain data from previous transmissions
  •                 *(arraypointer + k) = '';
  •         }
  •         while (!(USART1->ISR & USART_ISR_RXNE)); //wait indefinitely for the beginning of the transmission
  •         USART1->ICR |= USART_ICR_RTOCF; //make sure receiver timeout flag is cleared
  •         while (!(USART1->ISR & USART_ISR_RTOF)) { //while not receiver timeout
  •                 if (((USART1->ISR & USART_ISR_RXNE)) && (currentpointer < arraypointer + length)) { //if buffer is not full yet and there is new data
  •                         *currentpointer = USART1->RDR;
  •                         currentpointer++;
  •                 }
  •         }
  •         USART1->ICR |= USART_ICR_RTOCF; //when receiver timed out and we're done, clear the flag
  • }

使用大小为 8 的缓冲区进行测试。与长度为 1、3-7、8 和 10 的传输完美配合(仅保留前 8 个字符)。较短的超时(0 位)会把整个事情搞砸(有道理)。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分