1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
概述
本篇将以STM32F407VET6芯片的USART1为例,总结STM32CubeIDE平台关于UART通信的**主动收发(无中断收发)和被动收发(中断收发)**流程。应当注意,对于USART的常规应用,应当使用HAL库中的UART API. UART初始化 UART的完整初始化流程为: 1.UART参数初始化 (1).UART句柄配置 (2).UART初始化结构体配置 (3).UART使能 2.UART时钟初始化(置于UART_Msp初始化函数) 3.UART_GPIO初始化(置于UART_Msp初始化函数) (1).GPIO时钟初始化 (2).GPIO参数初始化 4.UART中断配置(置于UART_Msp初始化函数) (1).NVIC总中断优先级配置 (2).NVIC使能总中断 (3).UART开启分中断(发送中断/接收中断) UART参数初始化 UART句柄 UART句柄是UART初始化和具体操作中最重要的参数,应当声明为工程级别的全局变量。HAL库中采用 发送缓冲区 和 接收缓冲区 一次发送/接受 一个或多个字节 的方式提高数据吞吐效率。 typedef struct __UART_HandleTypeDef { /* UART实例,取值有 USART1,USART2,USART3,UART4,UART5... */ USART_TypeDef *Instance; /* UART初始化结构体 */ UART_InitTypeDef Init; /* UART 本次 发送缓冲区指针 */ uint8_t *pTxBuffPtr; /* UART 本次 发送缓冲区字节数 */ uint16_t TxXferSize; /* UART 本次 已发送字节数,用于查询发送进度 */ __IO uint16_t TxXferCount; /* UART 本次 接收缓冲区指针 */ uint8_t *pRxBuffPtr; /* UART 本次 接收缓冲区字节数 */ uint16_t RxXferSize; /* UART 本次 已接收字节数,用于查询接收进度 */ __IO uint16_t RxXferCount; /* DMA发送缓冲区指针 */ DMA_HandleTypeDef *hdmatx; /* DMA接收缓冲区指针 */ DMA_HandleTypeDef *hdmarx; /* UART同步锁状态,取值有 HAL_UNLOCKED / HAL_LOCKED */ HAL_LockTypeDef Lock; /* UART发送状态 */ __IO HAL_UART_StateTypeDef gState; /* UART接收状态 */ __IO HAL_UART_StateTypeDef RxState; /* UART错误码 */ __IO uint32_t ErrorCode; } UART_HandleTypeDef; UART初始化结构体 typedef struct { /* 波特率 */ uint32_t BaudRate; /* 帧字长,一般取 UART_WORDLENGTH_8B */ uint32_t WordLength; /* 停止位,一般取 UART_STOPBITS_1 */ uint32_t StopBits; /* 奇偶校验位,一般取 UART_PARITY_NONE */ uint32_t Parity; /* UART收发模式,取值有 UART_MODE_RX - 发送模式 UART_MODE_TX - 接收模式 UART_MODE_TX_RX - 发送_接收全双工模式 */ uint32_t Mode; /* 硬件流控制,一般取 UART_HWCONTROL_NONE */ uint32_t HwFlowCtl; /* 过采样倍率,一般取 UART_OVERSAMPLING_16 */ uint32_t OverSampling; } UART_InitTypeDef; UART参数初始化函数 /* UART参数初始化 参数:huart - UART句柄指针 返回: HAL_ERROR - huart = NULL 时,将返回 HAL_ERROR HAL_OK - UART初始化成功 */ HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); UART参数初始化实例: void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 使用 UART API 而不是 USART API if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } UART时钟初始化 /* UART时钟使能应置于 Msp初始化函数 中 */ /* 宏函数,USART时钟使能 */ __HAL_RCC_USART1_CLK_ENABLE(); /* 宏函数,USART时钟失能 */ __HAL_RCC_USART1_CLK_DISABLE(); /* 宏函数,UART时钟使能 */ __HAL_RCC_UART4_CLK_ENABLE(); /* 宏函数,UART时钟失能 */ __HAL_RCC_UART4_CLK_DISABLE(); UART_GPIO初始化 /* UART_GPIO初始化应当置于 Msp初始化函数 中 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO时钟初始化 */ __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = USART1_TX_Pin|USART1_RX_Pin; /* 复用推挽输出模式 */ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; /* 上拉电阻 */ GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 复用映射 */ GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); UART中断配置 /* UART中断配置应置于 Msp初始化函数 中 */ /* UART总中断优先级配置 */ HAL_NVIC_SetPriority(USART1_IRQn,0,0); /* UART总中断使能 */ HAL_NVIC_EnableIRQ(USART1_IRQn); Msp初始化函数 UART参数初始化函数HAL_UART_Init()中调用了Msp初始化函数实现用户自定义初始化配置。UART的时钟使能、GPIO初始化、中断配置 都应当在Msp初始化函数中实现。 /* 使用 UART API 而并非 USART API */ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { // 时钟使能 // GPIO初始化 // 中断配置 } UART无中断收发 UART发送数据 UART发送数据API /* UART无中断发送数据 参数: huart - UART句柄指针 pData - UART本次发送缓冲区指针 Size - UART本次发送缓冲区字节数 Timeout - UART发送超时时限 返回: HAL_OK - UART成功发送指定字节数(Size) HAL_ERROR - pData = NULL 或 Size = 0 将返回 HAL_ERROR HAL_TIMEOUT - UART发送超时 HAL_BUSY - UART发送繁忙 */ HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); UART无中断发送示例 uint8_t *TxBufferPtr = (uint8_t*)"Successful!nr"; #ifndef TIMEOUT #define TIMEOUT 1000 #endif while(HAL_UART_Transmit(&huart1,TxBufferPtr,13,TIMEOUT) != HAL_OK); UART接收数据 UART接收数据API /* UART无中断接收数据 参数: huart - UART句柄指针 pData - UART本次接收缓冲区指针 Size - UART本次接收缓冲区字节数 Timeout - UART接收超时时限 返回: HAL_OK - UART成功接收指定字节数(Size) HAL_ERROR - pData = NULL 或 Size = 0 将返回 HAL_ERROR HAL_TIMEOUT - UART接收超时 HAL_BUSY - UART接收繁忙 */ HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); UART无中断接收数据示例 uint8_t RxBufferPtr[10] = {0}; #ifndef TIMEOUT #define TIMEOUT 1000 #endif /* 接收完成指定字节数之前,main()将一直阻塞 */ while(HAL_UART_Receive(&huart1,RxBufferPtr,10,TIMEOUT) != HAL_OK); // 接收回显 while(HAL_UART_Transmit(&huart1,RxBufferPtr,10,TIMEOUT) != HAL_OK); UART中断收发 HAL库中将UART中断深度封装,仅提供中断回调函数进行用户中断处理逻辑的实现。中断回调函数均有弱定义(__weak)声明,用户可在任意源文件(.c)中重新强定义(无__weak声明)中断回调函数实现自定义中断处理逻辑。 UART中断回调流程: 1.中断发生 2.进入中断服务函数 UARTx_IRQHandler() 3.中断服务函数调用 通用入口函数 HAL_UART_IRQHandler(), 通用入口函数中进行中断源的判断、中断标志的清除等操作 4.通用入口函数依据事件判断调用 中断回调函数 HAL_UART_XxxCallback() UART发送中断 UART发送中断使能 /* 使能发送中断并配置本次发送中断缓冲区 参数: huart - UART句柄指针 pData - UART本次发送缓冲区指针 Size - UART本次发送缓冲区字节数 返回: HAL_OK - 配置成功且UART发送中断准备就绪 HAL_ERROR - pData = NULL 或 Size = 0 将返回 HAL_ERROR HAL_BUSY - UART发送中断未准备就绪 */ HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); UART发送完成中断回调 /* UART成功发送指定字节数(Size)将执行此中断回调 */ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { // 用户中断处理逻辑 } UART发送中断示例 uint8_t *TxBufferPtr = (uint8_t*)"Successful!nr"; int main(void) { /*****省略代码*****/ while(HAL_UART_Transmit_IT(&huart1,TxBufferPtr,13) != HAL_OK); /*****省略代码*****/ } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { // 发送完成之后打开LED LED_ON(); } } 注意: UART发送中断回调的机制是:每发送一个字节之后均会进入中断服务函数,通过UART句柄中的TxXferCount判断UART发送数据的进度,如果发送达到指定字节数(Size),则调用HAL_UART_TxCpltCallback(). HAL_UART_Transmit_IT()只能开启1次发送中断,调用发送中断回调函数之后便 失能 发送中断。在合适的时机再次调用HAL_UART_Transmit_IT()可以再次开启发送中断。 HAL_UART_Transmit_IT()不可在UART的Msp初始化函数中调用。Msp初始化函数并非在UART参数初始化函数HAL_UART_Init()的末尾调用,在Msp初始化函数调用之后还会进行UART状态的初始化操作。如果在Msp初始化函数中调用HAL_UART_Transmit_IT()将导致错误判断UART发送状态,HAL_UART_Transmit_IT()将错误返回HAL_BUSY. 正确的做法是:在UART参数初始化函数HAL_UART_Init()调用后调用HAL_UART_Transmit_IT(). UART接收中断 UART接收中断使能 /* 使能接收中断并配置本次接收中断缓冲区 参数: huart - UART句柄指针 pData - UART本次接收缓冲区指针 Size - UART本次接收缓冲区字节数 返回: HAL_OK - 配置成功且UART接收中断准备就绪 HAL_ERROR - pData = NULL 或 Size = 0 将返回 HAL_ERROR HAL_BUSY - UART接收中断未准备就绪 */ HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); UART接收完成中断回调 /* UART成功接收指定字节数(Size)将执行此中断回调 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 用户中断处理逻辑 } UART接收中断示例 uint8_t RxBufferPtr[10] = {0}; int main(void) { /*****省略代码*****/ while(HAL_UART_Receive_IT(&huart1,RxBufferPtr,10) != HAL_OK); /*****省略代码*****/ } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { #ifndef TIMEOUT #define TIMEOUT 1000 #endif // 接收回显 while(HAL_UART_Transmit(&huart1,RxBufferPtr,10,TIMEOUT) != HAL_OK); // 换行 while(HAL_UART_Transmit(&huart1,(uint8_t*)"rn",2,TIMEOUT) != HAL_OK); // 使能中断 while(HAL_UART_Receive_IT(&huart1,RxBufferPtr,10) != HAL_OK); } } 注意: UART接收中断回调的机制是:每接收一个字节之后均会进入中断服务函数,通过UART句柄中的RxXferCount判断UART接收数据的进度,如果接收达到指定字节数(Size),则调用HAL_UART_RxCpltCallback(). HAL_UART_Receive_IT()只能开启1次接收中断,调用接收中断回调函数之后便 失能 接收中断。在合适的时机再次调用HAL_UART_Receive_IT()可以再次开启接收中断。 HAL_UART_Receive_IT()不可在UART的Msp初始化函数中调用。Msp初始化函数并非在UART参数初始化函数HAL_UART_Init()的末尾调用,在Msp初始化函数调用之后还会进行UART状态的初始化操作。如果在Msp初始化函数中调用HAL_UART_Receive_IT()将导致错误判断UART接收状态,HAL_UART_Receive_IT()将错误返回HAL_BUSY. 正确的做法是:在UART参数初始化函数HAL_UART_Init()调用后调用HAL_UART_Receive_IT(). |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1936浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
729浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
569浏览 3评论
594浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
552浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 20:27 , Processed in 0.609648 second(s), Total 44, Slave 38 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号