【STM32】串行通讯方式及USART串口通信

目录

一、通讯的基本概念

1.数据的传送方式

2.数据的通讯方向

3.数据的同步方式

4.数据的传输速率

5.电平信号标准

二、串口通信

1.串口通信介绍

2.STM32上的USART

3.USART库函数初始化

(1)USART初始化结构体​

(2)USART时钟初始化结构体


一、通信的基本概念

1.数据的传送方式

数据传送方式分为并行和串行两种方式。

并行传输方式一次能通过8、16、32、64根数据线同时传输多位数据,传输速率高,一般用于特殊场合,比如芯片内部的总线。

串行传输方式一次只能传输一位数据,传输速度慢,但节省数据线成本,可以满足长距离传输数据的要求。

2.数据的通讯方向

按信道方向区分,数据通讯方向可分为以下三类:

全双工:双方可同时收发数据;

半双工:双方可分时收发数据,不能同时发数据;

单工:单方向收发数据。

3.数据的同步方式

根据通讯过程中是否使用到时钟信号可分为两种方式:

同步:收发设备双方会使用一根信号线表示时钟信号,在时钟信号的驱动下双方进行协调,同步数据。该种方式传送的数据皆为有效数据,传输效率高,但对通讯双方时钟允许误差要求较高。

例如SPI,I2C

异步:不使用时钟信号进行数据同步,直接把主体数据进行打包,以数据帧的格式传输数据。该种方式传输的数据包含有数据帧的标识符,传输效率无同步高,但对时间允许误差大。

例如UART通用异步收发器

4.数据的传输速率

这是一个衡量通讯性能的重要参数,单位为比特率(Bitrate),定义如下

比特率:每秒钟传输的二进制位数,单位为比特每秒 (bit/s)

容易混淆的是,在串口通信中,描述串口通信速率的是波特率(Baudrate),定义如下

波特率:每秒钟传输的码元,单位为bps。

常见的通讯传输中,比如TTL电平标准,用 0V 表示数字 0, 5V 表示数字 1,那么一个码元可以表示两种状态 0 和1,所以此时一个码元等于一个二进制比特位,故此时波特率的大小与比特率一致;如果在通讯传输中,有0V、 2V、 4V 以及 6V 分别表示二进制数 00、01、 10、 11,那么每个码元可以表示四种状态,即两个二进制比特位,所以码元数是二进制比特位数的一半,这个时候的波特率为比特率的一半。不过我们经常用到的是一个码元等于一个二进制比特位的情况,所以常会将波特率和比特率混为一谈。

**补充**:在通信线路上表示0和1有两种方式,一种是电平信号,另一种是差分信号。电平信号的传输线中有一个参考电平线(一般是GND),然后信号线上的信号值是由信号线电平和参考电平线的电压差决定。差分信号的传输线中没有参考电平线,所有都是信号线,然后1和0的表达靠信号线之间的电压差。电平信号的2根通信线之间的电平差异容易受到干扰,传输容易失败;差分信号不容易受到干扰,因此传输质量比较稳定。

5.电平信号标准

串口常用的电平标准有如下三种,在进行串口通信时,必须要统一标准。

TTL电平:+5V表示10V表示0

RS232电平:-3~-15V表示1+3~+15V表示0

RS485电平:两线压差+2~+6V表示1-2~-6V表示0(差分信号)

电子电路中常使用TTL标准,老式计算机和路由与调制调解器会使用到RS232标准,因为它抗干扰能力更强。

二、常见的通信方式

名称引脚双工时钟电平设备
USARTTX、RX全双工异步单端点对点
I2CSCL、SDA半双工同步单端多设备
SPISCLK、MOSI、MISO、CS全双工同步单端多设备
CANCAN_H、CAN_L半双工异步差分多设备
USBDP、DM半双工异步差分点对点

三、串口通信

1.串口通信介绍

根据上面的划分,串口通信属于串行、异步、全双工/单工、使用电平信号中的TTL电平和RS232电平的通信方式。

由于是异步通信,没有用到时钟信号,故两台通讯设备需要使用统一的波特率,常设置的波特率为 4800、 9600、 115200 等。

