一 配置串口工作参数
HAL_UART_Init()
此函数初始化时需要传入形参,形参为用户定义的句柄,对句柄结构体成员设置之后作为形参传入HAL库串口初始化函数即可完成配置串口工作参数过程。
句柄中需要设置的成员主要如下
①寄存器基地址 USART_TypeDef *Instance
②异步通信参数 UART_InitTypeDef Init
主要有波特率,字长,停止位,校检位,UART模式
代码示例如下:
UART_HandleTypeDef g_uart1_handle; /* UART句柄 */
void usart_init(uint32_t baudrate)
{
/*UART 初始化设置*/
g_uart1_handle.Instance = USART1;
g_uart1_handle.Init.BaudRate = baudrate; /* 波特率 */
g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
g_uart1_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
g_uart1_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
g_uart1_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&g_uart1_handle);
}
二 串口底层初始化
HAL_UART_Msplnit()
此函数为串口的MSP回调函数,用于配置串口所用到的外设硬件包括GPIO,中断,时钟。
首先此函数形参依然定义为一个串口句柄UART_HandleTypeDef *xxx,之后对传入形参进行判断是否传入的形参为所用串口基地址,如果是接下来按照如下步骤
①使能串口与所对应IO口时钟
②初始化IO口
③使能串口中断,设置优先级
代码示例如下:
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;
if (huart->Instance == USART_UX) /* 如果是串口1,进行串口1 MSP初始化 */
{
USART_TX_GPIO_CLK_ENABLE(); /* 使能串口TX脚时钟 */
USART_RX_GPIO_CLK_ENABLE(); /* 使能串口RX脚时钟 */
USART_UX_CLK_ENABLE(); /* 使能串口时钟 */
gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* 串口发送引脚号 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */
HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* 串口RX脚 模式设置 */
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */
#if USART_EN_RX /*已宏定义为真*/
HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART1中断通道 */
HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3);/* 组2,最低优先级:抢占优先级3,子优先级3 */
#endif
}
}
三 开启串口异步接收中断
HAL_UART_Receive_IT()
此函数放在串口初始化函数当中,作用是以中断方式接收指定字节数据
含有三个参数
①用户定义句柄
②接收数据缓冲区 需要另外定义缓冲区,以发送一个字节示例定义: char g_rx_buffer[1]
另外需要对类型进行强制转换为函数形参要求类型
③要接收的数据大小
代码示例如下:
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, 1)
四 设置优先级,使能中断
HAL_NVIC_SetPriority()
HAL_NVIC_EnableIRQ()
已在串口底层初始化函数中完成编写
五 编写中断服务函数
USARTx_IRQHandler()/UARTx_IRQHandler
首先中断服务函数中调用HAL库中断共用处理函数 HAL_UART_IRQHandler(),形参为之前用户定义句柄。此函数会失能中断需要再次使能中断,即开启串口异步接收中断。下一步,调用中断回调函数,重新定义此函数。
HAL_UART_RxCpltCallback() 形参为句柄,接收完成回调函数
若用到多个串口需要判断是否为所需要串口接收到数据,另外定义接收到数据的标志,通过查询该标志来确定是否完成了数据的接收。
代码示例如下:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART_UX) /* 如果是串口1 */
{
if ((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成 */
{
if (g_usart_rx_sta & 0x4000) /* 接收到了0x0d(即回车键) */
{
if (g_rx_buffer[0] != 0x0a) /* 接收到的不是0x0a(即不是换行键) */
{
g_usart_rx_sta = 0; /* 接收错误,重新开始 */
}
else /* 接收到的是0x0a(即换行键) */
{
g_usart_rx_sta |= 0x8000; /* 接收完成了 */
}
}
else /* 还没收到0X0d(即回车键) */
{
if (g_rx_buffer[0] == 0x0d)
g_usart_rx_sta |= 0x4000;
else
{
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0];
g_usart_rx_sta++;
if (g_usart_rx_sta > (USART_REC_LEN - 1))
{
g_usart_rx_sta = 0; /* 接收数据错误,重新开始接收 */
}
}
}
}
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
}
}
六 串口数据发送
HAL_UART_Transmit()
在主函数中编写串口数据发送,首先判断接收数据标志位,如果确定接受则进行数据的发送。
此函数有4个形参
①用户定义句柄
②要发送的数据地址 即定义的缓冲区
③要发送的数据大小
④设置发送时间
接着等待发送完成,利用函数__HAL_UART_GET_FLAG()
此函数有两个形参
①用户定义句柄
②获取SR寄存器TC位状态若为1则发送完成
最后将接收标志复原