完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、代码自动生成以后的项目及代码结构:
main.c中,调用了串口初始化 串口初始化函数赋值了串口的参数 相当于底层的初始化,配置引脚、并开启中断。 至此串口1配置完毕 二、库文件stm32f1xx_hal_uart.c内的秘密 2.1 初始化 1.usart.c中,MX_USART1_UART_Init 调用了库的HAL_UART_Init,将结构体传递进该函数中 2.HAL_UART_Init干了些什么事? if (huart->gState == HAL_UART_STATE_RESET) { huart->Lock = HAL_UNLOCKED; HAL_UART_MspInit(huart); } huart->gState = HAL_UART_STATE_BUSY; __HAL_UART_DISABLE(huart); /* Disable the peripheral */ UART_SetConfig(huart);/* Set the UART Communication parameters */ /* In asynchronous mode, the following bits must be kept cleared: - LINEN and CLKEN bits in the USART_CR2 register, - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); __HAL_UART_ENABLE(huart); /* Enable the peripheral */ huart->ErrorCode = HAL_UART_ERROR_NONE; huart->gState = HAL_UART_STATE_READY; huart->RxState = HAL_UART_STATE_READY; 调用MspInit-->修改状态忙-->配置寄存器-->清楚标志位 2.2 先理解HAL_UART_Receive函数 uint32_t tickstart = 0U; if (huart->RxState == HAL_UART_STATE_READY) /* Check that a Rx process is not already ongoing */ { __HAL_LOCK(huart); /* Process Locked */ huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; tickstart = HAL_GetTick(); huart->RxXferSize = Size; huart->RxXferCount = Size; while (huart->RxXferCount > 0U) { huart->RxXferCount--; if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) return HAL_TIMEOUT; *pData++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); } } huart->RxState = HAL_UART_STATE_READY; __HAL_UNLOCK(huart); 判断是否忙-->锁住-->标记接收忙-->获取tick计数 -->赋值RxXferCount有多少数据要接收-->每次从DR内获取一个Byte存在pData指向的空间 2.3 HAL_UART_Receive_IT只是配置了一下参数,并没有做任何处理 /* Check that a Rx process is not already ongoing */ if (huart->RxState == HAL_UART_STATE_READY) { __HAL_LOCK(huart); /* Process Locked */ huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->RxXferCount = Size; huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; __HAL_UNLOCK(huart); /* Process Unlocked */ /*Error Interrupt */ __HAL_UART_ENABLE_IT(huart, UART_IT_PE); __HAL_UART_ENABLE_IT(huart, UART_IT_ERR); /* Enable the UART Data Register not empty Interrupt */ __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); return HAL_OK; } 存储在pData指向位置、空间大小RxXferSize 、接收计数RxXferCount ; 接收状态忙;使能接收中断 那么当有数据来的时候,就需要依靠中断函数来处理了。 2.4再看看中断函数在做什么 stm32f1xx_it.c内有定义USART1_IRQHandler,只调用了HAL_UART_IRQHandler函数,下面是 HAL_UART_IRQHandler具体内容 errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE)); if (errorflags == RESET) { if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) { UART_Receive_IT(huart); return; } } /* If some errors occur */ if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) { //略过错误处理 /* Call UART Error Call back function if need be --------------------------*/ if (huart->ErrorCode != HAL_UART_ERROR_NONE) { /* UART in mode Receiver -----------------------------------------------*/ if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) UART_Receive_IT(huart); //略过错误处理 huart->ErrorCode = HAL_UART_ERROR_NONE; } } return; } /* End if some error occurs */ /* UART in mode Transmitter ------------------------------------------------*/ if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) { UART_Transmit_IT(huart); return; } /* UART in mode Transmitter end --------------------------------------------*/ if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) { UART_EndTransmit_IT(huart); return; } 无非是三件事,判断是由什么中断响应的,有错误则处理,响应要调用的接收或者发送。 注意区别 UART_Receive_IT 和 HAL_UART_Receive_IT。 HAL_UART_Receive_IT是用户调用的需要接收多少数据存在何处。 UART_Receive_IT是中断调用的有数据收到该如何处理。 2.5 UART_Receive_IT 真正在接收数据的函数,但在最后会关闭中断 uint16_t *tmp; /* Check that a Rx process is ongoing */ if (huart->RxState == HAL_UART_STATE_BUSY_RX) { *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); if (--huart->RxXferCount == 0U) { __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); __HAL_UART_DISABLE_IT(huart, UART_IT_PE); __HAL_UART_DISABLE_IT(huart, UART_IT_ERR); huart->RxState = HAL_UART_STATE_READY; #if (USE_HAL_UART_REGISTER_CALLBACKS == 1) /*Call registered Rx complete callback*/ huart->RxCpltCallback(huart); #else /*Call legacy weak Rx complete callback*/ HAL_UART_RxCpltCallback(huart); #endif /* USE_HAL_UART_REGISTER_CALLBACKS */ return HAL_OK; } return HAL_OK; } 如果是接收状态忙,则从DR中读取1Byte数据。 如果接收计数归零,则使中断失效,并调用回调函数(用户定义则调用用户的,否则调用系统的) 至此,所有用到的代码分析完毕 三、总结 1、HAL_UART_Receive_IT和HAL_UART_Receive的区别就是:中断接收是有数据到了才去读;直接接收是直接读取,如果超时就返回 2、HAL_UART_Receive_IT配置后,有数据来,计数会在调用中断函数之后自动减1。只有到计数为0时,才会关闭中断并调用回调函数。至此有数据来不再调用中断函数,因为中断已经失效。 3、HAL_UART_Receive_IT在计数未至0之前,应该可以读取之前接收到的数据,但这样做应该比较危险。 4、在开源电子的例程中,使用 HAL_UART_Receive_IT(&huart1,(uint8_t *)aRxBuffer, 1); 即Size设置为1,只接收1Byte数据,在每次中断结束后重新配置来使能中断。 四、还有必要再看一眼uart的结构体定义 /** * @brief UART handle Structure definition */ typedef struct __UART_HandleTypeDef { USART_TypeDef *Instance; /*!< UART registers base address */ UART_InitTypeDef Init; /*!< UART communication parameters */ uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */ uint16_t TxXferSize; /*!< UART Tx Transfer size */ __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */ uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */ uint16_t RxXferSize; /*!< UART Rx Transfer size */ __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */ DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */ DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */ HAL_LockTypeDef Lock; /*!< Locking object */ __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management and also related to Tx operations. This parameter can be a value of @ref HAL_UART_StateTypeDef */ __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations. This parameter can be a value of @ref HAL_UART_StateTypeDef */ __IO uint32_t ErrorCode; /*!< UART Error code */ #if (USE_HAL_UART_REGISTER_CALLBACKS == 1) void (* TxHalfCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Tx Half Complete Callback */ void (* TxCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Tx Complete Callback */ void (* RxHalfCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Rx Half Complete Callback */ void (* RxCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Rx Complete Callback */ void (* ErrorCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Error Callback */ void (* AbortCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Complete Callback */ void (* AbortTransmitCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Transmit Complete Callback */ void (* AbortReceiveCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Receive Complete Callback */ void (* WakeupCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Wakeup Callback */ void (* MspInitCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Msp Init callback */ void (* MspDeInitCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Msp DeInit callback */ #endif /* USE_HAL_UART_REGISTER_CALLBACKS */ } UART_HandleTypeDef; |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1763 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1617 浏览 1 评论
1059 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
723 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1670 浏览 2 评论
1933浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
726浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
566浏览 3评论
592浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
550浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 08:20 , Processed in 0.680020 second(s), Total 46, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号