【正点原子STM32连载】第十三章 串口通信实验 摘自【正点原子】APM32E103最小系统板使用指南

本文主要是介绍【正点原子STM32连载】第十三章 串口通信实验 摘自【正点原子】APM32E103最小系统板使用指南,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1)实验平台:正点原子APM32E103最小系统板
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban

第十三章 串口通信实验

本章将介绍使用串口进行数据的收发操作,具体实现APM32E103与上位机软件的数据通信,APM32E103将接受自上位机软件的数据原原本本地发送回给上位机软件。通过本章的学习,读者将学习到USART和GPIO引脚复用的使用。
本章分为如下几个小节:
13.1 硬件设计
13.2 程序设计
13.3 下载验证

13.1 硬件设计
13.1.1 例程功能

  1. 回显串口接收到的数据
  2. 每间隔一定时间,串口发送一段提示信息
  3. LED0闪烁,提示程序正在运行
    13.1.2 硬件资源
  4. USART1(PA9、PA10连接至板载USB转串口芯片上)
  5. LED
    LED0 - PB5
    13.1.3 原理图
    本章实验使用的USART1通过跳线帽与板载的USB转串口芯片连接,其原理图如下图所示:

在这里插入图片描述

图13.1.3.1 USART1与USB转串口芯片跳线帽连接

因此在进行本章实验之前,需确保上图位置中正确安装了跳线帽
在这里插入图片描述

图13.1.3.2 串口通信跳线帽位置
板载的USB转串口芯片的USB接口通过板载的USB UART端口引出,其原理图如下图所示:
在这里插入图片描述

图13.1.3.3 USB转串口芯片相关原理图
从以上原理图可以看出,PA9引脚和PA10引脚分别作为发送和接收引脚分别与USB转串口芯片的接收和发送引脚进行连接,USB转串口芯片再通过一对USB差分信号连接至USB UART的接口,这样一来,APM32E103就可以通过USB与PC上位机软件进行串口通信了。
13.2 程序设计
13.2.1 Geehy标准库的GPIO驱动
针对本章的实验要求,需要将串口发送引脚配置成复用推挽输出模式,而串口接收引脚配置成上拉输入模式。
13.2.2 Geehy标准库的USART驱动
Geehy标准库的USART驱动提供了操作APM32E103片上USART的各种API函数,其中就包括配置USART、使能USART等函数,本章实验还是能了USART中断用于接收USART数据。配置并使用USART收发数据的步骤。配置USART的具体步骤如下所示:
①:配置USART
②:使能USART
③:使能USART接收缓冲区非空中断
④:使能USART中断,并配置其相关的中断优先级
在Geehy标准库中对应的驱动函数如下:
①:配置USART
该函数用于配置USART的各项参数,其函数的原型如下所示:
void USART_Config(USART_T* usart, USART_Config_T* usartConfig);
该函数的形参描述,如下表所示:
在这里插入图片描述

表13.2.2.1 函数USART_Config()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表13.2.2.2 函数USART_Config()返回值描述
该函数使用USART_Config_T类型的结构体变量传入USART外设的配置参数,该结构体的定义如下所示:

