3.STM32之通信接口《精讲》之USART通信

本节将进行实战,基础了解请查看第二节(Whappy)
开始背!! USART ---》全双工   异步/同步  点对点

USART:STM32自带硬件电路,通过配置相对应的寄存器来设置数据帧的发送,我们收发只需要一个简单的函数,方便我们调用即可!

经过本人总结,完全可以把TX等价为人的嘴巴,RX等价人的耳朵,大脑就相当于人的存储器。这个世界是抽象的,人为定义的,可解和无解的

通过 UART 的基本结构可以看出,系统的主频通过分频器将时钟信号分频为双方约定的波特率,以确保数据传输的同步性。

在数据发送时,首先将数据写入发送数据寄存器(TXD寄存器)进行缓存,接着通过移位寄存器将数据逐位移送,并最终传输到 GPIO 的 TX 引脚进行发送。数据发送的过程涉及两个步骤:先将数据缓冲,再通过移位寄存器逐位传输。

同样,在数据接收时,接收到的信号首先通过接收的移位寄存器进行缓冲,再送到接收数据寄存器中。移位寄存器在接收过程中起到了逐位接收数据的作用,确保数据能够正确地存入接收寄存器中。

简而言之,TX 和 RX 的数据发送和接收都要经过移位寄存器的处理,这样的结构保证了串行数据能够按位正确传输和接收。


细节问题!!

从图中可以看出,UART 通信支持不同的字长设置,包括 9 位字长和 8 位字长,并且可以选择是否使用校验位。

需要注意的是,当使用 8 位字长并启用校验时,由于校验位的存在,数据位将减少一位,这样就无法构成一个完整的字节。因此,在选择字长时,若使用 9 位字长,可以选择启用校验位,而 8 位字长通常应选择不使用校验位,以确保每个数据帧完整且符合字节的要求。

USART 的停止位在串行通信中起到了非常重要的作用,它用于标识一个数据帧的结束。具体来说,停止位用于确保数据接收端能够准确地判断每个数据字节的边界,从而区分相邻的数据帧。下面是停止位的作用详细解释:

1. 数据帧的结束标志

  • 停止位用于标识数据帧的结束。一个数据帧通常由 起始位(Start Bit)、数据位(Data Bits)、校验位(Parity Bit)和 停止位(Stop Bit)组成。当接收端接收到停止位时,它就知道一个数据帧已经接收完毕,可以开始处理数据或等待下一个数据帧的到来。

2. 提供接收端的时间间隔

  • 停止位为接收端提供了一个时间间隔,使接收端有足够的时间去处理接收到的数据并准备好接收下一个数据帧。这有助于防止接收端因为过快接收数据而出现数据丢失或错位。
  • 例如,假设设置了一个 1 位停止位,接收端会在数据帧的每个字节结束后等待 1 个位时间。若设置了 2 位停止位,则会等待 2 个位时间。这个间隔为接收端提供了一个缓冲期。

3. 保证数据同步

  • 在串行通信中,停止位确保了数据帧的同步性。停止位的长度通常为 1 位或 2 位。当接收端检测到停止位时,它会确定接收到的数据的边界,并与其他数据帧区分开来。如果没有停止位,接收端就无法知道何时停止接收,可能会导致接收错误。

4. 防止数据重叠

  • 停止位防止了数据帧之间的重叠,特别是在高速传输中,它确保每个数据字节的传输是清晰的、独立的。若没有停止位,接收端可能无法准确分辨每个数据字节的起始和结束,导致数据错误。

5. 灵活配置停止位

  • 大多数 USART 实现允许配置 1 位停止位2 位停止位。选择更长的停止位可以在某些噪声较大的环境中提高可靠性,避免数据接收错误,但也会稍微降低通信速率。

总结:

停止位的作用可以概括为:

  • 标识数据帧的结束。
  • 提供接收端缓冲时间,确保数据接收不重叠。
  • 保证数据同步,避免接收错误。
  • 提高通信的稳定性,特别是在高速传输时。

合理设置停止位数量,可以有效提升通信的稳定性与可靠性,尤其在长时间或高速的串行数据传输中至关重要。

一般我们,就选择一位停止位。

