从今天开始定时更新一下有关STM32 HAL库学习的过程,主要是对HAL库函数的所有讲解。本章是关于uart串口的函数。
1、HAL_USART_Init(USART_HandleTypeDef * husart)
初始化串口的的函数:
用法为
UART_HandleTypeDef huart1;
huart1.xxx = ssss;
...
HAL_USART_Init(&huart1); //需要注意点的是函数的输入参数是指针类型
UART_HandleTypeDef huart4;
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK)
2、void HAL_USART_MspInit (USART_HandleTypeDef * husart)
串口回调函数,主要进行硬件部分的初始化
例如开启串口的时钟和管脚的配置,本函数被上一个函数自动调用。
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspInit 0 */
/* USER CODE END UART4_MspInit 0 */
/* UART4 clock enable */
__HAL_RCC_UART4_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**UART4 GPIO Configuration
PI9 ------> UART4_RX
PA0 ------> UART4_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 1, 2);
HAL_NVIC_EnableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspInit 1 */
/* USER CODE END UART4_MspInit 1 */
}
3.HAL_StatusTypeDef HAL_USART_Transmit (USART_HandleTypeDef * husart, uint8_t * pTxData, uint16_t Size, uint32_t Timeout);
串口发送数据的函数,最重要的函数之一。单工以阻塞模式发送大量数据。
huart :要发送数据的串口指针,ptxData:要发送的数据,注意此处的指针形式,Size:发送数据的长度(字节数) Timeout:发送数据超时时间
发送数据的大小要注意是u8类型的(0-255)
HAL_UART_Transmit(&huart4,"222",3,2);
//发送一个字符串
u8 num = 10;
HAL_UART_Transmit(&huart4,&num,1,2);
//发送一个数字
u16 num = 0xffde;
u8 temp;
temp = num>>8;
HAL_UART_Transmit(&huart4,&temp,1,1);
temp = num;
HAL_UART_Transmit(&huart4,&temp,1,1);
//发送一个十六位的数据
注意:使用本函数发送十六位或者二十四位数据的时候下面的方法是错误的:
u16 num = 0x1234;
HAL_UART_Transmit(&huart4,&num,2,2);
此方法打印出的数据为 34 12 。不是想要输出的1234需要注意。
4、HAL_StatusTypeDef HAL_UART_Receive (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size,uint32_t Timeout)
串口接收数据的库函数,阻塞的方式接收数据。
huart :要发送数据的串口指针,pData:接收数据缓存地址,注意此处的指针形式,Size:接收数据的长度(字节数) Timeout:数据接收等待时间,CPU等待这个时间用来接收数据。
注意本函数不会因为设置接收接收字符数和实际接收到的数据量不一致而发生冲突,接收到的数据小于设定接收量时少的那部分补零,多于设定量时直截取需要的数据量。
uint16_t numd[3];
HAL_UART_Receive(&huart4,numd,3,1000);
HAL_UART_Transmit(&huart4,numd,3,1);
//等一秒时间接收三位数据
5、HAL_StatusTypeDef HAL_UART_Transmit_IT (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
使用中断的方式发送数据,对应上面的阻塞方式发送数据。
本函数的使用需要慎重考虑前后程序,要注意本函数发送方式为中断方式,如果本函数后面直接跟着用HAL_UART_Transmit函数,那么后面数据不会发送。可通过增加短延时解决
uint16_t numd[3];
HAL_UART_Receive(&huart4,numd,3,1000);
while(HAL_UART_Transmit_IT(&huart4,numd,3)==HAL_OK);
HAL_Delay(10); //不加延时以下数据无法使用阻塞方式发送
num1= num23>>8;
HAL_UART_Transmit(&huart4,&num1,1,1);
num1 = num23;
HAL_UART_Transmit(&huart4,&num1,1,1);
6、
HAL_StatusTypeDef HAL_UART_Receive_IT (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
一种中断模式接收数据的函数。
huart :接收数据串口指针。pdata 接收区的指针 size 接受数据量字节长度,一般设置接收长度为1,每次接受一个字节的数据就进入中断处理。
注意如果设置接收数据不为1,而是某个固定的值,当串口接受的数据量不满足这个值的时候,串口中断不会被触发。一直等待接收数据满足设定值才会触发中断。如果出现接收出错可以使用
HAL_USART_ErrorCallback
函数来重置接收。
本函数必须在接受回调函数中再次调用才能经行下一次的接收。
#define num 1
uint16_t numd[num];
void UART_Init()
{
.....
HAL_UART_Receive_IT(&huart4,numd,num);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//接收完成回调函数
{
HAL_UART_Receive_IT(&huart,numd,num);
}
7、HAL_StatusTypeDef HAL_UART_Transmit_DMA (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
使用DMA的方式发送数据。
huart :发送数据串口指针。pdata 发送数据数组的首地址 size 发送数据量字节长度。使用这个函数之前需要做uart函数关于DMA设置的初始化。使用本函数发送完毕之后需要清除传输完成标志关闭DMA后才能够再次调用本函数。
因为DMA发送数据可以有两种形式一种是循环发送,另一种是单次发送。如果使用单次发送的情况下,本函数发送完毕之后就无法再次通过调用的方式发送数据。如果需要通过不断调用的方法发送数据可以将清除标志等函数放置在本函数之后,中间必须要隔着其他的函数(实现延时的功能)此方法适用于发送数据量不多的情况下。如果发送的数据量大的情况需要配合DMA的发送完成中断,在发送完成中断中清除标志位等操作。
#define SEND_BUF_SIZE 6
u8 SendBuff[SEND_BUF_SIZE]="123456"; //发送数据缓冲区
UART_HandleTypeDef UART1_Handler;
HAL_UART_Transmit_DMA(&UART1_Handler,SendBuff,SEND_BUF_SIZE);//开启DMA传输
.... //用于数据量不多的情况下可以使用此方法清除完成标志
if(__HAL_DMA_GET_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7))//等待DMA2_Steam7传输完成
{
__HAL_DMA_CLEAR_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7);//清除DMA2_Steam7传输完成标志
HAL_UART_DMAStop(&UART1_Handler); //传输完成以后关闭串口DMA
}
//使用中断的方法清除发送完毕标志位
//DMA初始化中开启DMA通道所在的中断
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn,0,1);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
void XferCpltCallback()
{
if(__HAL_DMA_GET_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7))//等待DMA2_Steam7传输完成
{
__HAL_DMA_CLEAR_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7);//清除DMA2_Steam7传输完成标志
HAL_UART_DMAStop(&UART1_Handler); //传输完成以后关闭串口DMA
}
}
void DMA2_Stream7_IRQHandler()
{
HAL_DMA_IRQHandler(&UART1TxDMA_Handler);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
XferCpltCallback();
}
8、HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart,uint8_t * pData, uint16_t Size)
huart :接收数据串口指针。pdata 接收数据数组的首地址 size 接收数据量字节长度。使用DMA的方式接收数据。
#define SEND_BUF_SIZE 6
u8 SendBuff[SEND_BUF_SIZE]=""; //发送数据缓冲区
UART_HandleTypeDef UART1_Handler;
HAL_UART_Receive_DMA(&UART1_Handler,SendBuff,SEND_BUF_SIZE);//开启DMA传输
9、HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef* huart)
huart:串口指针,暂停DMA数据传输。
HAL_UART_DMAPause(&UART1_Handler);
10、HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
huart:串口指针,从暂停状态中恢复DMA传送。
HAL_UART_DMAResume(&UART1_Handler);
11、HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
huart:串口指针,停止DMA的传输。
HAL_UART_DMAStop(&UART1_Handler);
使用本函数停止DMA的传输之后可以再次使用
HAL_UART_Transmit_DMA
打开DMA传输,无法使用HAL_UART_DMAResume打开。
12、HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart)
huart:串口指针.中止uart的中断、DMA形式的发送和接收数据。使用本函数没法阻止阻塞方法发送和接受数据。本函数只能阻止本次的数据传输,如果打开了接收中断会被关闭需要重新断模式接收数据。
HAL_UART_Abort(&UART1_Handler);
13、HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart)
huart:串口指针。中止串口中断方式或者DMA方式的发送数据。
用法同上
14、HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart)
huart:串口指针。中止串口中断方式或者DMA方式的接收数据。
用法同上
15、HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart)
huart:串口指针。中止串口中断或者DMA的中断。
用法同上
16、HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart)
huart:串口指针。中止串口中断方式或者DMA方式的发送数据并且关闭发送中断和DMA中断。
用法同上
17、HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart)
huart:串口指针。中止串口中断方式或者DMA方式的接收数据并且关闭发送中断和DMA中断。
用法同上
18、void HAL_UART_IRQHandler (UART_HandleTypeDef * huart)
这个函数属于串口中断处理请求函数。它需要添加在对应串口中断处理函数中。
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
19、void HAL_UART_TxCpltCallback (UART_HandleTypeDef * huart)
本函数是串口发送 数据完毕的回调函数。需要开启发送中断,当串口使用中断模式发送完毕后才能自动调用本函数。
void HAL_UART_TxHalfCpltCallback (UART_HandleTypeDef * huart){}
20、
void HAL_UART_TxHalfCpltCallback (UART_HandleTypeDef * huart)
发送数据一半回调函数,不常用。
21、void HAL_UART_ErrorCallback (UART_HandleTypeDef * husart)
串口收发数据出错时的回调函数。当使用中断方式接收数据,数据接收的数量不满足设定的值的时候,可以使用本函数重置接收流程。
void HAL_UART_ErrorCallback (UART_HandleTypeDef * husart)
{
HAL_UART_Receive_IT(&UART1_Handler,(u8 *)aRxBuffer, RXBUFFERSIZE);
}
22、HAL_StatusTypeDef HAL_LIN_SendBreak (UART_HandleTypeDef * huart)
LIN总线通信函数,发送一个断开连接的标识。
23、HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode (UART_HandleTypeDef * huart)
多核处理器开启串口静音模式。
24、HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode (UART_HandleTypeDef * huart)
多核处理器关闭串口静音模式。
25、void HAL_MultiProcessor_EnterMuteMode (UART_HandleTypeDef * huart)
多核处理器进入串口静音模式。