/*** @brief   USART Word Length define*/
typedef enum
{USART_WORD_LEN_8B = 0,					/* 8位数据长度 */USART_WORD_LEN_9B = BIT12				/* 9位数据长度 */
} USART_WORD_LEN_T;/*** @brief   USART Stop bits define*/
typedef enum
{USART_STOP_BIT_1   = 0,				    /* 1比特停止位 */USART_STOP_BIT_0_5 = BIT12,				/* 0.5比特停止位 */USART_STOP_BIT_2   = BIT13,				/* 2比特停止位 */USART_STOP_BIT_1_5 = BIT12 | BIT13		/* 1.5比特停止位 */
} USART_STOP_BIT_T;/*** @brief   USART Parity define*/
typedef enum
{USART_PARITY_NONE  = 0,					/* 无校验 */USART_PARITY_EVEN  = BIT10,				/* 偶校验 */USART_PARITY_ODD   = BIT10 | BIT9		/* 奇校验 */
} USART_PARITY_T;/*** @brief   USART mode define*/
typedef enum
{USART_MODE_RX      = BIT2,				/* 接收模式 */USART_MODE_TX      = BIT3,				/* 发送模式 */USART_MODE_TX_RX   = BIT2 | BIT3		/* 收发模式 */
} USART_MODE_T;/*** @brief   USART hardware flow control define*/
typedef enum
{USART_HARDWARE_FLOW_NONE    = 0,		/* 无硬件流控 */USART_HARDWARE_FLOW_RTS     = BIT8,	/* RTS硬件流控 */USART_HARDWARE_FLOW_CTS     = BIT9,			/* CTS硬件流控 */USART_HARDWARE_FLOW_RTS_CTS = BIT8 | BIT9		/* RTS和CTS硬件流控 */
} USART_HARDWARE_FLOW_T;/*** @brief   USART Config struct definition*/
typedef struct
{uint32_t                  baudRate;           /* 通信波特率 */USART_WORD_LEN_T          wordLength;         /* 数据宽度 */USART_STOP_BIT_T          stopBits;           /* 停止位 */USART_PARITY_T            parity;             /* 校验位 */USART_MODE_T              mode;               /* 模式 */USART_HARDWARE_FLOW_T     hardwareFlow;       /* 硬件流控 */
} USART_Config_T;
该函数的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_usart.h"void example_fun(void)
{USART_Config_T usart_init_struct;/* 配置USART1 */usart_init_struct.baudRate		= 115200;usart_init_struct.wordLength	= USART_WORD_LEN_8B;usart_init_struct.stopBits		= USART_STOP_BIT_1;usart_init_struct.parity		= USART_PARITY_NONE;usart_init_struct.mode			= USART_MODE_TX_RX;usart_init_struct.hardwareFlow	= USART_HARDWARE_FLOW_NONE;USART_Config(USART1, &usart_init_struct);
}

②:使能USART
该函数用于使能USART外设,其函数原型如下所示:
void USART_Enable(USART_T* usart);
该函数的形参描述,如下表所示:
形参 描述
usart 指向USART外设结构体的指针
例如:USART1、UART4等(在apm32e10x.h文件中有定义)
表13.2.2.3 函数USART_Enable()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表13.2.2.4 函数USART_Enable()返回值描述
该函数的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_usart.h"void example_fun(void)
{/* 使能USART1 */USART_Enable(USART1);
}

③:使能USART指定的中断
该函数用于使能USART指定的中断,其函数原型如下所示:
void USART_EnableInterrupt(USART_T* usart, USART_INT_T interrupt);
该函数的形参描述,如下表所示:
形参 描述
usart 指向USART外设结构体的指针
例如:USART1、UART4等(在apm32e10x.h文件中有定义)
interrupt 指定的USART中断源
例如:USART_INT_RXBNE、USART_INT_TXC等(在apm32e10x_usart.h文件中有定义)
表13.2.2.5 函数USART_EnableInterrupt()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表13.2.2.6 函数USART_EnableInterrupt()返回值描述
该函数的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_usart.h"void example_fun(void)
{/* 使能USART1的接收缓冲区非空中断 */USART_EnableInterrupt(USART1, USART_INT_RXBNE);/* 使能USART1的发送完成中断 */USART_EnableInterrupt(USART1, USART_INT_TXC);
}

④:配置USART中断
请见第12.2.2小节中配置中断的相关内容。
使用USART发送数据的具体步骤如下所示:
①:等待USART发送缓冲区为空
②:往USART发送缓冲区写入数据
在Geehy标准库中对应的驱动函数如下:
①:获取USART状态标志
该函数用于获取USART的状态标志,其函数原型如下所示:
uint8_t USART_ReadStatusFlag(USART_T* usart, USART_FLAG_T flag);
该函数的形参描述,如下表所示:
形参 描述
usart 指向USART外设结构体的指针
例如:USART1、UART4等(在apm32e10x.h文件中有定义)
flag 指定获取的状态标志
例如:USART_FLAG_RXBNE、USART_FLAG_TXC等(在apm32e10x_usart.h文件中有定义)
表13.2.2.7 函数USART_ReadStatusFlag()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
SET 状态标志有效
RESET 状态标志无效
表13.2.2.8 函数USART_ReadStatusFlag()返回值描述
该函数的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_usart.h"void example_fun(void)
{uint8_t status;/* 读取USART1外设的发送缓冲区为空状态标志 */status = USART_ReadStatusFlag(USART1, USART_FLAG_TXBE);if (status == SET){/* Do something. */}else{/* Do something. */}
}

