1、串口阻塞發(fā)送
串口阻塞發(fā)送的意思就是,發(fā)送一段數(shù)據(jù),在沒有發(fā)送完所有數(shù)據(jù)之前,一直停留在此發(fā)送函數(shù)(可設(shè)定阻塞時(shí)間),這個(gè)過程中會阻塞別的程序運(yùn)行;
1.1、配置
HAL庫的配置分為兩個(gè)層次,一個(gè)是HAL庫內(nèi)部調(diào)用的、與MCU硬件相關(guān)的初始化xxx_MspInit,一個(gè)是我們外部調(diào)用的初始化xxx_Init;
這兩個(gè)初始化函數(shù)配置完,就可以進(jìn)行阻塞式的串口發(fā)送了,很簡單。
1.1.1、HAL_UART_MspInit?
HAL_UART_MspInit,MCU硬件初始化,需要開啟RCC串口時(shí)鐘、RCC的GPIO端口時(shí)鐘、配置GPIO的模式;
(還有個(gè)反初始化HAL_UART_MspDeInit,這里就不說了)
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==DEBUG_USARTx){
/* 時(shí)鐘使能 */
DEBUG_USART_RCC_CLK_ENABLE();
DEBUG_USARTx_GPIO_ClK_ENABLE();
/* 串口外設(shè)功能GPIO配置 */
GPIO_InitStruct.Pin = DEBUG_USARTx_Tx_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = DEBUG_USARTx_AFx;
HAL_GPIO_Init(DEBUG_USARTx_Tx_GPIO, &GPIO_InitStruct);
GPIO_InitStruct.Pin = DEBUG_USARTx_Rx_GPIO_PIN;
HAL_GPIO_Init(DEBUG_USARTx_Tx_GPIO, &GPIO_InitStruct);
}
}
1.1.2、MX_DEBUG_USART_Init
MX_DEBUG_USART_Init,串口協(xié)議初始化,波特率、數(shù)據(jù)寬度、停止位、串口模式的配置;
void MX_DEBUG_USART_Init(void)
{
husart_debug.Instance = DEBUG_USARTx;
husart_debug.Init.BaudRate = DEBUG_USARTx_BAUDRATE;
husart_debug.Init.WordLength = UART_WORDLENGTH_8B;
husart_debug.Init.StopBits = UART_STOPBITS_1;
husart_debug.Init.Parity = UART_PARITY_NONE;
husart_debug.Init.Mode = UART_MODE_TX_RX;
husart_debug.Init.HwFlowCtl = UART_HWCONTROL_NONE;
husart_debug.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&husart_debug);
}
1.2、調(diào)用
外部調(diào)用的初始化就是MX_DEBUG_USART_Init,然后就可以使用HAL_UART_Transmit函數(shù)來發(fā)送數(shù)據(jù)了。
static uint8_t uart1_tx_buf[]="123456789";
int main(void)
{
HAL_Init(); //復(fù)位所有外設(shè),初始化Flash接口和系統(tǒng)滴答定時(shí)器
SystemClock_Config(); //配置系統(tǒng)時(shí)鐘
LED_GPIO_Init();
MX_DEBUG_USART_Init(); //串口初始化
while (1){
LED1_ON; HAL_Delay(1000);
LED1_OFF; HAL_Delay(1000);
HAL_UART_Transmit(&husart_debug,uart1_tx_buf,8,1000);
}
}
2、串口中斷發(fā)送
串口中斷發(fā)送的意思就是,發(fā)送數(shù)據(jù)的過程在中斷中進(jìn)行,這個(gè)中斷實(shí)際上是發(fā)送數(shù)據(jù)寄存器空的中斷。
比如說你要發(fā)送10個(gè)字節(jié)的數(shù)據(jù),那么肯定這10個(gè)字節(jié)不會一次性發(fā)送完吧,只能是一個(gè)一個(gè)字節(jié)地發(fā)送。每發(fā)送一個(gè)字節(jié),發(fā)送數(shù)據(jù)寄存器就會有一個(gè)為空的標(biāo)志,以提示可以發(fā)送下一個(gè)字節(jié)了,這樣在發(fā)送數(shù)據(jù)的過程中CPU不會一直在等待,而是用中斷來提示需要進(jìn)行發(fā)送的時(shí)候再發(fā)送。
2.1、配置
在1的基礎(chǔ)上,HAL_UART_MspInit 函數(shù)的末尾增加串口中斷配置,如下:
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==DEBUG_USARTx){
//這部分配置不變......
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
?增加串口1的中斷服務(wù)函數(shù),具體的功能不用我們寫;
void USART1_IRQHandler(void){
HAL_UART_IRQHandler(&husart_debug);
}
2.2、調(diào)用
和1的外部調(diào)用的初始化是一樣的,發(fā)送函數(shù)使用HAL_UART_Transmit_IT;
3、串口DMA發(fā)送
3.1、配置
注:必須增加串口的中斷配置(如2的配置),否則會出現(xiàn)只能發(fā)送一次的尷尬局面,3.1.2中的DMA中斷也必須配置,否則也是只能發(fā)送一次,不過這一處的配置應(yīng)該不會漏就是了;
3.1.1、HAL_UART_MspInit
在2的基礎(chǔ)上,增加有關(guān)DMA的配置,數(shù)據(jù)流、通道、傳輸方向、地址自增與否等等;(可以用CubeMX勾勾選選生成配置代碼,然后再移植到自己的代碼上)
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==DEBUG_USARTx){
//這部分配置不變......
/* USART1 DMA 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_LOW;
hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart1_tx);
__HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
3.1.2、UART1_DMA_Init
UART1_DMA_Init,這里面就是開啟DMA時(shí)鐘,配置DMA的優(yōu)先級;
DMA流的中斷服務(wù)函數(shù)也是只寫到這就OK了;
void UART1_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}
void DMA2_Stream7_IRQHandler(void){
HAL_DMA_IRQHandler(&hdma_usart1_tx);
}
3.2、調(diào)用
要先調(diào)用DMA初始化,再調(diào)用串口初始化;文章來源:http://www.zghlxwxcb.cn/news/detail-424188.html
因?yàn)榇诔跏蓟杏信渲肈MA的參數(shù)等操作,所以在這之前DMA需要初始化;文章來源地址http://www.zghlxwxcb.cn/news/detail-424188.html
static uint8_t uart1_tx_buf[]="123456789";
int main(void)
{
HAL_Init(); //復(fù)位所有外設(shè),初始化Flash接口和系統(tǒng)滴答定時(shí)器
SystemClock_Config(); //配置系統(tǒng)時(shí)鐘
LED_GPIO_Init();
UART1_DMA_Init(); //串口DMA初始化
MX_DEBUG_USART_Init(); //串口初始化
while (1){
LED1_ON; HAL_Delay(1000);
LED1_OFF; HAL_Delay(1000);
HAL_UART_Transmit_DMA(&husart_debug,uart1_tx_buf,8);
}
}
到了這里,關(guān)于STM32F4_HAL庫_串口阻塞/中斷/DMA三種方式發(fā)送數(shù)據(jù)的配置的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!