当前位置: 首页 > news >正文

STM32之串口详解

一、串口

1. 串口用途

串口是硬件中数据传递的一种方式,对应 USART 和 UART,包括 RS485、RS232、CAN 等。其主要用途是按照串行数据传递形式完成设备之间的数据通信。

2. 串行和并行

并行

  • 连接方式:数据发送端和数据接收端通过 4 根数据线连接。
  • 传输特点:数据线每次发送一个字节,数据可以同时发送 4 个字节数据。

串行

  • 连接方式:仅有一个数据通道可以完成数据通信。
  • 传输特点:数据字节按照顺序,类似于一串内容进行发送和接收。

接口类型

  • 全双工:当前设备支持接收数据和发送数据,并且可以同时完成接收和发送。
  • 半双工:当前设备支持接收数据和发送数据,但是设备如果处于接收数据状态,不允许发送数据;如果处于发送数据状态,不允许接收数据。
  • 单工:设备区分发送端和接收端。

3. 同步和异步

同步

  • 设备关系:主设备(Master)和从设备(Slave)。
  • 时钟特点:数据发送和接收时钟总线步调一致。
  • 传输细节:主设备和从设备之间进行数据传递,主设备数据位、字节和从设备数据位、字节时钟一致,即【同步状态】。

异步

  • 设备关系:主设备(Master)和从设备(Slave)。
  • 时钟特点:数据发送和接收时钟总线不同。
  • 传输细节:主设备数据位、字节和从设备数据位、字节,直接的时间关系无所谓。例如主设备进行数据发送,从设备等了两年半之后接收数据(为【异步】情况)。且数据内容必须有明确的【起始标记】和【终止标记】。

4. USART 原理图

5. 分析 USART 相关技术

5.1 技术特征

5.2 关于发送数据和接收数据相关寄存器总线图

  • MCU 通过串口 USART 进行数据发送,数据流转过程
    • MCU -> PWDATA 数据总线 -> 写操作
    • 发送数据寄存器 TDR ==> Transmit Data Register
    • 硬件自动将 TDR 数据转移到发送移位寄存器,最后转出到 TX 接口
  • MCU 通过串口 USART 进行数据接收,数据流转过程
    • 数据通过外部的 RX 接口进入到接收移位寄存器
    • 硬件自动接收移位寄存器中的数据,移动到接收数据寄存器 RDR ==> Read Data Register
    • RDR 数据转到 PWDATA 数据总线 -> MCU
数据发送过程
  1. 首先,MCU 要发送数据时,会将数据通过 PWDATA 数据总线进行传输,随后执行写操作,把数据写入到发送数据寄存器(TDR,Transmit Data Register)中。
  2. 之后,硬件会自动把 TDR 里的数据转移到发送移位寄存器。发送移位寄存器的作用是将并行的数据逐位转换成串行数据。
  3. 最后,这些串行数据会从 TX 接口发送出去,完成数据的发送流程。
数据接收过程
  1. 当有数据要被 MCU 接收时,数据首先通过外部的 RX 接口进入到接收移位寄存器。接收移位寄存器会把接收到的串行数据逐位收集起来,转换成并行数据。
  2. 接着,硬件自动将接收移位寄存器中的数据移动到接收数据寄存器(RDR,Read Data Register)。
  3. 最后,RDR 中的数据会被转移到 PWDATA 数据总线,进而传输到 MCU 中,完成数据的接收过程。

5.3 NRZ 数据格式

5.4 USART 时钟分析和波特率计算

        时钟使能
        当前开发板操作的 USART1 --> 对应时钟是 RCC->APB2ENR 寄存器控制,位 14
        串口数据发送和接收对应的【波特率 BRR】是根据对应时钟作为参考依据进行提供。

// 根据当前公式计算需要提供给寄存器的相关数据
// 假设波特率是 115200 ==> USARTDIV 数据
float usart_div = 72 * 1000 * 1000 / (16 * 115200);
// usart_div == 39.0625
/*
usart_div 进行拆解,分别对应整数部分和小数部分内容,提供给当前 USART1 中用于
计算波特率对应寄存器位。
*/
int usart_div_fraction = 0.0625 * 16 = 1 ==> 0x01
int usart_div_Mantissa = 39 ==> 0x27
// 两个数据进行组合 提供给 USART1 波特率寄存器的数据为
USART_BRR = 0x271

5.5 USART 相关配置相关寄存器分析

5.5.1 控制寄存器1 (USART_CR1)

5.5.2 控制寄存器2 (USART_CR2)
5.5.3 波特比率寄存器 (USART_BRR)
控制波特率寄存器,对应之前计算的 BRR 寄存器所需数据内容。

5.6 USART1 时钟使能和 GPIO 配置

5.6.1 APB2 USRAT1 时钟配置