这张图片展示了 STM32 微控制器中 USART (通用同步异步收发器) 的波特率寄存器 (USART_BRR) 结构。波特率寄存器用于配置 USART 接口的数据传输速度。以下是对其结构和配置方法的详细解释:

1. 波特率计算公式

公式:波特率 = \frac{{f_{PCLK2/1}}}{{16 \times \text{DIV}}

  • 其中,fPCLK2/1f_{PCLK2/1}fPCLK2/1​ 是 USART 使用的外部时钟频率(系统时钟经过分频后的频率)。
  • DIV 是设置在 USART_BRR 寄存器中的分频系数。
  • 使用此公式计算的波特率决定了 USART 接口传输数据的速度。

2. 波特率寄存器 (USART_BRR)

USART_BRR 寄存器用于设定 DIV 值,该寄存器中包括两个部分:

  • DIV_Mantissa[11:0]:分频器的整数部分,占用寄存器的第 15:4 位。
  • DIV_Fraction[3:0]:分频器的小数部分,占用寄存器的第 3:0 位。

这些位的组合形成了一个完整的分频系数(DIV),从而可以微调波特率。

3. 寄存器各部分说明

  • 位 31:16:保留位,硬件默认为 0。
  • 位 15:4DIV_Mantissa[11:0],是波特率分频器的整数部分,用于主要的分频比设定。
  • 位 3:0DIV_Fraction[3:0],是波特率分频器的小数部分,用于更精细的波特率调整。

4. 设置波特率的步骤

  1. 确定系统时钟频率 fPCLK2/1f_{PCLK2/1}fPCLK2/1​。
  2. 根据期望的波特率,计算分频系数 DIV\text{DIV}DIV。 DIV=fPCLK2/116×波特率\text{DIV} = \frac{{f_{PCLK2/1}}}{{16 \times \text{波特率}}}DIV=16×波特率fPCLK2/1​​
  3. 将计算得到的 DIV 分成整数和小数两部分,分别写入 DIV_MantissaDIV_Fraction
  4. 将 USART_BRR 寄存器配置为这些值后,USART 即会按照配置的波特率进行数据传输。

例子

其实,我们不必大费周章,STM32已经帮我们写好了,库函数,直接输入库函数即可

确实,STM32 提供了丰富的标准库函数和 HAL 库函数,我们可以直接调用库函数来配置 USART 的波特率,而不必手动计算和写入寄存器。通过库函数,可以简化代码的编写,提高代码的可读性和可维护性。

下面是使用 HAL 库的一个示例代码来设置 USART 波特率:
 

#include "stm32f1xx_hal.h"  // 根据芯片型号包含合适的 HAL 头文件UART_HandleTypeDef huart1;  // 声明一个 UART 句柄void USART1_UART_Init(void)
{huart1.Instance = USART1;               // 选择 USART1huart1.Init.BaudRate = 9600;            // 设置波特率,例如 9600huart1.Init.WordLength = UART_WORDLENGTH_8B; // 设置数据位长度,8位huart1.Init.StopBits = UART_STOPBITS_1; // 设置停止位,1位停止位huart1.Init.Parity = UART_PARITY_NONE;  // 设置校验位,无校验huart1.Init.Mode = UART_MODE_TX_RX;     // 设置模式,收发模式huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 无硬件流控huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 16倍过采样if (HAL_UART_Init(&huart1) != HAL_OK)   // 调用初始化函数{// 错误处理Error_Handler();}
}

解释

  1. UART_HandleTypeDef:这是一个 UART 句柄结构体,用于配置和操作 USART。在这里我们定义了 huart1,并将其关联到 USART1 外设。

  2. huart1.Instance:指定要配置的 USART 外设。在这里选择 USART1

  3. huart1.Init.BaudRate:设置波特率。这里我们设置为 9600,可以根据需要修改为其他波特率。

  4. huart1.Init.WordLength:设置数据位长度。UART_WORDLENGTH_8B 表示 8 位数据位。

  5. huart1.Init.StopBits:设置停止位数量,这里选择 1 位。

  6. huart1.Init.Parity:设置校验方式。UART_PARITY_NONE 表示无校验位。

  7. huart1.Init.Mode:设置 UART 工作模式,这里选择收发模式(UART_MODE_TX_RX),即既可以发送也可以接收数据。

  8. huart1.Init.HwFlowCtl:硬件流控,设置为无流控(UART_HWCONTROL_NONE)。

  9. huart1.Init.OverSampling:选择过采样倍数,UART_OVERSAMPLING_16 为 16 倍过采样。通常选择 16 倍过采样来保证通信质量。

  10. HAL_UART_Init:调用 HAL 库的 UART 初始化函数,传入配置好的 huart1 句柄,即可完成 USART 配置。此函数会自动计算波特率分频值并写入相应的寄存器,因此无需手动计算。

使用 HAL 库的好处

STM32 的 HAL 库封装了底层寄存器的操作,使得我们只需配置参数即可完成初始化。这样不仅简化了代码量,也提升了代码的通用性和可读性。如果后续需要调整波特率等参数,只需修改相关配置即可,无需手动计算和操作寄存器。

STM32 标准库和 HAL 库已经封装好了 USART 波特率的设置功能,我们可以直接使用库函数来配置 USART 波特率,而不需要手动计算并设置寄存器的值。

使用 STM32 库函数配置 USART 波特率

在 STM32 的 HAL 库中,HAL_UART_Init() 函数可以用来初始化 USART 并设置波特率。我们只需要定义一个 UART_HandleTypeDef 结构体,并设置其波特率等参数,然后调用这个初始化函数即可。

代码示例

假设我们使用 USART1,波特率为 9600:

#include "stm32f1xx_hal.h"UART_HandleTypeDef huart1;void USART1_UART_Init(void) {huart1.Instance = USART1;                       // 指定使用 USART1huart1.Init.BaudRate = 9600;                    // 设置波特率为 9600huart1.Init.WordLength = UART_WORDLENGTH_8B;    // 设置数据长度为8位huart1.Init.StopBits = UART_STOPBITS_1;         // 设置停止位为1位huart1.Init.Parity = UART_PARITY_NONE;          // 设置无校验位huart1.Init.Mode = UART_MODE_TX_RX;             // 设置模式为收发模式huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;    // 设置硬件流控制为无huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 设置过采样为16if (HAL_UART_Init(&huart1) != HAL_OK) {// 初始化错误处理Error_Handler();}
}

  1. UART_HandleTypeDef 结构体huart1 是一个 UART 的句柄,用于配置和控制 USART1。

  2. huart1.Instance = USART1:指定我们要初始化的 UART 外设为 USART1

  3. huart1.Init.BaudRate = 9600:设置 UART 的波特率为 9600。库函数会自动计算适合的 USART_BRR 寄存器值来实现这个波特率。

  4. 其他配置

    • WordLength 设置为 8 位数据长度。
    • StopBits 设置为 1 位停止位。
    • Parity 设置为无校验位。
    • Mode 设置为收发模式(即使能发送也能接收)。
    • HwFlowCtl 设置为无硬件流控制。
    • OverSampling 设置为 16 倍过采样。
  5. HAL_UART_Init(&huart1):调用 HAL 库函数进行初始化。这个函数会根据 huart1 的配置,自动设置 USART 的相关寄存器(包括波特率寄存器 USART_BRR)。

