日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32F4 HAL库开发 -- 串口

發布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32F4 HAL库开发 -- 串口 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、串口介紹

串口設置包含:開啟串口時鐘、設置響應的IO口模式、設置波特率、數據位長度、奇偶校驗位、DMA等信息。
具體參看:STM32開發 – 串口詳解

二、函數

1、串口參數初始化,并使能串口。

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);

該函數只有一個入口參數 huart,為UART_HandleTypeDef 結構體指針類型,我們俗稱其為串口句柄,它的使用會貫穿整個串口程序。一般情況下,我們會定義一個UART_HandleTypeDef 結構體類型全局變量,然后初始化各個成員變量。
結構體UART_HandleTypeDef 定義:

/*** @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 managementand 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 */ } UART_HandleTypeDef;

該結構體成員變量非常多,一般情況下下載調用函數HAL_UART_Init對串口進行初始化的時候,我們只需要先設置Instance和Init兩個成員變量的值。
Instance 是 USART_TypeDef 結構體指針類型的變量,它是執行寄存器基地址,實際上這個基地址HAL庫已經定義好了,如果是串口1,取值為USART1即可。
Init是UART_InitTypeDef 結構體類型變量,它是用來設置串口的各個參數,包括波特率、停止位等。
UART_InitTypeDef 結構體定義如下:

typedef struct {uint32_t BaudRate; /*!< This member configures the UART communication baud rate.The baud rate is computed using the following formula:- IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (huart->Init.BaudRate)))- FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8 * (OVR8+1)) + 0.5Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.This parameter can be a value of @ref UART_Word_Length */uint32_t StopBits; /*!< Specifies the number of stop bits transmitted.This parameter can be a value of @ref UART_Stop_Bits */uint32_t Parity; /*!< Specifies the parity mode.This parameter can be a value of @ref UART_Parity@note When parity is enabled, the computed parity is insertedat the MSB position of the transmitted data (9th bit whenthe word length is set to 9 data bits; 8th bit when theword length is set to 8 data bits). */uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.This parameter can be a value of @ref UART_Mode */uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled or disabled.This parameter can be a value of @ref UART_Hardware_Flow_Control */uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8).This parameter can be a value of @ref UART_Over_Sampling */ } UART_InitTypeDef;

BaudRate: 為串口波特率,用來確定串口通信的速率 。
WordLength: 為字長,可以設置8位字長或者9位字長。我們設置為 8 位字長數據格式 UART_WORDLENGTH_8B。
StopBits: 為停止位,可以設置為1個停止位或者2個停止位。我們設置為1個停止位 UART_STOPBITS_1。
Parity: 為是否需要奇偶校驗,我們設定為無奇偶校 UART_PARITY_NONE。
Mode: 為串口模式,可以設置為只收模式、只發模式或者收發模式。我們設置為全雙工收發模式 UART_MODE_TX_RX。
HwFlowCtl: 為是否支持硬件流控制,我們設置為無硬件流控制 UART_HWCONTROL_NONE。
pTxBuffPtr, TxXferSize 和 TxXferCount 三個變量分別用來設置串口發送的數據緩存指針,發送的數據量和還剩余的要發送的數據量。
pRxBuffPtr, RxXferSize 和RxXferCount 三個變量則是用來設置接收的數據緩存指針,接收的最大數據量以及還剩余的要接收的數據量。
hdmatx 和 hdmarx 是串口 DMA 相關的變量,指向 DMA 句柄。

函數 HAL_UART_Init 使用的一般格式為:

UART_HandleTypeDef UART1_Handler; //UART 句柄 UART1_Handler.Instance=USART1; //USART1 UART1_Handler.Init.BaudRate=115200; //波特率 UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字長為 8 位格式 UART1_Handler.Init.StopBits=UART_STOPBITS_1; //一個停止位 UART1_Handler.Init.Parity=UART_PARITY_NONE; //無奇偶校驗位 UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //無硬件流控 UART1_Handler.Init.Mode=UART_MODE_TX_RX; //收發模式 HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()會使能 UART1

需要說明的是,函數HAL_UART_Init內部會調用串口使能函數使能相應串口,所以調用了該函數之后我們就不需要重復使能串口了。當然,HAL庫也提供了具體的串口使能和失能的方法,具體使用方法如下:

__HAL_UART_ENABLE(handler); //使能句柄 handler 指定的串口 __HAL_UART_DISABLE(handler); //關閉句柄 handler 指定的串口

這里還需要注意,串口作為一個重要的外設,在調用的初始化函數HAL_UART_Init內部,會先調用MSP初始化回調函數進行MCU相關的初始化,函數為:

void HAL_UART_MspInit(UART_HandleTypeDef *huart);

我們的程序中,只需要重寫該函數即可。一般情況下,該函數內部用來編寫IO初始化,時鐘使能以及NVIC配置。

2、使能串口和GPIO時鐘

我們要使用串口,所以我們必須使能串口時鐘和使用到的GPIO口的時鐘。具體方法:

__HAL_RCC_USART1_CLK_ENABLE(); //使能 USART1 時鐘 __HAL_RCC_GPIOA_CLK_ENABLE(); //使能 GPIOA 時鐘

3、GPIO口初始化設置,以及復位映射配置

參看:STM32F4 HAL庫開發 – GPIO

4、開啟串口相關中斷,配置串口中斷優先級

__HAL_UART_ENABLE_IT 使能串口中斷的標識符。
示例:

__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE); //開啟接收完成中斷

第一個參數:為串口句柄,類型為UART_HandleTypeDef 結構體類型。
第二個參數:為我們要開啟的中斷類型值。

#define UART_IT_PE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_PEIE)) #define UART_IT_TXE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TXEIE)) #define UART_IT_TC ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TCIE)) #define UART_IT_RXNE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE)) #define UART_IT_IDLE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE))

有開啟中斷就有關閉中斷,操作方法為:

__HAL_UART_DISABLE_IT(huart,UART_IT_RXNE); //關閉接收完成中斷

對于中斷優先級配置,參考方法為:

HAL_NVIC_EnableIRQ(USART1_IRQn); //使能 USART1 中斷通道 HAL_NVIC_SetPriority(USART1_IRQn,3,3); //搶占優先級 3,子優先級 3

5、編寫中斷服務函數

串口1中斷服務函數為:

void USART1_IRQHandler(void) ;

當發生中斷的時候,程序就會執行中斷服務函數。然后我們在中斷服務函數中編寫相應的邏輯代碼即可。

6、串口數據接收和發送

HAL 庫操作 USART_DR 寄存器發送數據的函數是:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

通過該函數向串口寄存器 USART_DR 寫入一個數據。

HAL 庫操作 USART_DR 寄存器讀取串口接收到的數據的函數是:

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

通過該函數可以讀取串口接受到的數據。

7、DMA配置

參看:STM32F4 HAL庫開發 – DMA

三、STM32CubeMX 配置串口

1、配置

打開 Pinout選項卡界面,左側依次進入 Categories->Connectivity->USART1 配置欄。

配置欄有2個選項
**Mode:**用來設置串口的模式或者關閉串口

Asynchronous:異步
Synchronous:同步
Single Wire(Half-Duplex):單線(半雙工)
Multiprocessor Communication:多處理器通信

這里我們要開啟串口的異步模式,選擇Mode值為 Asynchronous。

Hardware Flow Control(RS232): 用來開啟/關閉串口的硬件控制流。
該選項只有在Mode選項值為 Asynchronous(異步通信)模式的前提下才有效。

選擇收發引腳:

在GPIO->USART里就可以看到新添加的USART1_TX和USART1_RX。

配置欄有一下幾個選項:
GPIO mode:
Altemate Fuction Push Pull (復用推挽)
GPIO Pull-up/Pull-down:
Pull-up (上拉)
Maximum output speed:
Very High(速度)

再次打開進入 Categories->Connectivity->USART1 配置欄

下半部分可以看到:
Parameter Settings:
包含波特率、數據位、奇偶校驗位、停止位、使能收發模式、過采樣等設置。
我們將 USART1 配置為:波特率 115200, 8 位字長模式,無奇偶校驗位, 1 個停止位,發送/接收均開啟。

DMA settings:
可以點擊Add,添加USART1_RX 和 USART1_TX。
可以選擇,Priority 優先級。
在 DMA Request Settings,也可以進行設置。