②:USART发送单个数据
该函数用于使用USART发送单个数据,其函数原型如下所示:
void USART_TxData(USART_T* usart, uint16_t data);
该函数的形参描述,如下表所示:
形参 描述
usart 指向USART外设结构体的指针
例如:USART1、UART4等(在apm32e10x.h文件中有定义)
data 待发送的数据
表13.2.2.9 函数USART_TxData()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表13.2.2.10 函数USART_TxData()返回值描述
该函数的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_usart.h"void example_fun(void)
{uint8_t data;/* 准备数据 */data = 0xFF;/* 通过USART1发送单个数据 */USART_TxData(USART1, (uint16_t)data);
}

使用USART接收数据的具体步骤如下所示:
①:判断USART接收缓冲区非空
②:读取USART接收缓冲区中的数据
在Geehy标准库中对应的函数如下:
①:获取USART状态标志
请见第13.2.2小节中获取USART状态标志的相关内容。
②:获取USART接收到的单个数据
该函数用于获取USART获取到的单个数据,其函数原型如下所示:
uint16_t USART_RxData(USART_T* usart);
该函数的形参描述,如下表所示:
形参 描述
usart 指向USART外设结构体的指针
例如:USART1、UART4等(在apm32e10x.h文件中有定义)
表13.2.2.11 函数USART_RxData()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
uint16_t类型数据 获取到的USART接收到的一个数据
表13.2.2.12 函数USART_RxData()返回值描述
该函数的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_usart.h"void example_fun(void)
{uint8_t data;/* 接收USART1接收到的一个数据 */data = USART_RxData(USART1);/* Do something. */
}

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{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); }while(0)#define USART_RX_GPIO_PORT          GPIOA
#define USART_RX_GPIO_PIN           GPIO_PIN_10
#define USART_RX_GPIO_CLK_ENABLE()  do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); }while(0)#define USART_UX                    USART1
#define USART_UX_IRQn               USART1_IRQn
#define USART_UX_IRQHandler         USART1_IRQHandler
#define USART_UX_CLK_ENABLE()       do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1); }while(0)

串口通讯驱动中,USART1的初始化函数,如下所示:

/*** @brief       初始化串口* @param       baudrate: 通讯波特率* @retval      无*/
void usart_init(uint32_t baudrate)
{GPIO_Config_T gpio_init_struct = {0};USART_Config_T usart_init_struct = {0};/* 使能时钟 */USART_UX_CLK_ENABLE();USART_TX_GPIO_CLK_ENABLE();USART_RX_GPIO_CLK_ENABLE();/* 初始化串口发送引脚 */gpio_init_struct.pin = USART_TX_GPIO_PIN;gpio_init_struct.speed = GPIO_SPEED_50MHz;gpio_init_struct.mode = GPIO_MODE_AF_PP;GPIO_Config(USART_TX_GPIO_PORT, &gpio_init_struct);/* 初始化串口接收引脚 */gpio_init_struct.pin = USART_RX_GPIO_PIN;gpio_init_struct.speed = GPIO_SPEED_50MHz;gpio_init_struct.mode = GPIO_MODE_IN_PU;GPIO_Config(USART_RX_GPIO_PORT, &gpio_init_struct);/* 初始化串口 */usart_init_struct.baudRate = baudrate;                      /* 通讯波特率 */usart_init_struct.wordLength = USART_WORD_LEN_8B;           /* 数据位 */usart_init_struct.stopBits = USART_STOP_BIT_1;              /* 停止位 */usart_init_struct.parity = USART_PARITY_NONE;               /* 校验位 */usart_init_struct.mode = USART_MODE_TX_RX;                  /* 收发模式 */usart_init_struct.hardwareFlow = USART_HARDWARE_FLOW_NONE;  /* 无硬件流控 */USART_Config(USART_UX, &usart_init_struct);USART_Enable(USART_UX);#if (USART_EN_RX != 0)USART_EnableInterrupt(USART_UX, USART_INT_RXBNE);USART_ClearStatusFlag(USART_UX, USART_FLAG_RXBNE);NVIC_EnableIRQRequest(USART_UX_IRQn, 0, 0);
#endif  
}

在串口通信的初始化函数中,在使能USART1收发引脚的GPIO端口时钟和USART1外设时钟后,配置了USART1发送引脚(USART_TX_GPIO_PORT)为复用推挽输出模式,并且配置了USART1接收引脚(USART_RX_GPIO_PORT)为上拉输入模式。在最后使能了USART1,同时也配置了USART1的接收缓冲区非空中断,这么一来,USART1的中断回调函数就会在USART1接收到数据的时候被调用。
串口通讯驱动中,USART1的中断回调函数,如下所示:

/*** @brief       串口中断服务函数* @param       无* @retval      无*/
void USART_UX_IRQHandler(void)
{if (USART_ReadIntFlag(USART_UX, USART_INT_RXBNE) == SET){
#if (SYS_SUPPORT_OS != 0)OSIntEnter();
#endifg_rx_buffer[0] = USART_RxData(USART_UX);    /* 接收一字节数据 */if ((g_usart_rx_sta & 0x8000) == 0)         /* 接收未完成 */{if (g_usart_rx_sta & 0x4000)            /* 接收到了0x0D */{if (g_rx_buffer[0] != 0x0A){g_usart_rx_sta = 0;             /* 接收错误,重新开始接收 */}else{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;         /* 接收错误,重新开始接收 */}}}}#if (SYS_SUPPORT_OS != 0)OSIntExit();
#endifUSART_ClearIntFlag(USART_UX, USART_INT_RXBNE);}}

在USART1的中断回调函数中主要用于读取USART1接收到的数据,并将其逐一存入接收的缓冲区,并在接收到“回车”和“换行”后标志数据接收完成。
13.2.4 实验应用代码
本实验的应用代码,如下所示:

int main(void)
{uint8_t len, i;uint16_t times = 0;NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4);  /* 设置中断优先级分组为组4 */sys_apm32_clock_init(15);                         /* 配置系统时钟 */delay_init(120);                                  /* 初始化延时功能 */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");for (i = 0;i < len;i++){USART_TxData(USART_UX, g_usart_rx_buf[i]);while (USART_ReadStatusFlag(USART_UX, USART_FLAG_TXBE)==RESET);}printf("\r\n\r\n");                      /* 插入换行 */g_usart_rx_sta = 0;}else{times++;if (times % 1000 == 0){printf("\r\n正点原子 APM32E103最小系统板 串口实验\r\n");printf("正点原子@ALIENTEK\r\n\r\n\r\n");}if (times % 200 == 0){printf("请输入数据,以回车键结束\r\n");}if (times % 30 == 0){LED0_TOGGLE();                     /* LED0翻转,提示系统正在运行 */}delay_ms(10);}}
}

本实验的实验代码很简单,在完成初始化后,就不断地通过串口通信驱动提供的数据接收完成标志判断数据是否接收完毕,若还未完成数据接收,则每间隔一段时间就使用printf函数通过USART1打印一段提示信息,若数据接收完毕,则将数据原原本本地使用printf函数通过USART1打印出去,实现数据的回显功能。
13.3 下载验证
在完成编译和烧录操作后,需要将开发板的USB UART接口与PC的USB接口通过具有数据传输功能的数据线进行连接,并保证13.1.3小节中指示跳线帽已正确安装。接着打开PC上的ATK-XCOM串口调试助手软件,选择好正确的COM端口和相关的配置后,就能看到串口调试助手上每间隔一段时间就打印一次“请输出数据,以回车键结束”,接下来就可以根据提示通过串口调试助手发送一段任意的数据(以回车换行结束),随后立马就能看到串口调试助手上显示发送出去的数据,这就是本实验实现的数据回显功能。

这篇关于【正点原子STM32连载】第十三章 串口通信实验 摘自【正点原子】APM32E103最小系统板使用指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/496597

相关文章

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Debian如何查看系统版本? 7种轻松查看Debian版本信息的实用方法

《Debian如何查看系统版本?7种轻松查看Debian版本信息的实用方法》Debian是一个广泛使用的Linux发行版,用户有时需要查看其版本信息以进行系统管理、故障排除或兼容性检查,在Debia... 作为最受欢迎的 linux 发行版之一,Debian 的版本信息在日常使用和系统维护中起着至关重要的作

什么是cron? Linux系统下Cron定时任务使用指南

《什么是cron?Linux系统下Cron定时任务使用指南》在日常的Linux系统管理和维护中,定时执行任务是非常常见的需求,你可能需要每天执行备份任务、清理系统日志或运行特定的脚本,而不想每天... 在管理 linux 服务器的过程中,总有一些任务需要我们定期或重复执行。就比如备份任务,通常会选在服务器资

TP-LINK/水星和hasivo交换机怎么选? 三款网管交换机系统功能对比

《TP-LINK/水星和hasivo交换机怎么选?三款网管交换机系统功能对比》今天选了三款都是”8+1″的2.5G网管交换机,分别是TP-LINK水星和hasivo交换机,该怎么选呢?这些交换机功... TP-LINK、水星和hasivo这三台交换机都是”8+1″的2.5G网管交换机,我手里的China编程has