现在的串口通信已经简化到只需要三根信号线:RXD、TXD、GND,当只使用GND和另外其中一根时实现单工通信。

串口通讯的数据传输以帧(数据包)的形式由发送设备通过自身的 TXD 接口传输到接收设备的 RXD接口。在串口通讯的协议层中,规定了数据包的内容(如图),它由起始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据。

图中用虚线分开的每一格代表一个码元或一个二进制数。(波特率:每秒钟传输的码元。)

数据包(帧)的起始信号由一个逻辑 0 的数据位表示;在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为 5、 6、 7 或 8 位长;数据包的停止信号可由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示,只要双方约定一致即可。

在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验 (odd)、偶校验(even)、 0 校验 (space)、 1 校验 (mark) 以及无校验 (noparity)。
奇校验要求有效数据和校验位中“1”的个数为奇数,比如一个 8 位长的有效数据为: 01101001,
此时总共有 4 个“1”,为达到奇校验效果,校验位为“1”,最后传输的数据将是 8 位的有效数据
加上 1 位的校验位总共 9 位。
偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,比如数据帧: 11001010,此时数据帧“1”的个数为 4 个,所以偶校验位为“0”。
0 校验是不管有效数据中的内容是什么,校验位总为“0”, 1 校验是校验位总为“1”。


2.STM32上的USART

STM32中实现串口通信的设备是通用同步异步收发器 (Universal Synchronous Asynchronous Receiver and Transmitter),USART。可以通过时钟进行同步串口通信,但我们一般只使用其中的异步功能,不使用时钟输出,即通用异步收发器UART(Universal Asynchronous Receiver and Transmitter)。

以STM32F103RCT6为例,说明USART用到的引脚及功能:
STM32F103RCT6 系统控制器有三个 USART 和两个 UART,其中 USART1 和时钟来源于 APB2 总线时钟,其最大频率为 72MHz,其他四个的时钟来源于 APB1 总线时钟,其最大频率为 36MHz,速率可达4.5Mbps。UART 只是异步传输功能,所以没有 SCLK、 nCTS 和 nRTS 功能引脚。

我们需要重点关注的是发送数据引脚TX,和接收数据引脚RX

USART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。

一个字符帧发送需要三个部分:起始位 + 数据帧 + 停止位。起始位是一个位周期的低电平,位周期就是每一位占用的时间;数据帧就是我们要发送的 8 位或 9 位数据,数据是从最低位开始传输的;停止位是一定时间周期的高电平。

当选择 8 位字长,使用 1 个停止位时,具体发送字符时序图见图字符发送时序图:

数据接收时只需更改相关寄存器的值,原理和上述差不多。

这里说明波特率在寄存器中如何设置,下面先给出计算公式:

fck为 USART 时钟(72MHz或36MHz),需要我们设置的 USARTDIV 是一个存放在波特率寄存器 (USART_BRR) 的一个无符号定点数。其中 DIV_Mantissa[11:0] 位定义 USARTDIV 的整数部分, DIV_Fraction[3:0] 位定USARTDIV 的小数部分。

例如USART1使用APB2(72MHz)的时钟,为得到115200bps的波特率,代入公式可以算的USARTDIV = 39.0625,则DIV_Fraction = 0.0625*16 = 0x01,DIV_Mantissa = 39 = 0x27,最终USART_BRR = 0x271.

3.USART库函数初始化

(1)USART初始化结构体

1) USART_BaudRate:波特率设置。一般设置为 2400、 9600、 19200、 115200。标准库函数会根据设定值计算得到 USARTDIV 值,从而设置 USART_BRR 寄存器值。
2) USART_WordLength:数据帧字长,可选 8 位或 9 位。它设定 USART_CR1 寄存器的 M 位的值。如果没有使能奇偶校验控制,一般使用 8 数据位;如果使能了奇偶校验则一般设置为 9 数据位。
3) USART_StopBits:停止位设置,可选 0.5 个、 1 个、 1.5 个和 2 个停止位,它设定USART_CR2寄存器的 STOP[1:0] 位的值,一般我们选择 1 个停止位。
4) USART_Parity:奇偶校验控制选择,可选 USART_Parity_No(无校验)、 USART_Parity_Even(偶校验) 以及 USART_Parity_Odd(奇校验),它设定 USART_CR1 寄存器的 PCE 位和 PS 位的值。
5) USART_Mode: USART 模式选择,有 USART_Mode_Rx 和 USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定 USART_CR1 寄存器的 RE 位和 TE 位。
6) USART_HardwareFlowControl:硬件流控制选择,只有在硬件流控制模式才有效,可选有使能 RTS、 使能 CTS、 同时使能 RTS 和 CTS、 不使能硬件流。