5.6.3 USART1 初始化配置代码实现
#include "usart1.h"void USART1_Init(u32 brr)
{/* 1. 时钟使能 GPIOA 和 USART1(均在 APB2 总线上)USART1 对应位 14,GPIOA 对应位 2 */RCC->APB2ENR |= (0x01 << 2) | (0x01 << 14);/* 2. 配置 PA9 (TX) 和 PA10 (RX) 的 GPIO 模式PA9 - 复用推挽输出模式(TX 发送端)PA10 - 浮空输入模式(RX 接收端) */GPIOA->CRH &= ~(0x00FF << 4);  // 清除 PA9 和 PA10 原有配置GPIOA->CRH |= 0x0B << 4;       // PA9 配置为复用推挽输出(50MHz)GPIOA->CRH |= 0x04 << 8;       // PA10 配置为浮空输入/* 3. USART1 串口参数配置 */// 3.1 配置为 8 数据位、无校验位、1 停止位(8n1 格式)USART1->CR1 &= ~(0x01 << 12);  // M 位清零,选择 8 数据位USART1->CR1 &= ~(0x01 << 10);  // PCE 位清零,禁用校验位USART1->CR2 &= ~(0x03 << 12);  // STOP 位清零,选择 1 停止位// 3.2 使能发送 (TE) 和接收 (RE) 功能USART1->CR1 |= (0x03 << 2);    // TE 位(bit3)和 RE 位(bit2)置 1// 3.3 配置波特率(根据输入的 brr 参数计算)float usart_div = 72000000.0f / (16.0f * brr);  // 72MHz 为 APB2 时钟频率u32 mantissa = (u32)usart_div;                  // 整数部分u32 fraction = (u32)((usart_div - mantissa) * 16);  // 小数部分(4 位精度)USART1->BRR = (mantissa << 4) | fraction;       // 写入波特率寄存器/* 4. 启动 USART1 */USART1->CR1 |= (0x01 << 13);  // UE 位置 1,使能 USART1
}

5.7 MCU 通过 USART1 数据发送和数据读取

5.7.1 相关寄存器分析
数据寄存器 DR
USART_DR 寄存器数据发送和接收都是操作对应的 DR 寄存器
数据存入到 DR 寄存器中,对应【写操作】,数据会从 MCU TX 发送到其他设备
DR 寄存器中获取数据,对应【读操作】,数据会从外设的 TXD 进入到 MCU RX。
// 伪代码
USART1->DR = 1; // 【写操作】数据发送
val = USART1->DR; // 【读操作】数据接收

5.7.2 USART 发送一个字节数据到 PC
// 发送一个字节数据到 PC
void USART1_SendByte(u8 byte)
{/*利用 USART1_SR 寄存器,判断之前的数据内容是否发送完成,如果没有发送完成,本次发送操作进入【阻塞状态】如果 USART1_SR TC ==> 0 表示之前的数据发送未完成如果 USART1_SR TC ==> 1 表示之前的数据发送完毕TC Transmission Complete*/while (0 == (USART1->SR & (0x01 << 6))); // 等待发送完成(TC 位为 1)/*将需要发送的数据存储到 USART1->DR 数据寄存器中,DR 会将数据直接提供给 TDR 寄存器,TDR 寄存器会将数据提供给移位寄存器,SR 寄存器 TC 位在数据发送完毕后会置 1*/USART1->DR = byte;
}

5.7.3 PC 数据到 MCU 【待升级版】
// 从 PC 接收一个字节数据到 MCU
u8 USART1_ReceiveByte(void)
{u8 data = 0;/*判断在 USART1->SR 寄存器中,对应的 RXNE(Read data register not empty)标志位如果没有数据可以收到,RXNE 为 0如果有数据可以读取,RXNE 为 1while 进行 RXNE 标志位判断,如果没有数据当前循环【阻塞后续代码】*/while (0 == (USART1->SR & (0x01 << 5))); // 等待接收数据(RXNE 位为 1)data = (u8)USART1->DR; // 读取接收数据return data;
}

https://github.com/0voice
http://www.dtcms.com/a/342100.html

相关文章:

  • 学习Linux嵌入式(正点原子imx课程)开发到底是在学什么
  • Spring Cloud Netflix学习笔记06-Zuul
  • Kafka消息持久化机制全解析:存储原理与实战场景
  • Kafka集成Flume
  • 人工智能 -- 循环神经网络day1 -- 自然语言基础、NLP基础概率、NLP基本流程、NLP特征工程、NLP特征输入
  • 算法 之 拓 扑 排 序
  • LeetCode 回文链表
  • 桥梁设计模式
  • RabbitMQ事务消息原理是什么
  • RabbitMQ:延时消息(死信交换机、延迟消息插件)
  • 领域专用AI模型训练指南:医疗、法律、金融三大垂直领域微调效果对比
  • 28、工业网络资产漏洞扫描与风险评估 (模拟) - /安全与维护组件/industrial-network-scanner
  • 深度解析Atlassian 团队协作套件(Jira、Confluence、Loom、Rovo)如何赋能全球分布式团队协作
  • Whisk for Mac 网页编辑器 PHP开发
  • 牛客:链表的回文结构详解
  • NewsNow搭建喂饭级教程
  • SQL中对视图的操作命令汇总
  • STM32H750 CoreMark跑分测试
  • [最新]Dify v1.7.2版本更新:工作流可视化和节点搜索
  • 2025 年 8 月《GPT-5 家族 SQL 能力评测报告》发布
  • SQL视图、存储过程和触发器
  • OBCP第四章 OceanBase SQL 调优学习笔记:通俗解读与实践指南
  • CentOS 7安装FFmpeg
  • QT QProcess, WinExec, ShellExecute中文路径带空格程序或者脚本执行并带参数
  • Qt实现TabWidget通过addTab函数添加的页,页内控件自适应窗口大小
  • Qt文件压缩工具项目开发教程
  • 【Bug】CentOS 7 使用vim命令报错vim: command not found
  • 开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑
  • Elasticsearch官方文档学习-未完待续
  • java项目:如何优化JVM参数?