目录
前言
UART就是常说的串口,他是一种简单而常用的通信接口,它使用简单,所以很多仪器设备和电路模块都用作通信接口,所以掌握串口的使用方法异常重要,今天我们学习STM32CubeMX串口的操作,以及HAL库串口的配置
1、UART接口概述
UART表示通用同步异步收发器,是一种串行通信接口,UART接口最多有五个 信号,而在这五个信号中TX和RX是必须的,一个为输出信号一个为输入信号,在与其他设备连接时,TX要连接设备的RX,而RX要连接设备的TX,而SCLK是发送器输出的时钟信号,这个时钟线只用于同步模式,异步模式无SCLK信号
串口硬件层的功能就是进行串行数据的发送和接收,发送和接受的基本单元是一个数据帧,串口通信的基本参数有以下几个
1、数据位:8位或者9位,一般设置为8位,因为1字节有8位,这样一帧传输1字节的有效数据
2、奇偶校验位:可以无奇偶校验位,也可以设置奇校验位或者偶校验位
3、停止位:1个或2个停止位,一般设置1个停止位
4、波特率:就是串行数据传输的速率,单位是bit/s,常用的波特率有9600、19200、115200等,一个串口单元的时钟由APB1或APB2总线提供,所以挂在不同APB总线上的传输最大速率也不一样
2、串口的HAL库驱动程序
串口驱动的头文件位置在stm32f1xx_hal_uart.h中,串口操作常用的函数如下
分组 | 函数名 | 功能描述 |
---|---|---|
初始化和总体功能 | HAL_UART_Init(UART_HandleTypeDef *huart) | 串口初始化,设置串口通信参数 |
HAL_UART_MspInit(UART_HandleTypeDef *huart) | 串口初始化的MSP弱函数,在HAL_UART_Init中被调用,重新实现这个函数一般用于串口引脚GPIO初始化和中断设置 | |
初始化和总体功能 | HAL_UART_GetState(const UART_HandleTypeDef *huart) | 获取串口当前状态 |
HAL_UART_GetError(const UART_HandleTypeDef *huart) | 返回串口错误代码 | |
阻塞式传输 | HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) | 阻塞方式发送一个缓冲区的数据,发送完成或超时才返回 |
HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) | 阻塞方式将数据接收到一个缓冲区,接收完成或者超时才返回 | |
中断方式传输 | HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) | 以中断方式发送一个缓冲区的数据 |
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) | 以中断方式将指定长度的数据接受到缓冲区 | |
DMA方式传输 | HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) | 以DMA方式发送一个缓冲区的数据 |
HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) | 以DMA方式将指定长度的数据接受到缓冲区 | |
HAL_UART_DMAPause(UART_HandleTypeDef *huart) | 暂停DMA传输过程 | |
HAL_UART_DMAResume(UART_HandleTypeDef *huart) | 继续之前的暂停的DMA传输过程 | |
HAL_UART_DMAStop(UART_HandleTypeDef *huart) | 中止DMA传输过程 | |
取消数据传输 | HAL_UART_Abort(UART_HandleTypeDef *huart) | 终止以中断或DMA形式启动的传输过程,自身以阻塞方式运行 |
HAL_UART_AbortTransmit(UART_HandleTypeDef *huart) | 终止以中断或者DMA形式启动的数据发送过程,函数自身以阻塞方式运行 | |
HAL_UART_AbortReceive(UART_HandleTypeDef *huart) | 终止以中断或DMA形式启动的接收过程,自身以阻塞方式运行 | |
HAL_UART_Abort_IT(UART_HandleTypeDef *huart) | 终止以中断或DMA形式启动的传输过程,自身以非阻塞方式运行 | |
HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart) | 终止以中断或者DMA形式启动的数据发送过程,函数自身以非阻塞方式运行 | |
HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart) | 终止以中断或DMA形式启动的接收过程,自身以非阻塞方式运行 |
介绍几个函数的用法 函数原型 = 函数实例
HAL_UART_Init(UART_HandleTypeDef *huart) = HAL_UART_Init(&huart1)
这个函数用于初始化,参数huart是UART_HandleTypeDef类型的指针,是串口外设对象指针,在CubeMX生成的串口程序文件中usart.c中,会有一个串口定义外设指针变量,如UART_HandleTypeDef huart1;
HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) = HAL_UART_Transmit(&huart1, (uint8_t *)data_buff, 3, 200)
(uint8_t *)data_buff是一个长度为3的数组 uint8_t data_buff[3];
这个函数是以阻塞式发送数据的,其实就是轮询模式,第一个参数我们已经介绍过了,const uint8_t *pData 第二个参数是需要发送的数据,而第三个参数 uint16_t Size 则是指需要发送的数据长度(字节)最后一个参数 uint32_t Timeout 则是用于超时时间的表示,单位为ms,发送和接收函数都是同样的用法不再过多介绍
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) = HAL_UART_Transmit_IT(&huart1, (uint8_t *)data_buff,3)
这个函数是以中断模式来发送数据的,其使用方法和轮询模式没什么区别,只不过少了超时时间而已,它发送成功后可不代表着数据发送完成了,数据发送结束后,会触发中断并进入回调函数内,若要在那处理一些问题,就要重新实现这个回调函数 HAL_UART_TxCpltCallback()
uint8_t rxBuffer[10]; HAL_UART_Receive_IT(&huart1,rxBuffer,10);
而接收的中断函数同样存在回调函数 HAL_UART_RxCpltCallback() ,我们在使用这个函数时 HAL_UART_Receive_IT 要注意它的一些特性
1、这个函数执行一次只能接受固定长度的数据,即使设置为只能接受1字节的数据
2、在完成数据接收后会自动关闭接收中断,不会再继续接收数据,也就是说这个函数是一次性的,如果要再接收下一批数据,需要再次执行这个函数
它的这些特性,使其在处理不确定长度,不确定输入时间的串口输入时会比较麻烦,需要做一些特殊的处理,我们在后面的实例中会介绍处理方法
3、STM32CubeMX的配置
打开串口1,在Mode这里我们选择异步通信,这也是串口中最常用的通信
这下面我们一般默认就行,但是要记住这些参数
最后不要忘记打开中断和设置对应的接收和发送引脚
重定向printf和scanf函数,别忘记添加stdio.h头文件
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
不要忘记接收函数会在接收之后关闭函数,我们要在重新编写接收回调函数,同时再次开启接收函数
/**
* @brief 串口数据接收回调函数
数据处理在这里进行
* @param huart:串口句柄
* @retval 无
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) /* 如果是串口1 */
{
HAL_UART_Receive_IT(&huart1,(uint8_t *)data_buff, 1);
}
}
现在我们就可以愉快的使用串口通信了
while (1)
{
/* USER CODE END WHILE */
printf("测试\n");
HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}