优点

使用库函数进行 UART 配置的优点在于:

  • 简化了配置步骤,无需手动计算和设置寄存器。
  • 提供更高的可移植性和可维护性,因为 HAL 库在不同系列的 STM32 芯片中都有类似的接口。
  • 减少了出错的可能性。

STM32 的标准库(STM32 Standard Peripheral Library,简称 StdPeriphLib)是 STMicroelectronics 为 STM32 微控制器提供的早期外设库,主要用于简化外设的配置和使用。相比于低层直接操作寄存器,标准库通过封装函数接口,使代码更易读易维护。虽然标准库在最新的 STM32 开发中被 HAL 库替代,但仍然被许多开发者使用,特别是在老旧的 STM32 芯片上。

使用 STM32 标准库初始化 USART 波特率的示例代码

以 STM32F103 微控制器和 USART1 为例,设置波特率为 9600。这个库不包含 HAL 库那样的结构体 UART_HandleTypeDef,而是直接通过库函数操作外设寄存器。

代码示例
#include "stm32f10x.h"void USART1_Init(void) {USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;// 1. 开启 GPIOA 和 USART1 的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);// 2. 配置 PA9 为 USART1_TXGPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;               // TX 引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       // 设置引脚速率GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         // 设置为复用推挽模式GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 PA10 为 USART1_RXGPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;              // RX 引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   // 设置为浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);// 3. 配置 USART 参数USART_InitStructure.USART_BaudRate = 9600;              // 波特率 9600USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长 8 位USART_InitStructure.USART_StopBits = USART_StopBits_1;  // 停止位 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; // 使能接收和发送// 4. 初始化 USART1USART_Init(USART1, &USART_InitStructure);// 5. 启动 USART1USART_Cmd(USART1, ENABLE);
}