当使用同步模式时需要配置 SCLK 引脚输出脉冲的属性,标准库使用一个时钟初始化结构体USART_ClockInitTypeDef 来设置,该结构体内容也只有在同步模式才需要设置。

(2)USART时钟初始化结构体

异步 无需设置。

1) USART_Clock:同步模式下 SCLK 引脚上时钟输出使能控制,可选禁止时钟输出(USART_Clock_Disable) 或开启时钟输出 (USART_Clock_Enable);如果使用同步模式发送,一般都需要开启时钟。它设定 USART_CR2 寄存器的 CLKEN 位的值。
2) USART_CPOL:同步模式下 SCLK 引脚上输出时钟极性设置,可设置在空闲时 SCLK 引脚为低电平 (USART_CPOL_Low) 或高电平 (USART_CPOL_High)。它设定 USART_CR2 寄存器的 CPOL位的值。
3) USART_CPHA:同步模式下 SCLK 引脚上输出时钟相位设置,可设置在时钟第一个变化沿捕
获数据 (USART_CPHA_1Edge) 或在时钟第二个变化沿捕获数据。它设定 USART_CR2 寄存器的
CPHA 位的值。 USART_CPHA 与 USART_CPOL 配合使用可以获得多种模式时钟关系。
4) USART_LastBit:选择在发送最后一个数据位的时候时钟脉冲是否在 SCLK 引脚输出,可以是
不输出脉冲 (USART_LastBit_Disable)、输出脉冲 (USART_LastBit_Enable)。它设定 USART_CR2 寄存器的 LBCL 位的值。

下一篇写实验案例。


参考资料:

1.串口通信详解

2.野火《STM32库开发指南》

如需了解具体使用到的寄存器,可以参考官方文档,其他博客或书籍。

  • 17
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是基于STM32的USART串行通信实验步骤: 1. 首先,需要确认使用的是哪一款STM32芯片,并且需要将其连接到电脑上。 2. 然后,打开Keil或者其他编译器,新建一个工程,并且将所需的库文件添加到工程中。 3. 在代码中引用串口通信相关的库文件,并且初始化串口通信的引脚和波特率等参数。 4. 编写主程序,实现通过串口发送和接收数据的功能。 5. 在代码中添加中断处理函数,用于在收到数据时进行相应的处理。 6. 编译程序,下载到STM32芯片中,然后运行程序,即可进行串行通信实验。 下面是一个简单的STM32串口通信实验代码示例: ``` #include "stm32f10x.h" #include "stdio.h" #include "string.h" void USART1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); 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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_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); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_Cmd(USART1, ENABLE); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); } void USART1_SendChar(uint8_t ch) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, ch); } void USART1_SendString(char* str) { while (*str) { USART1_SendChar(*str++); } } uint8_t USART1_ReceiveChar(void) { while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); return USART_ReceiveData(USART1); } void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t data = USART1_ReceiveChar(); // 处理接收到的数据 } } int main(void) { USART1_Init(); while (1) { USART1_SendString("Hello World!\r\n"); // 延时 } } ``` 在这个示例代码中,我们首先定义了串口通信的参数,在初始化函数中将引脚和波特率等参数初始化,并且开启了中断处理函数。发送和接收数据的函数也被定义在代码中。在主程序中,我们通过发送字符串的方式不断向串口发送数据,同时在中断处理函数中处理接收到的数据。在这个简单的示例中,我们只是简单地处理了接收到的数据,实际应用中需要根据具体的需求进行相应的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值