本帖最后由 正点原子运营 于 2024-3-28 14:36 编辑
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板
2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版
6)正点原子STM32技术交流QQ群:725095144
本章将介绍使用串口进行数据的收发操作,具体实现STM32F103与上位机软件的数据通信,STM32F103将接受自上位机软件的数据原原本本地发送回给上位机软件。通过本章的学习,读者将学习到USART和GPIO引脚复用的使用。 本章分为如下几个小节: 13.1 硬件设计 13.2 程序设计 13.3 下载验证
13.1 硬件设计 13.1.1 例程功能 1. 回显串口接收到的数据 2. 每间隔一定时间,串口发送一段提示信息 3. LED0闪烁,提示程序正在运行
13.1.2 硬件资源 1. USART1 USART1_TX - PA9 USART1_RX - PA10 2. LED LED0 - PB5
13.1.3 原理图 本章实验使用的USART1引脚通过排针引出,其原理图如下图所示:
13.2 程序设计 13.2.1 HAL库的GPIO驱动 在前面的章节中,介绍了GPIO引脚在输出模式和输入模式下的使用,但本章要使用GPIO引脚作为串口输出的收发引脚,因此不再是使用输出模式或输入模式,而是要使用GPIO的复用功能模式,例如将PA9引脚复用为USART1的数据发送引脚或将PA10引脚复用为USART1的数据接收引脚,具体的步骤如下: ①:配置GPIO的复用功能 在HAL库中对应的驱动函数如下: ①:配置GPIO的复用功能 请见第10.2.1小节中配置GPIO引脚的相关内容。
13.2.2 HAL库的UART驱动 HAL库的UART驱动提供了操作STM32F103片上UART的各种API函数,其中就包括配置UART、使能UART等函数,本章实验还使能了UART中断用于接收UART数据。配置并使用UART收发数据的步骤。配置UART的具体步骤如下所示: ①:配置UART ②:UART中断接收数据 在HAL库中对应的驱动函数如下: ①:配置USART 该函数用于配置USART的各项参数,其函数的原型如下所示: - HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
复制代码该函数的形参描述,如下表所示: 表13.2.2.1 函数HAL_UART_Init()形参描述 该函数的返回值描述,如下表所示: 表13.2.2.2 函数HAL_UART_Init()返回值描述 该函数需要传入UART的句柄指针,该句柄中就包含了UART的初始化配置参数结构体,该结构体的定义如下所示: - typedef struct
- {
- uint32_t BaudRate; /* 波特率 */
- uint32_t WordLength; /* 位宽 */
- uint32_t StopBits; /* 停止位 */
- uint32_t Parity; /* 校验位 */
- uint32_t Mode; /* 模式 */
- uint32_t HwFlowCtl; /* 硬件流控 */
- uint32_t OverSampling; /* 过采样 */
- }UART_InitTypeDef;
复制代码该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- UART_HandleTypeDef uart_handle = {0};
-
- /* 初始化USART1 */
- uart_handle.Instance = USART1;
- uart_handle.Init.BaudRate = 115200;
- uart_handle.Init.WordLength = UART_WORDLENGTH_8B;
- uart_handle.Init.StopBits = UART_STOPBITS_1;
- uart_handle.Init.Parity = UART_PARITY_NONE;
- uart_handle.Init.Mode = UART_MODE_TX_RX;
- uart_handle.Init.HwFlowCtl =UART_HWCONTROL_NONE;
- uart_handle.Init.OverSampling =UART_OVERSAMPLING_16;
- HAL_UART_Init(&uart_handle);
- }
复制代码①:UART中断接收数据 该函数用于UART中断接收数据,其函数原型如下所示: - HAL_StatusTypeDef HAL_UART_Receive_IT( UART_HandleTypeDef *huart,
- uint8_t *pData,
- uint16_t Size)
复制代码该函数的形参描述,如下表所示: 表13.2.2.3 函数HAL_UART_Receive_IT()形参描述 该函数的返回值描述,如下表所示: 表13.2.2.4 函数HAL_UART_Receive_IT()返回值描述 该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- uint8_t buf[10];
-
- /* UART中断接收数据 */
- HAL_UART_Receive_IT(&uart_handle, buf, sizeof(buf));
- }
复制代码
13.2.3 串口通讯驱动 本实验的串口通信驱动主要是配置USART1并完成一些相关的初始化操作,并支持将printf函数重定向到USART1进行输出,同时向应用层提供了一个数据接收缓冲区和接收完成标志,通过这些,应用层就能够很方便地使用USART1进行数据传输了,本章实验中,串口通讯的驱动代码包括usart.c和usart.h两个文件。 串口通讯驱动中,对GPIO、USART的相关宏定义,如下所示: - #define USART_TX_GPIO_PORT GPIOA
- #define USART_TX_GPIO_PIN GPIO_PIN_9
- #define USART_TX_GPIO_CLK_ENABLE() \
- do { \
- __HAL_RCC_GPIOA_CLK_ENABLE(); \
- } while (0)
- #define USART_RX_GPIO_PORT GPIOA
- #define USART_RX_GPIO_PIN GPIO_PIN_10
- #define USART_RX_GPIO_CLK_ENABLE() \
- do { \
- __HAL_RCC_GPIOA_CLK_ENABLE(); \
- } while (0)
- #define USART_UX USART1
- #define USART_UX_IRQn USART1_IRQn
- #define USART_UX_IRQHandler USART1_IRQHandler
- #define USART_UX_CLK_ENABLE() \
- do { \
- __HAL_RCC_USART1_CLK_ENABLE(); \
- } while (0)
复制代码串口通讯驱动中,USART1的初始化函数,如下所示: - /**
- *@brief 串口X初始化函数
- *@param baudrate: 波特率, 根据自己需要设置波特率值
- *@note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
- * 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
- *@retval 无
- */
- void usart_init(uint32_t baudrate)
- {
- g_uart1_handle.Instance = USART_UX; /* 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_Init()会使能UART1 */
- /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
- HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
- }
复制代码在串口通信的初始化函数中,在使能USART1收发引脚的GPIO端口时钟和USART1外设时钟后,配置了USART1收发引脚的GPIO复用功能和配置其为复用功能模式,并在最后配置并使能了USART1,同时也使能并配置了USART1的接收缓冲区非空中断,这么一来,USART1的中断回调函数就会在USART1接收到数据的时候被调用。 串口通讯驱动中,USART1的接收完成回调函数,如下所示: - /**
- *@brief Rx传输回调函数
- *@param huart: UART句柄类型指针
- *@retval 无
- */
- voidHAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart->Instance == USART_UX)
- {
- if((g_usart_rx_sta & 0x8000) == 0)
- {
- if(g_usart_rx_sta& 0x4000)
- {
- if(g_rx_buffer[0] != 0x0a)
- {
- g_usart_rx_sta = 0;
- }
- else
- {
- g_usart_rx_sta |= 0x8000;
- }
- }
- else
- {
- 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);
- }
- }
复制代码在USART1的接收完成回调函数中主要用于读取USART1接收到的数据,并将其逐一存入接收的缓冲区,并在接收到“回车”和“换行”后标志数据接收完成。
13.2.4 实验应用代码 本章实验的应用代码,如下所示: - int main(void)
- {
- uint16_t len;
- uint16_t times = 0;
-
- HAL_Init(); /* 初始化HAL库 */
- sys_stm32_clock_init(RCC_PLL_MUL9); /* 配置时钟,72MHz */
- delay_init(72); /* 初始化延时 */
- usart_init(115200); /* 初始化串口 */
- led_init(); /* 初始化LED */
-
- while (1)
- {
- if (g_usart_rx_sta & 0x8000) /* 接收到数据 */
- {
- len = g_usart_rx_sta & 0x3FFF;
- printf("\r\n您发送的消息为:\r\n");
- HAL_UART_Transmit( &g_uart1_handle,
- (uint8_t *)g_usart_rx_buf,
- len,
- HAL_MAX_DELAY);
- printf("\r\n\r\n");
- g_usart_rx_sta = 0;
- }
- else
- {
- if ((times % 5000) == 0)
- {
- printf("\r\n正点原子 M144Z-M3最小系统板STM32F103版 \
- 串口通信实验\r\n");
- printf("正点原子@ALIENTEK\r\n\r\n\r\n");
- }
- if ((times % 200) == 0)
- {
- printf("请输入数据,以回车键结束\r\n");
- }
- if ((times % 30) == 0)
- {
- LED0_TOGGLE();
- }
- times++;
- delay_ms(10);
- }
- }
- }
复制代码本实验的实验代码很简单,在完成初始化后,就不断地通过串口通信驱动提供的数据接收完成标志判断数据是否接收完毕,若还未完成数据接收,则每间隔一段时间就使用printf函数通过USART1打印一段提示信息,若数据接收完毕,则将数据原原本本的使用printf函数通过USART1打印出去,实现数据的回显。
13.3 下载验证 在完成编译和烧录操作后,需要将引出USART1引脚的排针通过串口转TTL模块等工具连接至PC。接着打开PC上的ATK-XCOM串口调试助手软件,选择好正确的COM端口和相关的配置后,就能看到串口调试助手上每间隔一段时间就打印一次“请输出数据,以回车键结束”,接下来就可以根据提示通过串口调试助手发送一段任意的数据(以回车换行结束),随后立马就能看到串口调试助手上显示发送出去的数据,这就是本实验实现的数据回显。 |