NVIC Settings:
配置完DMA后,在打開NVIC Settings,就可以看到 DMA的使能是選中的。
這里我們勾選 USART1 global interrupt 的中斷使能。

2、生成源碼

MX_USART1_UART_Init 函數

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;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}}

HAL_UART_MspInit 函數

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**USART1 GPIO ConfigurationPB6 ------> USART1_TXPB7 ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF7_USART1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USART1 DMA Init *//* USART1_RX Init */hdma_usart1_rx.Instance = DMA2_Stream2;hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_rx.Init.Mode = DMA_NORMAL;hdma_usart1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);/* USART1_TX Init */hdma_usart1_tx.Instance = DMA2_Stream7;hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_tx.Init.Mode = DMA_NORMAL;hdma_usart1_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}}

HAL_UART_MspDeInit 函數

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) {if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPB6 ------> USART1_TXPB7 ------> USART1_RX*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);/* USART1 DMA DeInit */HAL_DMA_DeInit(uartHandle->hdmarx);HAL_DMA_DeInit(uartHandle->hdmatx);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */} }

DMA中斷:

void DMA2_Stream2_IRQHandler(void) {/* USER CODE BEGIN DMA2_Stream2_IRQn 0 *//* USER CODE END DMA2_Stream2_IRQn 0 */HAL_DMA_IRQHandler(&hdma_usart1_rx);/* USER CODE BEGIN DMA2_Stream2_IRQn 1 *//* USER CODE END DMA2_Stream2_IRQn 1 */ }void DMA2_Stream7_IRQHandler(void) {/* USER CODE BEGIN DMA2_Stream7_IRQn 0 *//* USER CODE END DMA2_Stream7_IRQn 0 */HAL_DMA_IRQHandler(&hdma_usart1_tx);/* USER CODE BEGIN DMA2_Stream7_IRQn 1 *//* USER CODE END DMA2_Stream7_IRQn 1 */ }

中斷和接收數據處理:

void USART1_IRQHandler(void) {THC_LiquidCooled_Handler(); }void THC_LiquidCooled_Handler (void) {HAL_UART_IRQHandler(&DEF_UART_LIQUID);if(RESET != __HAL_UART_GET_FLAG(&DEF_UART_LIQUID, UART_FLAG_IDLE)){__HAL_UART_CLEAR_IDLEFLAG(&DEF_UART_LIQUID); //清除標志位HAL_UART_DMAStop(&DEF_UART_LIQUID);METERComm.Rbuf_CNT = LIQUID_BUF_RXD_SIZE - __HAL_DMA_GET_COUNTER(&DEF_HDMA_LIQUID_RX);HAL_UART_Receive_DMA(&DEF_UART_LIQUID,RLIQUIDBuf,LIQUID_BUF_RXD_SIZE);} }void CheckLIQUID_RBuf_Fun(void) {if(LIQUIDComm.Rbuf_CNT != 0){//判斷幀頭、幀尾、BCC校驗u16 LenBuf;u16 onePackageLen = 0;u16 onePackageBodyLen = 0;int16_t onePackageBodyCrc = 0;LenBuf = (LIQUIDComm.Rbuf_CNT & (LIQUID_BUF_RXD_SIZE - 1));if ((RLIQUIDBuf[0] == 0x01) && (RLIQUIDBuf[1] == 0x03)){onePackageBodyLen = RLIQUIDBuf[2];onePackageLen = onePackageBodyLen + 5; //包含 子機地址、功能碼、讀取字節數、CRC碼if( onePackageLen <= LenBuf ){onePackageBodyCrc=RLIQUIDBuf[onePackageLen-2] + ((RLIQUIDBuf[onePackageLen-1]<<8)&0xff00); //校驗碼反著的if( onePackageBodyCrc == Check_CRC16(RLIQUIDBuf, onePackageBodyLen+3) ){THC_LIQUID_Receive(RLIQUIDBuf+3, onePackageBodyLen);memset(RLIQUIDBuf,'\0', LIQUID_BUF_RXD_SIZE); //收到一幀以后,清空bufLIQUIDComm.Rbuf_CNT = 0;}}}} }

四、485通訊

485通訊還需要有一個cs引腳配置。

// RS485 發送 #define LIQUID_RS485_T (HAL_GPIO_WritePin(LIQUIDCOOLED_GPIO_Port, LIQUIDCOOLED_485CK_Pin, GPIO_PIN_SET)) //RS485 接收 #define LIQUID_RS485_R (HAL_GPIO_WritePin(LIQUIDCOOLED_GPIO_Port, LIQUIDCOOLED_485CK_Pin, GPIO_PIN_RESET))

發送數據:

void LIQUID_RS485_Send_Data(u8 *pdata,u32 data_size) {LIQUID_RS485_T;//RS485 發送HAL_UART_Transmit(&DEF_UART_LIQUID,pdata,data_size,1000);LIQUID_RS485_R;//RS485 接收 }

五、使能

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //uart使能idle中斷 HAL_UART_Receive_DMA(&huart1,USART_RX_BUF1,USART_REC_LEN);//打開DMA接收,數據存入rx_buffer數組中。

六、接線

RS485:

RS485通信的時候,必須A接A,B接B,否則通信不正常。

RS232:

RS232通信的時候,Rx接Tx,Tx接Rx。

總結

以上是生活随笔為你收集整理的STM32F4 HAL库开发 -- 串口的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日色视频 | 免费又黄又爽又猛大片午夜 | 六月色丁香 | 色婷婷精品久久二区二区密 | 99在线视频播放 | 1024国产视频 | 久久久久亚洲av无码专区首jn | 亚洲精品一区二区18漫画 | 深夜免费福利 | www.亚洲精品 | 97av免费视频| 亚洲AV成人无码一二三区在线 | 老熟妇仑乱一区二区av | 久久精品区 | 少妇影院在线观看 | 九九在线 | 免费成人深夜在线观看 | 图片一区二区 | 国产一区二区三区精品视频 | 精品黑人一区二区三区 | 亚洲v视频 | 97超碰免费在线观看 | 妺妺窝人体色www在线下载 | 美国一区二区 | 热99在线 | 在线中文字幕观看 | 亚洲女女做受ⅹxx高潮 | 欧美成人dvd在线视频 | 9色av| 麻豆视频免费看 | 含羞草一区二区 | 欧美一级网站 | 一区二区三区国产精品视频 | 成人国产在线 | 毛片福利视频 | 久草剧场 | 九色porny自拍视频 | 成人黄色激情小说 | 一区二区国产视频 | 麻豆国产一区二区 | 一区二区三区在线视频播放 | 天天干,夜夜操 | 人人妻人人澡人人爽精品欧美一区 | 色综合中文网 | 91网址在线 | 国产suv精品一区二区33 | 香蕉久久一区二区三区 | 日韩不卡中文字幕 | 宅男噜噜噜66一区二区 | 超碰资源总站 | 图片区小说区视频区 | 国产精品秘| 天天色天天干天天色 | 国产成年人视频 | 少妇精品亚洲一区二区成人 | 天天综合人人 | 亚洲天堂2024 | 久久精品在线视频 | 涩涩视频网站在线观看 | 国产日韩久久 | 精品视频在线免费 | 麻豆91在线 | 亚洲av综合色区无码一区 | 变态另类丨国产精品 | 免费一级黄色片 | 亚洲精品日日夜夜 | 一区二区三区免费毛片 | 国产精品视频一区二区三区 | 亚洲精品视频一二三区 | 一区二区视频观看 | 久久久久久久国产精品美女 | 91在线播| 伊人黄色片 | 色哟哟无码精品一区二区三区 | 久久国产高清 | 国产精品操 | 欧美天天色 | 殴美一区二区 | 一区二区三区不卡视频在线观看 | 91视频免费网站 | 特级丰满少妇一级aaaa爱毛片 | jizz处女| av在线一区二区 | 日韩av色| 欧美伦理一区二区三区 | 日韩中出 | 精品国产一二三 | 日韩六区| 夜夜夜网 | 日韩电影在线一区二区 | 国产一区在线播放 | 久久嫩草视频 | 美女mm131爽爽爽免费动视频 | av观看在线免费 | 天天射狠狠干 | 久章草影院 | 精品久久久视频 | 少妇裸体淫交视频免费看高清 | 日韩成人在线播放 |