STM32 USART串口通信
一、介绍
通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信。
二、硬件连接
- 串口之间的接线方式
- TTL与RS232的电平标准
- STM32 USART框图
三、通信协议
-
数据包
串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备得RXD接口,在协议层中规定了数据包的内容,具体包括起始位、主体数据(8位或9位)、校验位以及停止位,通讯的双方必须将数据包的格式约定一致才能正常收发数据。
-
波特率
由于异步通信中没有时钟信号,所以接收双方要约定好波特率,常见的波特率有4800、9600、115200等。 -
起始和停止信号
数据包的首尾分别是起始位和停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示,双方需约定一致。 -
有效数据
有效数据规定了主题数据的长度,一般为8或9位。 -
数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、 0 校验(space)、 1 校验(mark)以及无(noparity)。
4、STM32 USART的寄存器
- 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 | 保护时间和预分频寄存器 |
- 寄存器的地址映象
四、代码分析
- 配置串口的结构体
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;
- 中断配置结构体
typedef struct { uint8_t NVIC_IRQChannel; // 配置USART为中断源 uint8_t NVIC_IRQChannelPreemptionPriority; // 抢断优先级 uint8_t NVIC_IRQChannelSubPriority; // 子优先级 FunctionalState NVIC_IRQChannelCmd; // 使能中断 } NVIC_InitTypeDef;
- 配置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
- 配置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;//接收与发送都使能
- 将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 }
- 中断函数使用
当串口接收到数据后此中断函数会被调用,调用次函数后,会将接收到的信息有通过串口发送获取。这里的中断函数名已经在启动文件中已经定义好了的,建议不做更改。
注意:有的小伙伴编写好程序后,发现串口无法收到发送的信息,可能是这里的中断函数名写错了。
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); }
五、程序源码
- 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); }
- main.c文件
#include "stm32f10x.h" #include "usart1.h" int main(void) { SystemInit(); //配置系统时钟为 72M USART1_Config(); //USART1 配置 while (1) { } }
五、编译运行
-
编译
-
运行
六、常见问题
程序下载后运行后发送数据无反馈。
解决办法:
- 检查中断函数名是否正确。
- 将STM32的引脚设置为运行模式,有不知道的怎么设置为运行模式的小伙伴可以参考STM32零基础入门教程。
本文来自博客园,作者:浇筑菜鸟,转载请注明原文链接:https://www.cnblogs.com/jzcn/p/15789561.html
如本博客的内容侵犯了你的权益,请与以下地址联系,本人获知后,马上删除。同时本人深表歉意,并致以崇高的谢意! cn_jiaozhu@qq.com
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)