STM32第十二节(中级篇):串口通信(第二节)——串口固件库函数以及串口发送和接收代码讲解

news2024/11/15 23:45:19

STM32第十二节(中级篇):串口通信(第二节)——串口固件库函数以及串口发送和接收代码讲解


串口固件库函数

代码片段

/** 
  * @brief  USART Init Structure definition  
  */ 
  
typedef struct
{
  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                           The baud rate is computed using the following formula:
                                            - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */

  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref USART_Word_Length */

  uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref USART_Stop_Bits */

  uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref USART_Parity
                                           @note When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */
 
  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref USART_Mode */

  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                           or disabled.
                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;

        本节课的代码是基础的配置,在后续学习以及编写代码的时候有很大的作用在上述代码中,就是对于USART结构体的初始化,我们可以在野火的资料盘中找到,在stm32f10x_usart.h文件中可以找到。我们观察这段代码,逐行解释代码部分。

结构体参数解释

        uint32 _t USART BaudRate;        //波特率 BRR

        uint16_t USART WordLength;     //字长 CR_1/M

        uint16_t USART StopBits;           //停止位 CR_2/STOP

        uint16_t USART Parity;               //校验控制 CR_1 PCE、CR_1 PS 

        uint16_t USART Mode;               //模式选择CR_1 TE、CR_1 RE

        // 硬件流选择 CR_3 CTSE、CR_3 RTSE:

        uintl6_t USART HardwareFlowControl;

结构体参数配置

        字长可以设置为八位或九位,详细内容在上节课有细致讲到。

        每一段数据传输的时候都要有停止位(STOP),对于STOP来说,有四个可选择的时间段。

        如果有效验位的话,会分为奇效验和偶效验两种效验方式,当然也可以选择没有效验位。

        对于USART模式上的选择来说,有输入数据和输出数据的选择。

/** @defgroup USART_Word_Length 
  * @{
  */ 
  
#define USART_WordLength_8b                  ((uint16_t)0x0000)
#define USART_WordLength_9b                  ((uint16_t)0x1000)
                                    
#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WordLength_8b) || \
                                      ((LENGTH) == USART_WordLength_9b))

/** @defgroup USART_Stop_Bits 
  * @{
  */ 
  
#define USART_StopBits_1                     ((uint16_t)0x0000)
#define USART_StopBits_0_5                   ((uint16_t)0x1000)
#define USART_StopBits_2                     ((uint16_t)0x2000)
#define USART_StopBits_1_5                   ((uint16_t)0x3000)
#define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_StopBits_1) || \
                                     ((STOPBITS) == USART_StopBits_0_5) || \
                                     ((STOPBITS) == USART_StopBits_2) || \
                                     ((STOPBITS) == USART_StopBits_1_5))

/** @defgroup USART_Parity 
  * @{
  */ 
  
#define USART_Parity_No                      ((uint16_t)0x0000)
#define USART_Parity_Even                    ((uint16_t)0x0400)
#define USART_Parity_Odd                     ((uint16_t)0x0600) 
#define IS_USART_PARITY(PARITY) (((PARITY) == USART_Parity_No) || \
                                 ((PARITY) == USART_Parity_Even) || \
                                 ((PARITY) == USART_Parity_Odd))

/** @defgroup USART_Mode 
  * @{
  */ 
  
#define USART_Mode_Rx                        ((uint16_t)0x0004)
#define USART_Mode_Tx                        ((uint16_t)0x0008)
#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00))

/** @defgroup USART_Hardware_Flow_Control 
  * @{
  */ 
#define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
#define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
#define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
#define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)
#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL)\
                              (((CONTROL) == USART_HardwareFlowControl_None) || \
                               ((CONTROL) == USART_HardwareFlowControl_RTS) || \
                               ((CONTROL) == USART_HardwareFlowControl_CTS) || \
                               ((CONTROL) == USART_HardwareFlowControl_RTS_CTS))

        以上就是有关结构体的参数构建,这个是最基本都要会的结构体,当然,还有同步时钟初始化结构体的相关构建。

同步时钟初始化结构体

代码展示

