一、介绍

通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信。

二、硬件连接

  1. 串口之间的接线方式

  2. TTL与RS232的电平标准

  3. STM32 USART框图

三、通信协议

  1. 数据包

    串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备得RXD接口,在协议层中规定了数据包的内容,具体包括起始位、主体数据(8位或9位)、校验位以及停止位,通讯的双方必须将数据包的格式约定一致才能正常收发数据。

  2. 波特率

    由于异步通信中没有时钟信号,所以接收双方要约定好波特率,常见的波特率有4800、9600、115200等。

  3. 起始和停止信号

    数据包的首尾分别是起始位和停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示,双方需约定一致。

  4. 有效数据

    有效数据规定了主题数据的长度,一般为8或9位。

  5. 数据校验

    在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、 0 校验(space)、 1 校验(mark)以及无(noparity)。

4、STM32 USART的寄存器

  1. STM32 USART的配置的寄存器,库函数中的结构体积是基于寄存器进行封装的,还没学会怎么看寄存器的小伙伴可以看我之前的笔记
寄存器 偏移 复位值 描述
USART_SR 0x00 0x00C0 状态寄存器
USART_DR 0x04 不确定 数据寄存器
USART_BRR 0x08 0x0000 波特比率寄存器
USART_CR1 0x0C 0x0000 控制寄存器1
USART_CR2 0x10 0x0000 控制寄存器2
USART_CR3 0x14 0x0000 控制寄存器3
USART_GTPR 0x18 0x0000 保护时间和预分频寄存器
  1. 寄存器的地址映象

四、代码分析

  1. 配置串口的结构体
typedef struct
{
uint32_t USART_BaudRate; // 波特率设置
uint16_t USART_WordLength; //数据位数设置
uint16_t USART_StopBits; //停止位设置
uint16_t USART_Parity; //是否奇偶校验
uint16_t USART_Mode; //接收与发送都使能
uint16_t USART_HardwareFlowControl; //硬件流控制模式设置
} USART_InitTypeDef;
  1. 中断配置结构体
typedef struct
{
uint8_t NVIC_IRQChannel; // 配置USART为中断源
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢断优先级
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 使能中断
} NVIC_InitTypeDef;
  1. 配置USART 的 IO引脚

    将Tx配置为复用推挽输出,将Rx配置为浮空输入
    /* USART1 使用IO端口配置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
  1. 配置USART 的工作模式配置
    /* USART1 工作模式配置 */
USART_InitStructure.USART_BaudRate = 115200; //波特率设置:115200
USART_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;//接收与发送都使能
  1. 将Rx读取配置为中断读取模式
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 配置USART为中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢断优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断
NVIC_Init(&NVIC_InitStructure); // 初始化配置NVIC
}
  1. 中断函数使用

    当串口接收到数据后此中断函数会被调用,调用次函数后,会将接收到的信息有通过串口发送获取。这里的中断函数名已经在启动文件中已经定义好了的,建议不做更改。



    注意:有的小伙伴编写好程序后,发现串口无法收到发送的信息,可能是这里的中断函数名写错了。
void USART1_IRQHandler(void)
{
uint16_t res;
/* 判断是否收到中断信号 */
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
res = USART_ReceiveData(USART1);
USART_SendData(USART1, res);
}
//USART_SendData(USART1,(uint16_t)0xAC); }

五、程序源码

  1. usart1.c文件
/***************************************
* 文件名 :usart1.c
* 描述 :配置USART1
* 实验平台:MINI STM32开发板 基于STM32F103C8T6
* 硬件连接:------------------------
* | PA9 - USART1(Tx) |
* | PA10 - USART1(Rx) |
* ------------------------ **********************************************************************************/ #include "usart1.h"
#include <stdarg.h>
#include "misc.h" void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 配置USART为中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢断优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断
NVIC_Init(&NVIC_InitStructure); // 初始化配置NVIC
} void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure; /* 使能 USART1 时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); /* USART1 使用IO端口配置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA /* USART1 工作模式配置 */
USART_InitStructure.USART_BaudRate = 115200; //波特率设置:115200
USART_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;//接收与发送都使能 USART_Init(USART1, &USART_InitStructure); //初始化USART1
USART_Cmd(USART1, ENABLE);// USART1使能 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接受中断
NVIC_Configuration();// 串口中断优先级配置 } void USART1_IRQHandler(void)
{
uint16_t res;
/* 判断是否收到中断信号 */
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
res = USART_ReceiveData(USART1);
USART_SendData(USART1, res);
}
//USART_SendData(USART1,(uint16_t)0xAC); }
  1. main.c文件
#include "stm32f10x.h"
#include "usart1.h" int main(void)
{ SystemInit(); //配置系统时钟为 72M USART1_Config(); //USART1 配置 while (1)
{ }
}

五、编译运行

  1. 编译

  2. 运行

六、常见问题

程序下载后运行后发送数据无反馈。

解决办法:

  1. 检查中断函数名是否正确。
  2. 将STM32的引脚设置为运行模式,有不知道的怎么设置为运行模式的小伙伴可以参考STM32零基础入门教程

