我在通过USART接收数据时遇到了一些麻烦。我实际上想要实现的目标是,我可以通过USART接收一个没有特定长度(只有最大可能长度)的命令。因此,我使用中断例程来检查收到的每个字符,但是我仍然无法实现我想要的功能。每当我收到一个新字符时,都会调用该例程,但是由于某种原因HAL_UART_Receive_IT(&huart1,rx_data,buff_size_rx)不能实时升级,因此当我检查rx_data [pointer]时看不到接收到的字符,但是稍后它在rx_data缓冲区中。
到目前为止,我有:
int pointer =0;
...
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if ( USART1->ISR & UART_IT_TXE) {
}
if ( USART1->ISR & UART_IT_RXNE) {
HAL_UART_Receive_IT(&huart1,rx_data,buff_size_rx);
if(rx_data[pointer]=='\0') {
pointer=0;
readCommand(rx_data);
clearBuffer(rx_data,buff_size_rx);
} else {
pointer++;
if(pointer>=buff_size_rx) {
pointer=0;
}
}
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
Run Code Online (Sandbox Code Playgroud)
HAL_UART_Receive_IT()并不意味着从中断处理程序中调用,而是通过中断启动接收固定数量的字节。
一个可能的解决方法是在 HAL_UART_IRQHandler()完成后检查输入缓冲区,即在本/* USER CODE BEGIN USART1_IRQn 1 */节中。处理命令后,可以将其重置pRxBuffPtr并RxXferCount在句柄结构中将其重置为原始值,以从缓冲区的开头再次开始。
另一个可怕的解决方法是调用HAL_UART_Receive_IT()缓冲区大小为1的缓冲区,并设置一个HAL_UART_RxCpltCallback()处理程序,每次检查接收到的字节,并HAL_UART_Receive_IT()在必要时再次调用。
正如PeterJ和其他人(总是)建议的那样,当然可以在没有HAL的情况下进行操作。
UART->BRR根据参考手册计算值,或从hal复制相关代码。UART->CR1=USART_CR1_RE|USART_CR1_TE|USART_CR1_UE|USART_CR1_RXNEIE;现在,您正在中断。UART->SR一个临时变量,然后进行检查。UART->DR当有接收到的字节等待时读取,否则(稍后)进行错误处理。在嵌入式应用中,中断响应和处理时间通常很关键,而HAL却浪费了很多时间。
普通的 HAL 库对于连续接收或不同长度的命令没有用。
如果您已经安装了完整的HAL包,你可以看看的例子大号流大号埃维尔接口。
Projects\STM32F411RE-Nucleo\Examples_LL\USART\USART_Communication_Rx_IT_Continuous
Run Code Online (Sandbox Code Playgroud)
主要是将您设置为连续接收:
Projects\STM32F411RE-Nucleo\Examples_LL\USART\USART_Communication_Rx_IT_Continuous
Run Code Online (Sandbox Code Playgroud)
USART IT 处理程序应该看起来像
void Configure_USART(void) {
/* (1) Enable GPIO clock and configures the USART pins *********************/
/* Enable the peripheral clock of GPIO Port */
USARTx_GPIO_CLK_ENABLE();
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_MODE_ALTERNATE);
USARTx_SET_TX_GPIO_AF();
LL_GPIO_SetPinSpeed(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_MODE_ALTERNATE);
USARTx_SET_RX_GPIO_AF();
LL_GPIO_SetPinSpeed(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_PULL_UP);
/* (2) NVIC Configuration for USART interrupts */
/* - Set priority for USARTx_IRQn */
/* - Enable USARTx_IRQn */
NVIC_SetPriority(USARTx_IRQn, 0);
NVIC_EnableIRQ(USARTx_IRQn);
/* (3) Enable USART peripheral clock and clock source ***********************/
USARTx_CLK_ENABLE();
/* (4) Configure USART functional parameters ********************************/
/* TX/RX direction */
LL_USART_SetTransferDirection(USARTx_INSTANCE, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(USARTx_INSTANCE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
/* No Hardware Flow control */
/* Reset value is LL_USART_HWCONTROL_NONE */
// LL_USART_SetHWFlowCtrl(USARTx_INSTANCE, LL_USART_HWCONTROL_NONE);
/* Oversampling by 16 */
/* Reset value is LL_USART_OVERSAMPLING_16 */
// LL_USART_SetOverSampling(USARTx_INSTANCE, LL_USART_OVERSAMPLING_16);
/* Set Baudrate to 115200 using APB frequency set to 100000000/APB_Div Hz */
/* Frequency available for USART peripheral can also be calculated through LL RCC macro */
/* Ex :
Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or
LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance
In this example, Peripheral Clock is expected to be equal to
100000000/APB_Div Hz => equal to SystemCoreClock/APB_Div
*/
LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock/APB_Div, LL_USART_OVERSAMPLING_16, 115200);
/* (5) Enable USART *********************************************************/
LL_USART_Enable(USARTx_INSTANCE);
}
Run Code Online (Sandbox Code Playgroud)
最后要设置的是回调
void USART_CharReception_Callback(void);
Run Code Online (Sandbox Code Playgroud)
您可以将字节放入缓冲区并在主循环中或您想要的地方处理它。
| 归档时间: |
|
| 查看次数: |
30443 次 |
| 最近记录: |