【前言】
串口作为MCU最常用的外设,是掌握一款单片机最基本的技能之一。串口收接可以有多种形势,这一篇讨论如何使用接收中断+空闲中断来实现不定长接收。
【实验环境】
Mini-F5265-OB开发板。
【串口的选择】
Mini-F5265-OB拥有多达5个UART以及一个低功耗的LUART。UART最快速度可以达到7Mbps。本篇选用UART3作为试验串口,因此他通过MM32F3273G6P的DAP-LINK连接,这样就不需要外接USB转TTL来试验。
【串口IO选择】
根据开发板原理图,选用PC10、PC11来做为UART3的TX、RX的IO,其原理图如下:
【串口初始化】
串口初始化代码如下:
/* DEBUG UART define begin *************************************************/ #define DEBUG_UART UART3 #define DEBUG_UART_TX_PORT GPIOC #define DEBUG_UART_TX_PIN_SOURC GPIO_PinSource10 #define DEBUG_UART_RCC RCC_APB1Periph_UART3 #define DEBUG_UART_TX_GPIO_RCC RCC_AHBPeriph_GPIOC #define DEBUG_UART_GPIO_AF GPIO_AF_7 #define DEBUG_UART_TX_PIN GPIO_Pin_10 #define DEBUG_UART_RX_PORT GPIOC #define DEBUG_UART_RX_PIN_SOURC GPIO_PinSource11 #define DEBUG_UART_RX_GPIO_RCC RCC_AHBPeriph_GPIOC #define DEBUG_UART_RX_PIN GPIO_Pin_11 #define DEBUG_UART_IRQn UART3_IRQn /* DEBUG UART define end *************************************************/
宏定中,根据用户手册,使用宏定义了UART3所使用的IO、端口、时钟、中断号等。
/*********************************************************************************************************************** * @brief Initialize console for printf * @note none * @param Baudrate : UART3 communication baudrate * @retval none *********************************************************************************************************************/ void PLATFORM_InitConsole(uint32_t Baudrate) { GPIO_InitTypeDef GPIO_InitStruct; UART_InitTypeDef UART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB1PeriphClockCmd(DEBUG_UART_RCC, ENABLE); UART_StructInit(&UART_InitStruct); UART_InitStruct.BaudRate = Baudrate; UART_InitStruct.WordLength = UART_WordLength_8b; UART_InitStruct.StopBits = UART_StopBits_1; UART_InitStruct.Parity = UART_Parity_No; UART_InitStruct.HWFlowControl = UART_HWFlowControl_None; UART_InitStruct.Mode = UART_Mode_Tx | UART_Mode_Rx;; UART_Init(DEBUG_UART, &UART_InitStruct); UART_ITConfig(DEBUG_UART, UART_IT_RX, ENABLE); UART_ITConfig(DEBUG_UART, UART_IT_RXIDLE, ENABLE); RCC_AHBPeriphClockCmd(DEBUG_UART_TX_GPIO_RCC, ENABLE); GPIO_PinAFConfig(DEBUG_UART_TX_PORT, DEBUG_UART_TX_PIN_SOURC, DEBUG_UART_GPIO_AF); GPIO_PinAFConfig(DEBUG_UART_RX_PORT, DEBUG_UART_RX_PIN_SOURC, DEBUG_UART_GPIO_AF); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = DEBUG_UART_TX_PIN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(DEBUG_UART_TX_PORT, &GPIO_InitStruct); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = DEBUG_UART_RX_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(DEBUG_UART_RX_PORT, &GPIO_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = DEBUG_UART_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); UART_ClearITPendingBit(UART3, 0x7FF); UART_Cmd(DEBUG_UART, ENABLE); }
在初始化代码中,首先打开UART的时钟,然后配置波特率、数据宽度,停止位,等。然后配接收中断、空闲中断。接口配置IO,其中TX为输出模式,RX为中断输入模式,最后开启中断。
【中断回调】
/*********************************************************************************************************************** * @brief This function handles UART1 Handler * @note none * @param none * @retval none *********************************************************************************************************************/ void UART3_IRQHandler(void) { uint8_t i = 0; if (SET == UART_GetITStatus(UART3, UART_IT_RX)) { UART_RxBuffer[UART_RxLength++] = UART_ReceiveData(UART3); UART_ClearITPendingBit(UART3, UART_IT_RX); } if (SET == UART_GetITStatus(UART3, UART_IT_RXIDLE)) { UART_ClearITPendingBit(UART3, UART_IT_RXIDLE); for (i = 0; i < UART_RxLength; i++) { UART_SendData(UART3, UART_RxBuffer[i]); while (RESET == UART_GetFlagStatus(UART3, UART_FLAG_TXC)) { } } UART_RxLength = 0; } }
在中断回调函数中,如果中断进入的是接收中断,则把接收的字符串存入缓冲区中,如果是空闲中断,则把接收到的内容回传出去。
【整体思路】
在本次实验中,开启的UART3的RX中断、空闲中断,当进入的是RX中断时,把接收数据并存入缓冲区,如果产生空闲中断,则说明数据传输结束。最后把接收到的数据回传,同时重置接收标志位。
【实验现象】
【总结】
灵动的串口设计非常之优秀!