USART/UART
USART:通用同步异步收发器
UART:通用异步收发器
USART通常以用于异步通信。
异步通信
没有时钟信号,通过在数据信号中接入起始位和停止位等一些同步信号。
USART简化版框图
USART/UART异步通信配置步骤
1、配置串口工作参数
UART句柄结构定义:
需要配置波特率,字长,停止位,校验位可以不使用,模式可以是收/发/收发。
代码如下:
UART_HandleTypeDef g_uart1_handle; /* UART句柄 */
/* 串口1初始化函数 */
void usart_init(uint32_t baudrate)
{
g_uart1_handle.Instance = USART1;/* 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.Mode = UART_MODE_TX_RX;/* 收发模式 */
HAL_UART_Init(&g_uart1_handle);/* HAL_UART_Init()会使能UART1 */
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t*)g_rx_buffer, 1);//开启串口异步接收中断
}
第三步开启异步接收中断也在初始化中。
2、串口底层初始化
HAL库外设初始化MSP回调机制:
在使用HAL_UART_Init()使能UART1时,会自动调用MSP回调函数HAL_UART_MspInit()。而HAL_UART_MspInit()在stm32f1xx_hal_uart.c中,并且是弱函数
__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_MspInit could be implemented in the user file
*/
}
用户重新定义MSP回调函数:
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;
if(huart->Instance == USART1) /* 如果是串口1,进行串口1 MSP初始化 */
{
//(1)使能USART1和对应IO时钟
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
//(2)初始化IO
gpio_init_struct.Pin = GPIO_PIN_9;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽式复用输出 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化串口1的TX引脚 */
gpio_init_struct.Pin = GPIO_PIN_10;
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化串口1的RX引脚 */
//(3)使能USART1中断,设置优先级
HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
3、开启串口异步接收中断
已经在第一步设置
4、设置优先级,使能中断
已经在第二步最后配置
5、编写中断服务函数
编写中断服务函数并调用HAL库中断共用处理函数:
/* 串口1中断服务函数 */
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&g_uart1_handle);//调用HAL库中断共用处理函数
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t*)g_rx_buffer, 1);
}
然后HAL库会自己调用中断回调函数(上图中那些函数):用户选择自己需要的回调函数进行重新定义。
这里重新定义接收完成回调函数HAL_UART_RxCpltCallback(),判断接收完成后去做某件事。
uint8_t g_usart1_rx_flag = 0; /* 串口接收到数据标志 */
/* 串口数据接收完成回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)//首先判断是不是串口1
{
g_usart1_rx_flag = 1;//串口接受标志置为1,表示接收完成
}
}
6、串口数据发送
最后编写main函数
usart_init(115200); /* 波特率设为115200 */
while(1)
{
if(g_usart1_rx_flag == 1)
{
printf("您输入的字符为:\r\n");
HAL_UART_Transmit(&g_uart1_handle, (uint8_t*)g_rx_buffer, 1, 1000);
while(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_TC) != 1);
printf("\r\n");
g_usart1_rx_flag = 0;
}
else
{
delay_ms(10);
}
}
使用HAL_UART_Transmit()发送数据:
根据状态寄存器SR的TC位来判断是否发送完成,如果TC位为1则发送完成。
使用__HAL_UART_GET_FLAG()判断UART_FLAG_TC这一位是否为1,不为1说明没有发送完成,一直在while循环里面。发送完成接收标志g_usart1_rx_flag置为0。