typedef struct
{

  uint16_t USART_Clock;   /*!< Specifies whether the USART clock is enabled or disabled.
                               This parameter can be a value of @ref USART_Clock */

  uint16_t USART_CPOL;    /*!< Specifies the steady state value of the serial clock.
                               This parameter can be a value of @ref USART_Clock_Polarity */

  uint16_t USART_CPHA;    /*!< Specifies the clock transition on which the bit capture is made.
                               This parameter can be a value of @ref USART_Clock_Phase */

  uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted
                               data bit (MSB) has to be output on the SCLK pin in synchronous mode.
                               This parameter can be a value of @ref USART_Last_Bit */
} USART_ClockInitTypeDef;

结构体配置

/** @defgroup USART_Clock 
  * @{
  */ 
#define USART_Clock_Disable                  ((uint16_t)0x0000)
#define USART_Clock_Enable                   ((uint16_t)0x0800)
#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_Clock_Disable) || \
                               ((CLOCK) == USART_Clock_Enable))

/** @defgroup USART_Clock_Polarity 
  * @{
  */
  
#define USART_CPOL_Low                       ((uint16_t)0x0000)
#define USART_CPOL_High                      ((uint16_t)0x0400)
#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CPOL_Low) || ((CPOL) == USART_CPOL_High))

/** @defgroup USART_Clock_Phase
  * @{
  */

#define USART_CPHA_1Edge                     ((uint16_t)0x0000)
#define USART_CPHA_2Edge                     ((uint16_t)0x0200)
#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CPHA_1Edge) || ((CPHA) == USART_CPHA_2Edge))


/** @defgroup USART_Last_Bit
  * @{
  */

#define USART_LastBit_Disable                ((uint16_t)0x0000)
#define USART_LastBit_Enable                 ((uint16_t)0x0100)
#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LastBit_Disable) || \
                                   ((LASTBIT) == USART_LastBit_Enable))

串口编程常用函数

        我们在编程的时候常用的几个固件库函数一共有六个。接下来就仔细地为大家讲一下这六个函数。分别是串口初始化函数,中断配置函数,串口使能函数,数据发送函数,数据接收函数,中断状态位获取函数。

        串口初始化函数(void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);)

        中断配置函数(void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);)

        串口使能函数(void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);)

        数据发送函数(void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);)

        数据接收函数(void USART_SendBreak(USART_TypeDef* USARTx);)

        中断状态位获取函数(ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);)

        至此,全部理论部分就结束了,接下来就是代码的讲解:

串口发送和接收

硬件设计

                                                        TTL转USB电平(要有CH340驱动)

        今天所编写的第一个代码要求如下:

        单片机给电脑发送数据,电脑上位机把数据打印出来;

        电脑上位机给单片机发数据,单片机接收到数据之后立马发回给电脑,并打印出来。

编程流程

1.初始化串口需要用到的GPIO

        这些代码都放在了bsp_usart.h文件中,采用宏定义把我们所需要的usart串口所需要的GPIO引脚定义好:

// 串口1-USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler
2.初始化串口,USART_InitTypeDef,使能串口,中断配置(接收中断,中断优先级)

        首先,我们先定义结构体GPIO_InitTypeDef GPIO_InitStructure和USART_InitTypeDef USART_InitStructure;然后配置GPIO,首先打开APB2_GPIOA的时钟。然后就是串口外设的时钟,再接着就配置GPIO模式(老三套);配置USART Rx位浮空输入模式;就是我们刚刚讲的那几个串口结构体参数配置;

void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
	
	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

	// 将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	// 配置串口的工作参数
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 配置 针数据字长
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	// 配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	// 配置校验位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	// 配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = 
	USART_HardwareFlowControl_None;
	// 配置工作模式,收发一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	// 完成串口的初始化配置
	USART_Init(DEBUG_USARTx, &USART_InitStructure);
	
	// 串口中断优先级配置
	NVIC_Configuration();
	
	// 使能串口接收中断
	USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);	
	
	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);	    
}

        在电脑上位机向单片机传输数据时会有中断的产生,所以我们在这里还要配置中断函数,调节中断优先值,最后使能串口。