到这里USART就结束了,接下来就是实战程序开发了!请看下一节!!!!!!!!!!!

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

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

相关文章

无插件H5播放器EasyPlayer.js网页web无插件播放器选择全屏时,视频区域并没有全屏问题的解决方案

EasyPlayer.js H5播放器,是一款能够同时支持HTTP、HTTP-FLV、HLS(m3u8)、WS、WEBRTC、FMP4视频直播与视频点播等多种协议,支持H.264、H.265、AAC、G711A、MP3等多种音视频编码格式,支持MSE、WASM、WebCodec等多种解码方…

SPIRiT-Diffusion:基于自一致性驱动的加速MRI扩散模型|文献速递-基于深度学习的病灶分割与数据超分辨率

Title 题目 SPIRiT-Diffusion: Self-Consistency Driven Diffusion Model for Accelerated MRI SPIRiT-Diffusion:基于自一致性驱动的加速MRI扩散模型 01 文献速递介绍 磁共振成像(MRI) 在临床和研究领域被广泛应用。然而,其…

Vue3中一级导航栏的吸顶导航交互以及Pinia优化重复请求

一、前言 在日常的网站中,当鼠标滚轮往页面的底部滑动时,会出现顶部导航栏的隐藏,而出现新的导航栏显示,这就是一级导航栏的吸顶导航交互。本文当实现改模块功能的实现。 二、示例图 参考黑马程序员小兔仙儿PC端项目:…

JDK17源码系列-ArrayList源码解读

JDK17源码系列-ArrayList接口源码解读 1.List集合接口类图 2.ArrayList详细类图 ArrayList继承了AbstractList实现了List、Serializable等接口,实现Serializable接口使得ArrayList类的对象可以串行化,串行化后,对象可以进行网络传输&#x…

VBA学习笔记:点击单元格显示指定的列

应用场景: 表格中列数较多,特定条件下隐藏一些无关的列,只保留相关的列,使表格更加清晰。 示例:原表格如下 点击一年级,只显示一年级相关的科目: 点击二年级,只显示二年级相关的科…

RNN深度学习案例:LSTM火灾温度预测

本文为为🔗365天深度学习训练营内部文章 原作者:K同学啊 一 前期准备数据 1.导入数据 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import MinMaxScaler from keras.lay…

nmap简单使用

nmap的基本功能 nmap有4个基本功能,分别是 端口扫描 主机探测 服务识别 系统识别 端口扫描 nmap 183.2.172.185 从图中可以看出开放了80和443端口 指定端口扫描 指定端口扫描使用-p参数,可以一次性扫描一个或多个或某个范围内的端口 nmap 183.…

python文件排序都有哪些方法

在python环境中提供两种排序方案:用库函数sorted()对字符串排序,它的对象是字符;用函数sort()对数字排序,它的对象是数字,如果读取文件的话,需要进行处理(把文件后缀名‘屏蔽’)。 …

uni-app快速入门(五)--判断运行环境及针对不同平台的条件编译

一、判断运行环境 在实际项目开发中,经常需要进行开发环境和生产环境的切换,uni-app可根据process.env.NODE_ENV判断当前运行环境是开发环境和生产环境,根据不同的环境调用不同的后台接口,具体实现方式: 在项目的static目录下建…

QT定时器