STM32 USART串口通信的更多相关文章

  1. 单片机stm32 USART串口实际应用解析

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...

  2. stm32 usart 串口

    比特率是每秒钟传输二进制代码的位数,单位是:位/秒(bps).如每秒钟传送240个字符, 而每个字符格式包含10位(1个起始位.1个停止位.8个数据位),这时的比特率为: 10位 × 240个/秒 = ...

  3. STM32学习笔记:【004】USART串口通信

    版本:STM32F429 Hal库v1.10 串口通信能够实现两块电路之间不同的通信,在开发中作为打印调试也是一门利器(printf重定向). 补充一点小知识: 1. weak修饰符修饰的函数,说明这 ...

  4. (三)stm32之串口通信DMA传输完成中断

    一.DMA功能简介 首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量.在硬件系统中,主要由CPU(内核).外设.内存(SRAM).总线等结构组成,数据经常要在内存和外设之间,外设和外 ...

  5. STM32的串口通信

    本篇文章主要讲解一个在开发过程中经常使用到的一个外设---串口. 串口是绝大多数 MCU 中不可或缺的一个外设,同时也是我们开发中经常使用的一种调试手段,所以在STM32的学习中,串口的配置使用也是必 ...

  6. (stm32f103学习总结)—USART串口通信

    一. USART简介 USART即通用同步异步收发器,它能够灵活地与外部设备进行全双工 数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求. UART即通用异步收发器,它是在USART基 ...

  7. STM32之串口通信

    一.RS232通信协议 1.概念 个人计算机上的通讯接口之一,由电子工业协会(Electronic Industries Association,EIA) 所制定的异步传输标准接口. 2.电气特性 逻 ...

  8. STM32 在串口通信时运用MODBUS协议

    最近一个项目用到了MODBUS协议,就学习了一下,这里做一下记录以免后续忘记. 要用到MODBUS肯定要先知道是MOBUS协议,这里呢我们就又要先理解协议的含义了. 所谓的协议是什么?就是互相之间的约 ...

  9. stm32中的串口通信你了解多少

    在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...

  10. stm32学习笔记之串口通信

    在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...

随机推荐

  1. kali局域网断网攻击

    首先我们打开我们熟悉的kali linux操作系统,利用指令: ifconfig 来确认本机的ip地址 确认了本机的ip地址之后,利用一下的指令查看局域网下所有ip: fping -g 本机IP地址/ ...

  2. Apache Thrift 白皮书

    介绍: 轻量级.跨语言. 简洁的抽象和实现:数据传输.序列化.应用逻辑处理. IDL及代码生成系统. 基本架构图如下: 28种语言支持:28 programming languages. 支持客户端及 ...

  3. #Trie#洛谷 7717 「EZEC-10」序列

    题目 分析 考虑这些关系可以用若干个连通块表示,而可以用一个数异或边权表示, 那么每个连通块有一个生成树,而判断非树边是否合法即可, 那么问题就转换成有多少个数异或任意一个元素均不大于\(k\), 把 ...

  4. #树链剖分,zkw线段树#nssl 1489 大冰隙2

    题目 有一个长度为\(n\)的01数列\(a\)和一个长度为\(n\)的数列\(b\)表示权值 支持单点修改以及区间查询,\(0\)和\(1\)可以看作左括号和右括号, 将一段区间所有可匹配的的括号去 ...

  5. #树状数组,离散#洛谷 3586 [POI2015]LOG

    题目 分析 考虑\(\geq s\)的部分最多取到\(s\), 设\(<s\)的总和为\(p\),个数为\(t\), 那么\(p+(n-t)*s\geq c*s\)就一定能取到 代码 #incl ...

  6. 使用Python插入100万条数据到MySQL数据库并将数据逐步写出到多个Excel

    Python插入100万条数据到MySQL数据库 步骤一:导入所需模块和库 首先,我们需要导入 MySQL 连接器模块和 Faker 模块.MySQL 连接器模块用于连接到 MySQL 数据库,而 F ...

  7. 使用OHOS SDK构建assimp

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone https://github.com/assimp/assimp.git 进入源码 ...

  8. 深入理解 Java 循环结构:while、do while、for 和 for-each 循环

    Java 循环 循环可以执行一个代码块,只要达到指定的条件.循环很方便,因为它们节省时间,减少错误,并使代码更易读. Java While 循环 while 循环会循环执行一个代码块,只要指定的条件为 ...

  9. Qt调用摄像头一,基础版

    本示例,为纯Qt调用摄像头,功能比较简单,打开摄像头,设置参数,拍照 涉及到的功能有: 获取摄像头列表 获取摄像头分辨率 获取摄像头帧率 获取摄像头支持的视频模式 设置摄像头参数 拍照 此版本的缺点是 ...

  10. CentOS下修改 MySQL 的密码

    做服务器运维,修改 MySQL 的密码是经常的需要,定期修改 MySQL 密码是网站安全的一个保证.这里记录一下修改 MySQL 密码的一些命令,方便以后查看. 修改root密码 CentOS 下 M ...