3.编写中断服务函数
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 嵌套向量中断控制器组选择 */
	/* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组*/
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
  /* 抢断优先级*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}
4.编写发送和接收函数

        那么我们可以试着编写一个固件库函数使得我们可以发送一个字节:

        首先我们确定参数输入,指定需要的串口,和一个字节的数据(只能是八位);接下来找到SendData函数,第一个形参为串口名,第二个形参为八位的数据;根据上节课的知识,应该是发送数据寄存器为空。我们进入循环,判断USART_GetFlagStatus(形参为串口名和USART_FLAG_TXE位)是否为空。

/*****************  发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
	/* 发送一个字节数据到USART */
	USART_SendData(pUSARTx,ch);
		
	/* 等待发送数据寄存器为空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

 小结

        创作不易,点个三连关注一下吧!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2050077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.初识算法

1.1 算法无处不在 当我们听到“算法”这个词时&#xff0c;很自然地会想到数学。然而实际上&#xff0c;许多算法并不涉及复杂数学&#xff0c;而是更多地依赖基本逻辑&#xff0c;这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前&#xff0c;有一个有趣的事实值…

科研单位所需要的文件自动同步备份软件具有哪些特征?

科研单位进行文件同步备份是保障数据安全、提高工作效率、符合法规要求以及实现数据共享与再利用的重要措施。文件同步备份不仅能保护科研单位的研究成果&#xff0c;还能提升工作协同效率&#xff0c;具体优势体现在&#xff1a; 预防数据丢失&#xff1a;科研单位在工作中会产…

还不了解 Pinia 状态管理库⁉️

还不了解 Pinia 状态管理库⁉️&#x1f34d; 什么是Pinia❓状态管理工具⁉️&#xff1a; 学习过Vue2的小伙伴&#xff0c;一定都知道Vuex&#xff0c;什么不知道&#xff0c;请看VCR&#x1f449; &#xff1b; Vuex 是一个专为 Vue.js 应用程序设计的状态管理库&#xff0…

什么是GD32 MCU读保护?

如今电子产品市场风云变幻&#xff0c;暗流汹涌&#xff0c;有没有小伙伴遇到自己费了大力气写出来的代码&#xff0c;很容易就被别人“借鉴”了&#xff0c;真的是让闻者伤心&#xff0c;听着落泪啊。 那有没有什么方法可以防止别人将你的代码从MCU读出来呢&#xff1f;答案当…

软媒市场-解释软文发布后如何在搜索引擎持续获得曝光

软文发布后,在搜索引擎持续获得曝光是一个涉及多方面策略的过程。以下是一些关键步骤和技巧,旨在帮助软文在搜索引擎中保持较高的可见度和曝光率: 1. 关键词优化 关键词选择:首先,通过专业的关键词研究工具(如Google AdWords Keyword Planner、百度指数等)分析用户搜索习惯和热…

【C语言初阶】掌握C语言调试技巧,迈向高效编程的阶梯

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C语言 “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C语言指针 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀C语言调试技巧 &#x1f4d2;1. …

这个是git使用的合集

如果遇到了关于git和github的bug就会写这里 2024/8/16 github一直没有打卡和上传代码是因为感觉除了做项目的情况&#xff0c;普通的学习和普通的笔记没必要记在github里&#xff1b;如果是笔记类的东西为什么不记在csdn上呢&#xff1f;如果是算法题算法网站上回有记录啊&am…

第43课 Scratch入门篇:雪花随风飘

雪花随风飘 故事背景: 雪花轻轻地从灰蒙蒙的天空中飘落下来,它们像是天空中飘洒下来的羽毛,又像是冬日的精灵在翩翩起舞。每一片雪花都独一无二,它们在空中旋转、飘荡,最终缓缓降落在屋顶、树枝、街道和行人的肩头。 程序原理: 众多的雪花肯定是克隆功能,降落过程是通过…

three.js 光源、光源辅助对象和阴影简介

Three.js 光源对物体的影响 实际生活中物体表面的明暗效果是会受到光照的影响&#xff0c;比如晚上不开灯&#xff0c;你就看不到物体&#xff0c;灯光比较暗&#xff0c;物体也比较暗。在threejs中&#xff0c;咱们用网格模型Mesh模拟生活中物体&#xff0c;所以threejs中模拟…

Linux进程间通信学习记录(IPC 机制以及共享内存)

0.System V IPC机制&#xff1a; ①.IPC对象包含&#xff1a;共享内存、消息队列和信号灯集。 ②.每个IPC对象有唯一的ID。 ③.IPC对象创建后一直存在&#xff0c;直到被显示地删除。 ④.每一个IPC对象有一个关联的KEY。&#xff08;其他进程通过KEY访问对应的IPC对象&#xff…

索引的设计原则

4.索引的设计原则 4.1.数据准备 a.创建数据库、创建表 CREATE DATABASE atguigudb1; USE atguigudb1;# 创建学生表和课程表 CREATE TABLE student_info (id INT(11) AUTO_INCREMENT,student_id INT NOT NULL ,name VARCHAR(20) DEFAULT NULL,course_id INT NOT NULL ,class_…

x64汇编语言与逆向工程实战指南(四)

目录 1. 数组的存储与遍历1.1 编写数组数据写入内存1.2 汇编循环遍历数组元素 3. Lea指令4. mul指令与imul指令4.1 mul 指令4.2 imul 指令总结 5. div指令5.1 div 指令的基本原理5.2 8 位除法5.3 16 位除法5.3 32 位除法特点和要求 1. 数组的存储与遍历 1.1 编写数组数据写入内…

基于Web的可回收物品收购系统-计算机毕业设计源码49082

摘 要 随着电子商务和在线交易的快速发展&#xff0c;二手商品市场逐渐成为一个不可忽视的经济领域。其中&#xff0c;可回收系统的收购成为了一个关键环节&#xff0c;它不仅有助于资源的有效再利用&#xff0c;还对环境保护和可持续发展起到了积极的推动作用。Servlet可回收…

单片机中的存储器讲解

单片机中的存储器 目录 单片机中的存储器常用的存储器易失性存储器RAMSRAMDRAM 非易失性存储器ROMMask ROMPROMEPROME2PROMFlashNOR FlashNADN Flash 单片机里全局变量、局部变量、堆、栈的存储区域区域介绍栈区堆区静态区代码区常量区 内存分区分类四个区域 常用的存储器 易失…

【Linux】:实现一个简易的shell

目录 1.命令行提示符 2.命令行参数 2.1 获取命令行参数 2.2 解析命令行参数 3.判断指令类型 3.1 模拟cd命令 3.2 模拟export和echo bash的环境变量来源 4.外部指令的执行 1.命令行提示符 在我们输入指令前&#xff0c;终端界面一般有一个命令行提示符&#xff0c; …

性能优化理论篇 | swap area是个什么东西

我们知道每台计算机的内存&#xff08;RAM&#xff09;都是有限的&#xff0c;而我们的应用程序需要加载到内存才能被运行&#xff0c;如果一台机器运行多个应用程序时&#xff0c;内存可能会耗尽。Linux 系统中的“交换空间&#xff08;也称为交换分区&#xff09;”可以帮助缓…

VM相关配置及docker

NAT——VMnet8网卡 桥接——WLAN/网线 仅主机——VMnet1网卡 docker与虚拟机的区别 启动docker服务 systemctl start docker 重启 systemctl start docker关闭docker服务 systemctl stop docker.servicedocker的两大概念 镜像&#xff1a;images&#xff0c;应用程序的静态文…

nssctf-[SWPUCTF 2022 新生赛]1z_unserialize-简单的序列化题目

1. 打开题目是一段很简单的php代码 对代码进行分析&#xff0c;题目中有一个__destruct析构函数&#xff0c;这个函数是在对象被销毁的时候触发&#xff0c;那那么在这里new一下就相当于销毁一个对象&#xff0c;$a$this->lt;和$a($this->lly);相当于是$this->lt(thi…

CSS3-新特性

1.新增选择器 1.属性选择器 2.结构伪类选择器 3.伪元素选择器&#xff08;重点&#xff09; 4.CSS3 盒子模型 2.CSS3滤镜filter 3.CSS3 calc 函数 4.CSS3 过渡&#xff08;重点&#xff09;

8月18日微语报,星期日,农历七月十五

8月18日微语报&#xff0c;星期日&#xff0c;农历七月十五&#xff0c;周末愉快&#xff01; 一份微语报&#xff0c;众览天下事&#xff01; 1、南昌从业者谈蔬菜涨价&#xff1a;天热易变质增加损耗&#xff0c;农户收入未明显提升。 2、委员建议“行政教学分离”&#x…