QT定时器 1.概述 这篇文章介绍如何使用定时器 2.定时器 2.1.创建项目 新建一个普通的widget类型项目,在widget.ui文件中添加一个label控件 2.1.QTimer 在帮助文档搜索timerEvent,查看QTimer Class 类提供的定时器。 该类提供了一个定时事件的函…

双指针优质算法题集

目录 一、双指针算法介绍 二、移动0 1、题目链接 2、题解 3、代码实现 (1)、初次实现: (2)、优化后的实现: 二、复写0 1、题目链接: 2、题解 3、代码实现 一、双指针算法介绍 这里的指…

博奥龙黑胶虫去除剂,新品来袭!

形态特征: 大小方面:黑胶虫的直径通常在 0.5~1 微米左右,一般比细菌要小,但在显微镜下仍可明显观察到。 形状方面:其形态不规则,初始呈现点状,随着培养时间的增加其形态可以转变为密集的小黑点…

使用Element UI实现前端分页,及el-table表格跨页选择数据,切换分页保留分页数据,限制多选数量

文章目录 一、前端分页1、模板部分 (\<template>)2、数据部分 (data)3、计算属性 (computed)4、方法 (methods) 二、跨页选择1、模板部分 (\<template>)2、数据部分 (data)3、方法 (methods) 三、限制数量1、模板部分 (\<template>)2、数据部分 (data)3、方法…

HTML5+CSS前端开发[保姆级教学]+基本文本控制标签介绍

引入&#xff1a;Hello&#xff0c;各位编程猿们&#xff01;前几篇文章介绍了软件的安装以及编写新闻文章的代码初体验&#xff0c;这一篇我们来巩固一些这些知识点&#xff0c;复习一下基本文本控制标签&#xff01;&#xff01;&#xff01; 知识点一&#xff1a;基本文本控…

《FreeRTOS任务基础知识以及任务创建相关函数》

目录 1.FreeRTOS多任务系统与传统单片机单任务系统的区别 2.FreeRTOS中的任务&#xff08;Task&#xff09;介绍 2.1 任务特性 2.2 FreeRTOS中的任务状态 2.3 FreeRTOS中的任务优先级 2.4 在任务函数中退出 2.5 任务控制块和任务堆栈 2.5.1 任务控制块 2.5.2 任务堆栈…

AdaBoost 二分类问题

代码功能 生成数据集&#xff1a; 使用 make_classification 创建一个模拟分类问题的数据集。 数据集包含 10 个特征&#xff0c;其中 5 个是有用特征&#xff0c;2 个是冗余特征。 数据集划分&#xff1a; 将数据分为训练集&#xff08;70%&#xff09;和测试集&#xff08;3…

ffmpeg自动手动编译安装

1.下载linux ndk并配置profile文件 本例以android-ndk-r10e为例 vi /etc/profile export NDK_HOME/root/ffmpeg/android-ndk-r10e export PATH P A T H : PATH: PATH:NDK_HOME source /etc/profile 2.下载x264并生成 git clone https://code.videolan.org/videolan/x264.g…

英伟达基于Mistral 7B开发新一代Embedding模型——NV-Embed-v2

我们介绍的 NV-Embed-v2 是一种通用嵌入模型&#xff0c;它在大规模文本嵌入基准&#xff08;MTEB 基准&#xff09;&#xff08;截至 2024 年 8 月 30 日&#xff09;的 56 项文本嵌入任务中以 72.31 的高分排名第一。此外&#xff0c;它还在检索子类别中排名第一&#xff08;…

Flume1.9.0自定义拦截器

需求 1、在linux日志文件/data/log/moreInfoRes.log中一直会产生如下JSON数据&#xff1a; {"id":"14943445328940974601","uid":"840717325115457536","lat":"53.530598","lnt":"-2.5620373&qu…

RadSystems 自定义页面全攻略:个性化任务管理系统的实战设计

系列文章目录 探索RadSystems&#xff1a;低代码开发的新选择&#xff08;一&#xff09;&#x1f6aa; 探索RadSystems&#xff1a;低代码开发的新选择&#xff08;二&#xff09;&#x1f6aa; 探索RadSystems&#xff1a;低代码开发的新选择&#xff08;三&#xff09;&…