【STM32】串口(异步通信部分)

经典的串口接口硬件说实话在现在的电脑上已经很难见到了,而是被USB这种通用的串行接口替代了,哪怕外部设备要以串口连接到电脑,都需要进行各种硬件转换。但不得不说,在工业领域,串口还是一个非常常用的数据传输方式。

大部分图片来源:正点原子HAL库课程

目录

[1 通信的基本知识](#1 通信的基本知识)

[1.1 同步/异步通信](#1.1 同步/异步通信)

[1.2 比特率和波特率](#1.2 比特率和波特率)

[2 串口电平与连接](#2 串口电平与连接)

[2.1 RS232电平](#2.1 RS232电平)

[2.2 CMOS电平(STM32)](#2.2 CMOS电平(STM32))

[2.3 TTL电平(51)](#2.3 TTL电平(51))

[2.4 连接方式](#2.4 连接方式)

[3 U(S)ART](#3 U(S)ART)

[3.1 简介](#3.1 简介)

[3.2 查看芯片U(S)ART数量](#3.2 查看芯片U(S)ART数量)

[3.3 查看U(S)ART对应引脚](#3.3 查看U(S)ART对应引脚)

[3.4 波特率计算公式](#3.4 波特率计算公式)

[3.5 使用寄存器设置波特率的示例](#3.5 使用寄存器设置波特率的示例)

[3.6 HAL库异步通信配置](#3.6 HAL库异步通信配置)

[3.7 详细的解析](#3.7 详细的解析)

[3.8 相关的HAL库文件(可以去这里找用到的函数和宏定义)](#3.8 相关的HAL库文件(可以去这里找用到的函数和宏定义))


1 通信的基本知识

1.1 同步/异步通信

  • 同步通信: 共用同一时钟信号;
  • 异步通信: 没有时钟信号,通过在数据信号中 加入起始位和停止位等同步信号。

1.2 比特率和波特率

**比特率:**每秒钟传送的比特数,单位bit/s

**波特率:**每秒钟传送的码元数,单位Baud

比特率 = 波特率 * log2 M,M表示每个码元承载的信息量(这里M可以直接理解为信息调制后的的进制数)

二进制系统中,波特率数值上等于比特率(我的理解是要是一次性可以发送的数据不是1位,那么波特率就不等于比特率了)。


2 串口电平与连接

2.1 RS232电平

逻辑1:-15 ~ -3V

逻辑0:+3 ~ +15V

2.2 CMOS电平(STM32)

逻辑1:3.3V

逻辑0:0V

2.3 TTL电平(51)

逻辑1:5V

逻辑0:0V

2.4 连接方式

  • 232串口两设备连接:
  • STM32与电脑通信原理:

3 U(S)ART

3.1 简介

  • 都能全双工异步通信;
  • USART多了同步通信功能,但平时用它也比较少用它的同步功能;

3.2 查看芯片U(S)ART数量

《ST MCU选型手册》

3.3 查看U(S)ART对应引脚

芯片数据手册,如《STM32F103ZET6(中文版)》- 引脚定义

3.4 波特率计算公式

其中是串口的时钟,如:USART1的时钟是PCLK2,其他串口都是PCLK1。

注意⚠️:

这个式子其实不是为了计算波特率,而是为了计算USARTDIV的数值,其包括整数部分和小数部分,存储于USART_BRR寄存器中,是为了配置USART发送器时钟的。

3.5 使用寄存器设置波特率的示例

其中,+0.5是为了让其四舍五入,否则因为强制类型转换,小数部分直接会被忽略。

简化计算过程后,通用过程为:

3.6 HAL库异步通信配置

其中根据四步法的逻辑,可以分为:

1. 初始化

(1) 串口参数设置:HAL_UART_Init();

(2) 时钟设置:重写HAL_UART_MspInit(),在其中开启GPIO及UART的时钟;

(3) IO设置:重写HAL_UART_MspInit()中设置GPIO的配置;

(4) 中断设置:重写HAL_UART_MspInit()中使能中断,并设置中断优先级,使用HAL_UART_Receive_IT()函数开启中断,可以理解为开启串口阻塞(实际上并不阻塞);

**2. 定义读函数:**无

**3. 定义写函数:**无

4. 编写中断服务函数:

(1) 重写UARTx_IRQHandler()函数,调用UART的串口公用数据处理函数;

(2) 重写接收完毕的回调函数HAL_UART_RxCpltCallback(),实现自定义的接收完成后动作,并在最后重新调用HAL_UART_Receive_IT()开启串口中断,因为接收完毕后串口中断就用完了(对,一次性的)。

3.7 详细的解析

其中根据四步法的逻辑:

1. 初始化

(1) 串口参数设置:

(2) 时钟设置:

(3) IO设置:其中串口的上下拉状态由芯片串口通信的电平时序图来决定,如下:

由于图中空闲时为高电平,因此就是要设置上拉。

(4) 中断设置:**注意注意⚠️!**HAL_UART_Receive_IT()启用串口不可以写在HAL_UART_MspInit()函数内,因为其执行的条件是串口的状态是Ready,而只有HAL_UART_Init()执行完毕后,串口状态才会从Reset改为Ready。也就是说在HAL_UART_Init函数内部,在执行完HAL_UART_MspInit后,还有一些内容要执行,因此写在HAL_UART_MspInit函数内的HAL_UART_Receive_IT事实上是无法得到执行的。

**2. 定义读函数:**无

**3. 定义写函数:**无

4. 编写中断服务函数:

(1) 中断服务函数中调用的HAL库公共数据处理函数可以将中断的标志位清空,因此在执行完毕后才需要重新调用HAL_UART_Receive_IT()开启阻塞

小思考:在GPIO中断中无需手动开启可能是因为在GPIO配置中就配置了

(2) 在接收完毕回调函数、串口中断服务函数等场合,应首先通过串口外设的句柄对接收的信号进行来源判断,因为有可能多个串口都开启了,但其各自的反应需要定义成不同的逻辑。

  • 注意事项⚠️

在正点原子的相关教程中,在使用HAL_UART_Transmit函数发送串口数据后,会利用__HAL_UART_GET_FLAG函数读取SR寄存器的TX位配合while循环进行阻塞以保证信息的发送完毕,但事实上在HAL_UART_Transmit函数中已有类似的机制,因此是不需要进行手动阻塞的。

3.8 相关的HAL库文件(可以去这里找用到的函数和宏定义)

stm32f1xx_hal_uart.c

相关推荐
美式小田2 小时前
单片机学习笔记 9. 8×8LED点阵屏
笔记·单片机·嵌入式硬件·学习
兰_博3 小时前
51单片机-独立按键与数码管联动
单片机·嵌入式硬件·51单片机
时光の尘3 小时前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
嵌入式大圣5 小时前
单片机结合OpenCV
单片机·嵌入式硬件·opencv
日晨难再6 小时前
嵌入式:STM32的启动(Startup)文件解析
stm32·单片机·嵌入式硬件
yufengxinpian7 小时前
集成了高性能ARM Cortex-M0+处理器的一款SimpleLink 2.4 GHz无线模块-RF-BM-2340B1
单片机·嵌入式硬件·音视频·智能硬件
__基本操作__8 小时前
历遍单片机下的IIC设备[ESP--0]
单片机·嵌入式硬件
网易独家音乐人Mike Zhou14 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
zy张起灵14 小时前
48v72v-100v转12v 10A大功率转换电源方案CSM3100SK
经验分享·嵌入式硬件·硬件工程
PegasusYu17 小时前
STM32CUBEIDE FreeRTOS操作教程(九):eventgroup事件标志组
stm32·教程·rtos·stm32cubeide·free-rtos·eventgroup·时间标志组