USART 串口协议-stm32入门

通讯接口简介

通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统

STM32 芯片里面集成了很多功能模块,如定时器计数、PWM 输出、AD 采集等等,这些都是芯片内部的电路,这些电路的配置寄存器、数据寄存器都在芯片里面,操作这些寄存器非常简单,直接读写就行了。但是也有一些功能是 STM32 内部没有的,比如我们想要蓝牙无线遥控的功能,想要陀螺仪加速度计测量姿态的功能,STM32 没有,所以就只能外挂芯片来完成,那外挂的芯片,它的数据都在 STM32 外面,STM32 如何才能获取到这些数据呢?这就需要我们在这两个设备之间,连接上一根或者多根通信线,通过通信线路发送或者接受数据,完成数据交换,从而实现控制外挂模块和读取外挂模块数据的目的。所以通信的目的是将一个设备的数据传送到另一个设备。
单片机有了通信的功能,就能与众多别的模块互联,极大地扩展了硬件系统。

通信协议:制定通信的规则,通信双方按照协议规则进行数据收发

通信的目的是进行信息传递,双方约定的规则就是通信协议。

在 STM32 中,集成了很多用于通信的外设模块,比如 USART、I2C、SPI、CAN 和 USB,这么多通信接口,我们这个 C8T6 芯片是全部都支持的。

在 STM32 里面有下表这么多的通信协议:

名称 引脚 双工 时钟 电平 设备
USART TX、RX(或称 TXD、RXD) 全双工 异步 单端 点对点
I2C SCL、SDA 半双工 同步 单端 多设备
SPI SCLK、MOSI、MISO、CS 全双工 同步 单端 多设备
CAN CAN_H、CAN_L 半双工 异步 差分 多设备
USB DP、DM 半双工 异步 差分 点对点
  • 表中只列了通信协议的一个最典型的参数,因为各种通信协议应用都很宽泛,参数也很多,所以这里列出的仅是它最常用、最简单的配置。

  • 通信协议规定的引脚:数据按照协议的规定在这些引脚上进行输入和输出,从而实现通信。

    • TX 与 RX:TX(Transmit Exchange) 是数据发送脚,RX(Receive Exchange) 是数据接收脚。
    • SCL 与 SDA:SCL(Serial Clock)是时钟,SDA 是数据。
    • SCLK、MOSI、MISO、CS:SCLK(Serial Clock)是时钟,MOSI(Master Output Slave Input)是主机输出数据脚,MISO(Master Input Slave Output)是主机输入数据脚,CS(Chip Select)是片选,用于指定通信的对象。
    • CAN_H、CAN_L:这两个是差分数据脚,用两个引脚表示一个差分数据。
    • DP、DM:或者叫 D+ 和 D-,也是一对差分数据脚
  • 双工模式:

    • 全双工:指通信双方能够同时进行双向通信。一般来说,全双工的通信都有两根通信线,比如串口,一根 TX 发送,一根 RX 接收;SPI,一根 MOSI 发送,一根 MISO 接收 。发送线路和接收线路互不影响,全双工。
    • 半双工:剩下的这些,I2C、CAN 和 USB,都只有一根数据线,CAN 和 USB 两根差分线也是组合成为一根数据线的,所以都是半双工。当然还有一种方式,就是单工。
    • 单工:是指数据只能从一个设备到另一个设备,而不能反着来,比如把 串口的 RX 引脚去掉,那串口就退化成单工了。
  • 时钟特性:比如你发送一个波形,高电平然后低电平,接收方怎么知道你是 1、0 还是 1、1、0、0 呢?这就需要有一个时钟信号来告诉接收方,你什么时候需要采集数据。时钟特性分为同步和异步。

    • 同步:这里 I2C 和 SPI 有单独的时钟线,所以它们是同步的,接收方可以在时钟信号的指引下进行采样。
    • 异步:剩下的串口、CAN 和 USB 没有时钟线,所以需要双方约定一个采样频率,这就是异步通信。并且还需要加一些帧头帧尾等,进行采样位置的对齐。
  • 电平特性:

    • 上面三个都是单端信号,也就是它们引脚的高低电平都是对 GND 的电压差,所以单端信号通信的双方必须要共地,就是把 GND 接在一起,所以说这里通信的引脚,前三个还应该加一个 GND 引脚,不接 GND 是无法通信的。
    • 之后 CAN 和 USB 是差分信号,它是靠两个差分引脚的电压差来传输信号的,是差分信号。在通信的时候可以不需要 GND,不过 USB 协议里面也有一些地方需要单端信号,所以 USB 还是需要共地的。使用差分信号可以极大地提高抗干扰特性,所以差分信号一般传输速度和距离都会非常高,性能也是很不错的。
  • 设备特性:

    • 串口 和 USB 属于点对点通信,点对点通信就相当于老师找你去办公室谈话,只有两个人,直接传输数据就可以了。
    • 中间三个是可以在总线上挂载多个设备的,多设备就相当于老师在教室里,面对所有同学谈话,需要有一个寻址的过程,以确定通信的对象。

那本节。我们就来学习一下这里的第一个通信接口 — USART 串口。

1. 串口通信简介

就是软硬件的规则,与某个具体的硬件无关。

1.1 基本概念

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。

  • 在单片机领域,串口其实是一种最简单的通信接口。它的协议相比较 I2C、SPI 等,已经是非常简单了。而且一般单片机,它里面都会有串口的硬件外设,使用也是非常方便的。
  • 一般串口都是点对点通信,所以是两个设备之间的互相通信。

单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力。

其中单片机和电脑通信是串口的一大优势,可以接电脑屏幕,非常适合调试程序,打印信息,像 I2C 和 SPI 这些,一般都是芯片之间的通信,不会接在电脑上。

USART 串口协议-stm32入门_第1张图片
一些使用串口通讯的模块:

  1. USB 转串口模块,上面有个芯片,型号是 CH340,这个芯片可以把串口协议转换为 USB 协议,它一边是 USB 口,可以插在电脑上,另一边是串口的引脚,可以和支持串口的芯片接在一起,这样就能实现串口和电脑的通信了。
  2. 陀螺仪传感器的模块,可以测量角速度、加速度这些姿态参数,它左右各有 4 个引脚,一边是串口的引脚,另一边是 I2C 的引脚。
  3. 蓝牙串口模块,下面 4 个脚是串口通信的引脚,上面的芯片可以和手机互联,实现手机遥控单片机的功能。

1.2 硬件电路

简单双向串口通信有两根通信线(发送端 TX 和接收端 RX),复杂的串口通信还有其他引脚,比如时钟引脚、硬件流控制的引脚,这些引脚 STM32 的串口也有,不过我们最常用的还是简单的串口通信。也就是 VCC、GND、TX 和 TX 这 4 个引脚。

TX与RX要交叉连接。TX 是发送,RX 是接收,那肯定是一个设备的发送接另一个设备的接收,一个设备的接收接另一个设备的发送 这样来接线。这个注意一下,别接错了。

当只需单向的数据传输时,可以只接一根通信线。比如你只需要设备 1 向设备 2 的单向通信,那就可以只接这一根 TX 到 RX 的线,另一根就可以不接,这就变成了单工的通信方式。

当电平标准不一致时,需要加电平转换芯片。串口也是有很多电平标准的,像我们这种,直接从控制器里出来的信号,一般都是 TTL 电平,相同的电平才能互相通信,不同的电平信号,需要加一个电平转换芯片,转接一下。

USART 串口协议-stm32入门_第2张图片
串口接线图:
一般串口通信的模块都有 4 个引脚:VCC、TX、RX、GND。
VCC 和 GND 是供电,TX 和 RX 是通信的引脚。TX 和 RX 是单端信号,它们的高低电平都是相对于 GND 的,所以严格上来说,GND 应该也算是通信线。所以,串口通信的 TX、RX、GND 是必须要接的。上面的 VCC,如果两个设备都有独立供电,那 VCC 可以不接,如果其中一个设备没有供电。比如这里设备 1 是 STM32,设备 2 是蓝牙串口模块,STM32 有独立供电,蓝牙串口没有独立供电,那就需要把蓝牙串口的 VCC 和 STM32 的 VCC 接在一起,STM32 通过这根线,向右边的子模块供电,当然供电的电压也需要注意一下,要按照子模块的要求来,这就是供电要求。

1.3 电平标准

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

  • TTL电平:+3.3V或+5V表示1,0V表示0。
  • 我们在单片机电路中最常见的是 TTL 电平,也就是 5V 或者 3.3V 表示逻辑 1,0V 表示逻辑 0,这是我们最多遇到的电平标准。但是串口还有一些其他的电平标准,这里了解一下。
  • 这里 1 的电压,如果你是 5V 的器件,就是 +5V;如果是 3.3V 的器件,就是 +3.3V。逻辑 1,就是高电平的电压,就是 VCC 的电压。
  • RS232 电平:-3~-15V表示1,+3~+15V表示0

RS232 电平一般在大型的机器上使用,由于环境可能比较恶劣,静电干扰比较大,所以这里电平的电压都比较大,而且允许波动的范围也很大。

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

这里电平参考是两线压差,所以 RS485 电平是差分信号,差分信号抗干扰能力非常强,使用 RS485 电平标准,通信距离可以达到上千米。而上面这两种电平,最远只能达到几十米,再远就传不了了。

像单片机这种低压小型设备,使用的都是 TTL 电平,我们之后的内容,也都是基于 TTL 电平来讲解的,如果你做设备需要其他的电平,那就再加电平转换芯片就行了,在软件层面,它们都属于串口,所以程序并不会有什么变化。

到这里,串口协议的硬件部分我们就清楚了。在硬件电路上,协议规定是,一个设备使用 TX 发送高低电平,另一个设备使用 RX 接收高低电平。在线路中,使用 TTL 电平,因为 STM32 是 3.3V 的器件,所以如果线路对地是 3.3V,就代表发送了逻辑 1;如果线路对地是 0V,就代表发送了逻辑 0,那现在如何接线,如何发送 1 和 0 我们就知道了。

1.4 串口参数及时序

接下来我们来看一下串口协议的软件部分。如何用 1 和 0,来组成我们想要发送的一个字节数据。

USART 串口协议-stm32入门_第3张图片

这两个时序图就是串口发送一个字节的格式。这个格式是串口协议规定的,串口中,每一个字节都装载在一个数据帧里面,每个数据帧都由起始位、数据位和停止位组成,这里数据位有 8 个,代表一个字节的 8 位;在下边这个数据帧里面,还可以在数据位的最后,加一个奇偶校验位,这样数据位总共就是九位,其中有效载荷是前 8 位,代表一个字节,校验位跟在有效载荷后面,占 1 位,这就是串口数据帧的整体结构。

那我们来看一下串口的参数:

  1. 波特率:串口通信的速率

串口一般是使用异步通信,所以需要双方约定一个通信速率,比如我每隔 1s 发送一位,那你就也得每隔 1s 接收一位,如果你接收快了,那就会重复接收某些位。如果你接收慢了,那就会漏掉某些位,所以说发送和接收,必须要约定好速率,这个速率参数,就是波特率。
波特率本来的意思是每秒传输码元的个数,单位是 码元/s,或者直接叫波特(Baud);另外还有个速率表示,叫比特率,比特率的意思是每秒传输的比特数,单位是 bit/s,或者叫 bps。在二进制调制的情况下,一个码元就是一个 bit,此时波特率就等于比特率,像我们单片机的串口通信,基本都是二进制调制,也就是高电平表示 1,低电平表示 0,一位就是 1bit,所以说,这个串口的波特率,经常会和比特率混用,不过这也是没关系的,因为这两个说法的数值相等。如果是多进制调制,那比特率和波特率就不一样了,这个了解一下。
那反应到波形上,比如我们双方规定波特率为 1000bps,那就表示,1s 要发 1000 位,每一位的时间就是 1ms,发送方每隔 1ms 发送一位,接收方每隔 1ms 接收一位,这就是波特率,它决定了每隔多久发送一位。

  1. 起始位:标志一个数据帧的开始,固定为低电平
  • 在时序图的波形中,首先,串口的空闲状态是高电平,也就是没有数据传输的时候,引脚必须要置高电平,作为空闲状态,然后需要传输的时候,必须要先发送一个起始位,这个起始位必须是低电平,来打破空闲状态的高电平,产生一个下降沿,这个下降沿,就告诉接收设备,这一帧数据要开始了。如果没有起始位,那当我发送 8 个 1 的时候,是不是数据线就一直都是高电平,没有任何波动,对吧,这样接收方怎么知道我发送数据了呢?所以这里必须要有一个固定为低电平的起始位,产生下降沿,来告诉接收设备,我要发送数据了。
  • 同原理,在一个字节数据发送完成之后,必须要有一个停止位。停止位的作用是:用于数据帧间隔,固定为高电平。同时这个停止位,也是为下一个起始位做准备的,如果没有停止位,那当我数据最后一位是 0 的时候,下次再发送新的一帧,是不是就没法产生下降沿了,对吧,这就是起始位和停止位的作用。

起始位固定为 0,产生下降沿,表示传输开始,停止位固定为 1,把引脚恢复成高电平,方便下一次的下降沿,如果没有数据了,正好引脚也为高电平,代表空闲状态。

  1. 数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行

比如我要发送一个字节,是 0x0F,那就首先把 0F 转换为二进制,就是 0000 1111,然后低位先行,所以数据要从低位开始发送。也就是 1111 0000,像这样,依次放在发送引脚上,所以最终,引脚的波形就是 111(空闲状态) 0(起始位) 1111 0000 1(停止位) 111(空闲状态)。所以说如果你想发送 0x0F 这一个字节数据,那就按照波特率要求,定时翻转引脚电平,产生一个这样的波形就行了。

  1. 校验位:用于数据验证,根据数据位计算得来

这里串口使用的是一种叫奇偶检验的数据验证方法,奇偶校验可以判断数据传输是不是出错了,如果数据出错了,可以选择丢弃或者要求重传,校验可以选择 3 种方式,无校验、奇校验和偶校验,无校验,就是不需要校验位,波形就是上边这个,起始位、数据位、停止位,总共 3 个部分;奇校验和偶校验的波形是下边这个,起始位、数据位、校验位、停止位,总共 4 个部分。如果使用了奇校验,那么包括校验位在内的 9 位数据会出现奇数个 1,比如如果你传输 0000 1111,目前总共 4 个 1,是偶数个,那么校验位就需要再补一个 1,连同检验位就是 0000 1111 1,总共 5 个 1,保证 1 为奇数;如果数据是 0000 1110,此时 3 个 1,是奇数个,那么检验位就补一个 0,连同校验位就是 0000 1110 0,总共还是 3 个 1,1 的个数为奇数。发送方在发送数据后,会补一个校验位,保证 1 的个数为 奇数,接收方在接收数据后,会验证数据位和检验位,如果 1 的个数还是奇数,就认为数据没有出错,如果在传输中,因为干扰,有 1 位由 1 变成 0,或者由 0 变成 1 了,那么整个数据的奇偶特性就会变化,接收方一验证,发现 1 的个数不是奇数,那就认为传输出错,就可以选择丢弃或者要求重传,这就是奇校验的差错控制方法。如果选择双方约定偶校验,那就是保证 1 的个数为偶数,校验方法也是一样的道理。当然奇偶校验的 检出率并不是很高,比如如果有两位数据同时出错,奇偶特性不变,那就校验不出来了,所以奇偶校验只能保证一定程度上的数据校验,如果想要更高的检出率,可以了解一下 CRC 校验,这个校验会更加好用,当然也会更复杂,我们这个 STM32 内部也有 CRC 的外设,可以了解一下。

  1. 停止位:用于数据帧间隔,固定为高电平

我们这里的数据位,有两种表示方法,一种是把检验位作为数据位的一部分,就像上面那个时序一样,分为 8 位数据和 9 位数据,其中 9 位数据,就是 8 位有效载荷和 1 位校验位;另一种就是把数据位和校验位独立开,数据位就是有效载荷,校验位就是独立的 1 位,像上面的描述,就是把数据位和校验位分开描述了,在串口助手软件里,也是用的这种分开描述的方法,数据位 8 位,检验位 1 位。总之,无论是合在一起,还是分开描述,描述的都是同一个东西,这个应该也好理解。

1.5 串口通信的实际波形

通过波形理解串口是如何来传输数据的,这些波形是用示波器实测的。(操作方法是,把探头的 GND 接在负极,探头接在发送设备的 TX 引脚,然后发送数据,就能捕捉到这些波形了。
USART 串口协议-stm32入门_第4张图片

  1. 第一个波形是发送一个字节数据 0x55 时,在 TX 引脚输出的波形,波特率是 9600,所以每一位的时间就是 1/9600,大概是 104us,可以看到,这里一位就是 100us 多一点,就是 104us,没发送数据的时候,是空闲状态高电平,数据帧开始,先发送起始位,产生下降沿,代表数据帧开始,数据 0x55 转到二进制,低位先行,就是依次发送 1010 1010,然后这个参数是 8 位数据,1 位停止,无校验,没有校验位,所以之后就是停止位,把引脚置回高电平,这样一个数据帧就完成了,在 STM32 中,这个根据字节数据翻转高低电平,是由 USART 外设自动完成的,不用我们操心,当然你也可以软件模拟产生这样的波形,那就是定时器定一个 104us 的时间,时间到之后,按照数据帧的要求,调用 GPIO_WriteBit 置高低电平,产生一个和这一模一样的波形,这样也是可以完成串口通信的。TX 引脚发送,就是置高低电平,那在 RX 引脚接收,显然就是读取高低电平了,这也可以由 USART 外设自动来完成,不用我们操心,如果想软件模拟的话,那就是定时调用 GPIO_ReadInputDataBit 来读取每一个位,最终拼接成一个字节。当然接收的时候,应该还需要一个外部中断,在起始位的下降沿,进入接收状态,并且对齐采样时钟,然后依次采样 8 次,这就是接收的逻辑。
  2. 接着看下下面的波形,如果发送 0xAA,波形就是第二个波形这样的,起始位,然后 0101 0101,停止位,结束,再下面,如果发送 0xFF,就是 8 个 1,那波形就是第三个波形这样的,起始位,8 个 1,停止位,结束,在起始位下降沿之后的一个数据帧的时间内,这个高电平就是数据 1 来看的,当数据帧结束后,这里虽然还是 1,没有任何变化,但此时的 1,已经是属于空闲状态了,它需要等待下一个下降沿,来开启新的一帧数据,之后再看下面,如果发送 0x00,就是 8 个 0,那波形就是第四个波形这样的,起始位,8 个 0,停止位置回高电平,这样来进行。
  3. 然后继续看右边的波形,将波特率改为 4800,也就是波特率变为一半,那相应的波形时长就会变为原来的二倍,可以看到,这里 10 位数据总共大概 2ms 多一点,具体应该在 2.08ms,那一位就是 208us,是之前的二倍,数据波形的时间拉宽,波形的变化趋势是不变的,之后看下面这第二个波形,这里加了一个偶校验位,数据是 0x55,1 的个数是 4 个,已经是偶数了,所以输出的校验位是 0,低电平,此时包括校验位在内的数据总共是偶数个 1,总的波形就是这个样子。最后看一下停止位的变化,串口的停止位是可以进行配置的,可以选择 1 位、1.5 位、2 位等。看一下,这第三个波形是 1 位停止位,连续发送两个 0x55,两个数据帧会接在一起,中间没有空闲状态,这第四个波形是 2 位停止位,连续发送两个 0x55,可以看到,这里停止位就是两位的宽度,中间也没有空闲状态,不过这样数据分隔的就更宽一些了,这就是不同长度停止位的现象。

到这里,有关串口协议的硬件和软件就介绍完了,总结一下就是,TX 引脚输出定时翻转的高低电平,RX 引脚定时读取引脚的高低电平,每个字节的数据加上起始位、停止位、可选的校验位,打包成数据帧,依次输出在 TX 引脚,另一端 RX 引脚依次接收,这样就完成了字节数据的传递。这就是串口通信。

2. STM32 内部的 USRAT 外设

2.1 USRAT 简介

外设作用:按照串口协议来产生和接收高低电平信号,实现串口通信。

USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器

  • 我们经常还会遇到串口,叫 UART,这里少了 S,就是异步收发器;
  • 其实这个STM32 的 USART 同步模式,只是多了个时钟输出而已,它只支持时钟输出,不支持时钟输入,所以这个同步模式更多的是为了兼容别的协议或者特殊用途而设计的,并不支持两个 USART 之间进行同步通信。所以我们学习串口,主要还是异步通信。
  • 一般我们串口很少使用同步功能。所以 USART 和 UART 使用起来,也没什么区别。

USART 是 STM32 内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从 TX 引脚发送出去,也可自动接收 RX 引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里。

  • 我们之前学习串口协议,串口主要就是靠收发约定好的波形来进行通信的,那这个 USART 外设,就是串口通信的硬件支持电路,USART 大体可分为发送和接收两部分,发送部分就是将数据寄存器的一个字节数据,自动转换为协议规定的波形,从 TX 引脚发送出去;接收部分就是自动接收 RX 引脚的波形,按照协议规定,解码为一个字节数据,存放在数据寄存器里。这就是 USART 电路的功能。
  • 当我们配置好了 USART 电路,直接读写数据寄存器,就能自动发送和接收数据了。

自带波特率发生器,最高达4.5Mbits/s

这个波特率发生器就是用来配置波特率的,它其实就是一个分频器,比如我们 APB2 总线给个 72MHz 的频率,然后波特率发生器进行一个分频,得到我们想要的波特率时钟,最后在这个时钟下,进行收发,就是我们指定的通信波特率。

可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)

  • 这些就是 STM32 的 USART 支持配置的参数了,这个数据位长度就是我们 串口参数及时序 节的参数,有 8 位和 9 位,是包含奇偶校验位的长度,一般不需要校验就选 8 位,需要校验就选 9 位。
  • 停止位长度支持三种停止位,也就是在进行连续发送时,停止位长度决定了帧的间隔,我们最常用的就是 1 位停止位,其他的很少用。

可选校验位(无校验/奇校验/偶校验)

我们最常用的是无校验。

以上这些所有的参数,都是可以通过配置寄存器来完成的。使用库函数配置的话,就更简单了,直接给结构体赋值就行了。

串口参数我们最常用的是波特率 9600 或者 115200,数据位 8 位,停止位 1 位,无校验,一般我们都选这种常用的参数,不用纠结,选它就是了。

支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN

  • 同步模式,就是多了个时钟 CLK 的输出
  • 硬件流控制,比如 A 设备有个 TX 向 B 设备的 RX 发送数据,A 设备一直在发,发的太快了,B 处理不过来,如果没有硬件流控制,那 B 就只能抛弃新数据或者覆盖原数据了,如果有硬件流控制,在硬件电路上,就会多出一根线,如果 B 没准备好接收,就置高电平,如果准备好了,就置低电平,A 接收到了 B 反馈的准备信号,就只会在 B 准备好的时候,才发数据,如果 B 没准备好,那数据就不会发送出去。这就是硬件流控制,可以防止因为 B 处理慢而导致的数据丢失的问题。硬件流控制,STM32 也是有的,不过我们一般不用,需要的话可以了解一下。
  • DMA,是这个串口支持 DMA 进行数据转运,如果有大量的数据进行收发,可以使用 DMA 转运数据,减轻 CPU 的负担。
  • 智能卡、IrDA、LIN,这些是其他的一些协议,因为这些协议和串口是非常像的,所以 STM32 就对 USART 加了一些小改动,就能兼容这么多协议了。不过我们一般不用。智能卡应该是跟我们刷的饭卡、公交卡这类有关的;IrDA 用于红外通信,这个红外通信就是一个红外发光管,另一边是红外接收管,然后靠闪烁红外光通信,并不是我们遥控器的那个红外通信,所以并不能模拟遥控器;LIN 是局域网的通信协议,这个感兴趣的话,可以自己研究一下。

STM32F103C8T6 USART资源: USART1、 USART2、 USART3

总共 3 个独立的 USART 外设,可以挂载很多串口设备,其中这里 USART1 是 APB2 总线上的设备,剩下的都是 APB1 总线上的设备,这个就开启时钟的时候注意一下,在使用的时候,挂载在哪个总线,影响并不是很大。

2.2 USART 框图

USART 串口协议-stm32入门_第5张图片
这个框图一眼看上去还是非常复杂的,但是实际上主要部分也没有很多,它这里就是把各个寄存器和寄存器每一位控制的地方都画出来了,所以才显得比较乱,我们看的时候可以先忽略这些寄存器,先看主体结构。

  1. 左上角的引脚部分,有 TX 和 RX,这两个就是发送和接收引脚;下面这里的 SW_RX、IRDA_OUT/IN 这些是智能卡和 IrDA 通信的引脚,我们不用这些协议,所以这些引脚就不用管的。右边这个框框,IrDA、SIR 这些东西也都不用管的。引脚这块,TX 发送脚,就是从这里接出去的,RX 接收脚,就是通向这里,这样就行了。
  2. 然后灰色区域部分就是串口的数据寄存器了,发送或接收的字节数据就存在这里。上面这有两个数据寄存器,一个是发送数据寄存器 TDR(Transmit DR),另一个是接受数据寄存器 RDR(Receive DR),这两个寄存器占用同一个地址,就跟 51 单片机串口的 SBUF 寄存器一样,在程序上,只表现为一个寄存器,就是数据寄存器 DR(Data Register),但实际硬件中,是分成了两个寄存器,一个用于发送 TDR,一个用于接收 RDR,TDR 是只写的,RDR 是只读的,当你进行写操作的时候,数据就写入到 TDR;当你进行读操作的时候,数据就从 RDR 读出来的,这个了解一下。 然后往下看,下面是两个移位寄存器,一个用于发送,一个用于接收,发送移位寄存器的作用就是,把一个字节的数据一位一位的移出去,正好对应串口协议的波形的数据位。这两个寄存器如何工作?举个例子,比如你在某时刻给 TDR 写入 0x55 这个数据,在寄存器里就是二进制存储,0101 0101,那么此时,硬件检测到你写入数据了,它就会检查,当前移位寄存器是不是有数据正在移位,如果没有,这个 0101 0101 就会立刻全部移动到发送移位寄存器,准备发送,当数据从 TDR 移动到移位寄存器时,会置一个标志位,叫 TXE(TX Empty),发送寄存器空,我们检查这个标志位,如果置 1 了,我们就可以在 TDR 写入下一个数据了,注意一下,当 TXE 标志置 1 时,数据其实还没有发送出去,只要数据从 TDR 转移到发送移位寄存器了,TXE 就会置 1,我们就可以写入新的数据了,然后发送移位寄存器就会在下面的发生器控制的驱动下,向右移位,然后一位一位的,把数据输出到 TX 引脚,这里是向右移位,所以正好和串口协议规定的低位先行,是一致的,当数据移位完成后,新的数据就会再次自动的从 TDR 转移到发送移位寄存器里来,如果当前移位寄存器移位还没有完成,TDR 的数据就会进行等待,一旦移位完成,就会立刻转移过来,有了 TDR 和 移位寄存器的双重缓存,可以保证连续发送数据的时候,数据帧之间不会有空闲,提高了工作效率。简单来说,就是你数据一旦从 TDR 转移到移位寄存器了,管你有没有移位完成,我就立刻把下一个数据放在 TDR 等着,一旦移完了,新的数据就会立刻跟上,这样做,效率就会比较高。然后看一下接收端这里,也是类似的,数据从 RX 引脚通向接收移位寄存器,在接受器控制的驱动下,一位一位的读取 RX 电平,先放在最高位,然后向右移,移位 8 次之后,就能接受一个字节了,同样,因为串口协议规定是低位先行,所以接收移位寄存器是从高位往低位这个方向移动的,之后,当一个字节移动完成后,这一个字节的数据就会整体的一下子转移到接收数据寄存器 RDR 里来,在转移的过程中,也会置一个标志位,叫 RXNE(RX Not Empty),接收数据寄存器非空,当我们检测到 RXNE 置 1 之后,就可以把数据读走了,同样,这里也是两个寄存器进行缓存,当数据从移位寄存器转移到 RDR 时,就可以直接移位接收下一帧数据了,这就是 USART 外设整个的工作流程。

到这里,这个外设的主要功能就差不多了。大体上,就是数据寄存器和移位寄存器,发送移位寄存器往 TX 引脚移位,接收移位寄存器从 RX 引脚移位,当然发送还需要加上帧头帧尾,接收还需要剔除帧头帧尾,这些操作,它内部有电路会自动执行,我们知道有硬件帮我们做了这些工作就行了。

  1. 接着我们继续看一下下面的控制部分和其他增强部分,下面这里是发送器控制,它就是用来控制发送移位寄存器的工作的,接收器控制,用来控制接收移位寄存器的工作的,然后左边有一个硬件数据流控,也就是硬件流控制,简称流控。前面我们也大概介绍过,如果发送设备发的太快,接收设备来不及处理,就会出现丢弃或覆盖数据的现象,那有了流控,就可以避免这个问题,这里流控有两个引脚,一个是 nRTS,一个是 nCTS,nRTS(Request To Send)是请求发送,是输出脚,也就是告诉别人,我当前能不能接收;nCTS(Clear To Send)是清除发送,是输入脚,也就是用于接收别人 nRTS 的信号的,这里前面加个 n 意思是低电平有效,那这两个引脚怎么玩的呢?首先得找另一个支持流控的串口,它的 TX 接到了我的 RX,然后我的 RTS 要输出一个能不能接收的反馈信号,接到对方的 CTS,当我能接收的时候,RTS 就置低电平,请求对方发送,对方的 CTS 接收到之后,就可以一直发。当我处理不过来时,比如接收数据寄存器我一直没有读,又有新的数据过来了,现在就代表我没有及时处理,那 RTS 就会置高电平,对方 CTS 接收到之后,就会暂停发送,直到这里接收数据寄存器被读走,RTS 置低电平,新的数据才会继续发送,那反过来,当我的 TX 给对方发送数据时,我们 CTS 就要接到对方的 RTS,用于判断对方,能不能接收,TX 和 CTS 是一对的,RX 和 RTS 是一对的,CTS 和 RTS 也要交叉连接,这就是流控的工作模式。

我们一般不使用流控,所以流控就了解一下就行。

  1. 右边 SCLK 控制部分电路用于产生同步的时钟信号,它是配合发送移位寄存器输出的,发送寄存器每移位一次,同步时钟电平就跳变一个周期,时钟告诉对方,我移出去一位数据了,你看要不要让我这个时钟信号来指导你接收一下?当然这个时钟只支持输出,不支持输入,所以两个 USART 之间,不能实现同步的串口通信,那这个时钟信号有什么用呢?第一个用途:兼容别的协议,比如串口加上时钟之后,就跟 SPI 协议特别像,所以有了时钟输出的串口,就可以兼容 SPI;另外这个时钟也可以做自适应波特率,比如接收设备不确定发送设备给的什么波特率,那就可以测量一下这个时钟的周期,然后再计算得到波特率,不过这就需要另外写程序来实现这个功能了。这个时钟功能,我们一般不用,所以也是了解一下就行了。
  2. 中间这个唤醒单元,这部分的作用是实现串口挂载多设备,我们之前说,串口一般是点对点的通信,点对点,支支持两个设备互相通信,想发数据直接发就行,而多设备,在一条总线上,可以接多个从设备,每个设备分配一个地址,我想跟某个设备通信,就先进行寻址,确定通信对象,再进行数据收发。这个唤醒单元就可以用来实现多设备的功能,在这里可以给串口分配一个地址,当你发送指定地址时,此设备唤醒开始工作;当你发送别的设备地址时,别的设备就唤醒工作,这个设备没收到地址,就会保持沉默,这样就可以实现多设备的串口通信了。这部分功能我们一般不用,大家也了解一下就行。
  3. 下面有中断输出控制,中断申请位,就是状态寄存器这里的各种标志位,状态寄存器这里就(接受其控制模块下方),有两个标志位比较重要,一个是 TXE 发送寄存器空,另一个是 RXNE 接收寄存器非空,这两个是判断发送状态和接收状态的必要标志位,刚才也都讲过,剩下的标志位了解一下就行。中断输出控制这里,就是配置中断是不是能通向 NVIC,这个应该好理解。
  4. 最下面是波特率发生器部分,之前提到过,波特率发生器其实就是分频器,APB 时钟进行分频,得到发送和接收移位的时钟,看一下,这里时钟输入是 fPCLKx(x = 1 或 2),USART1 挂载在 APB2,所以就是 PCLK2 的时钟,一般是 72M,其他的 USART 都挂载在 APB1,所以是 PCLK1 的时钟,一般是 36M,之后这个时钟进行一个分频,除一个 USARTDIV 的分频系数,USARTDIV 里面就是右边这样,是一个数值,并且分为了整数部分和小数部分,因为有些波特率,用 72M 除一个整数的话,可能除不尽,会有误差,所以这里分频系数是支持小数点后 4 位的,分频就更加精准,之后分频完之后,还要再除一个 16,得到发送器时钟和接收器时钟,通向控制部分,然后右边这里,如果 TE(TX Enable)为 1,就是发送器使能了,发送部分的波特率就有效,如果 RE(RX Enable)为 1,就是接收器使能了,接收部分的波特率就有效。

剩下还有一些寄存器的指示,比如各个 CR 控制寄存器的哪一位控制哪一部分电路,SR 状态寄存器都有哪些标志位,这些可以自己看看手册里的寄存器描述,那里的描述比这里清晰很多。

最后我们再看看串口的引脚。在引脚定义表的复用功能这一栏就给出了每个 USART,它的各个引脚都是复用在了哪个 GPIO 口上的,比如这里 USART2 的 TX 是 PA2 口,RX 是 PA3 口,USART3 的 TX 和 RX 分别是 PB10 和 PB11,然后,USART1 的 TX 和 RX 分别是 PA9 和 PA10,这些引脚都必须按照引脚定义里的规定来。
USART 串口协议-stm32入门_第6张图片
比如你要使用 USART1,那 TX 必须是 PA9,RX 必须是 PA10,或者看一下重映射这里,有没有重映射,这里有 USART1 的重映射,所有有机会换一次口。剩下的引脚,就没有机会作为 USART1 的接口了,所以这个表在设计电路的时候很重要,要提前规划好引脚,别让引脚复用功能冲突了,有关外设的复用引脚是哪个的问题,都是看引脚定义表,一看就知道。

2.3 USART 基本结构

USART 串口协议-stm32入门_第7张图片
这就是 USART 最主要、最基本的结构。

  1. 最左边是波特率发生器,用于产生约定的通信速率,时钟来源是 PCLK2 或 1,经过波特率发生器分频后,产生的时钟通向发送控制器和接收控制器。
  2. 发送控制器和接收控制器,用来控制发送移位和接收移位,之后,由发送数据寄存器和发送移位寄存器这两个寄存器的配合,将数据一位一位的移出去,通过 GPIO 口的复用输出,输出到 TX 引脚,产生串口协议规定的波形,这里画了几个右移的符号,这就代表这个移位寄存器是往右移的,是低位先行。当数据由数据寄存器转移到移位寄存器时,会置一个 TXE 的标志位,我们判断这个标志位,就可以知道是不是可以写下一个数据了。
  3. 然后接收部分也是类似的,RX 引脚的波形,通过 GPIO口 输入,在接收控制器的控制下,一位一位的移入接收移位寄存器,这里画了右移的符号,也是右移的,因为是低位先行,所以要从左边开始移进来,移完一帧数据后,数据就会统一转运到接受数据寄存器,在转移的同时,置一个 RXNE 标志位,我们检查这个标志位,就可以知道是不是收到数据了,同时这个标志位也可以去申请中断,这样就可以在收到数据时,直接进入中断函数,然后快速的读取和保存数据。
  4. USART 内部结构中实际上有 4 个寄存器,但是在软件层面,只有一个 DR 寄存器可以供我们读写,写入 DR 时,数据走上面这条路,进行发送;读取 DR 时,数据走下面这条路,进行接收,这就是 USART 进行串口数据收发的过程。
  5. 最后右下角是一个开关控制,就是配置完成之后,用 Cmd 开启一下外设。

3. 细节问题

3.1 数据帧

USART 串口协议-stm32入门_第8张图片
这个图是在程序中配置 8 位字长和 9 位字长的波形对比。这里的字长就是我们前面说的数据位长度。它这里的字长,是包含校验位的描述方式。

  1. 上面 9 位字长的波形:
    1. 第一条时序,很明显就是 TX 发送或者 RX 接收的数据帧格式,空闲高电平,然后起始位 0,然后根据写入数据,置 1 或 0,依次发送位 0 到 位 8,共 9 位,最后停止位 1,数据帧结束,在这里位 8,也就是第 9 个位置,是一个可能的奇偶校验位,通过配置寄存器就可以配置成奇校验、偶校验或者无校验。这里可以选择配置成 8 位有效载荷 + 1 位校验位,也可以选择 9 位全都是有效载荷,不过既然选择了 9 位字长,那一般都是要加上校验位的,因为 8 位有效载荷,正好对应一个字节。
    2. 然后下面这个时钟,就是我们之前说的同步时钟输出的功能,可以看到在每个数据位中间,都有一个时钟上升沿,时钟频率和数据速率也是一样的,接收端可以在时钟上升沿进行采样,这样就可以精准定位每一位数据,这个时钟的最后一位,可以通过这个 LBCL 位控制要不要输出,另外这个时钟的极性、相位什么的,也可以通过配置寄存器配置,需要的话可以了解一下。
    3. 然后下面这两个波形,一个是空闲帧,就是从头到尾都是 1,还有一个是断开帧,就是从头到尾都是 0,这两个数据帧,是局域网协议用的,我们串口用不着,不用管的。
  2. 下面 8 位字长的波形:
    1. 可以看到,这里的数据位是从位 0 一直到 位 7,总共是 8 位,比上面这个少了一个位 8,同样这个最后一位位 7,也是一个可能的奇偶校验位,还是同样,既然选择了 8 位字长,那这里就最好选择无校验,要不然校验位占 1 位,有效载荷就只剩7 位了,一个字节都发不了,这不逼死强迫症么。
    2. 最后这些时钟什么的,跟上面也是类似的。

总的来说,这里有 4 种选择,9 位字长,有校验或无校验;8 位字长,有校验或无校验;但我们最好选择 9 位字长,有校验 或 8 位字长,无校验这两种,这样每一帧的有效载荷都是 1 字节,这样才舒服。

USART 串口协议-stm32入门_第9张图片
接下来我们继续来看这个数据帧不同停止位的波形变化。

STM32 的串口可以配置停止位长度为 0.5、1、1.5、2 这四种。这四种参数区别就是停止位的时长不一样。

  1. 第一个是 1 个停止位,这时停止位的时长就和数据位是一位,时长一样。
  2. 然后是 1.5 个停止位,这时的停止位就是数据位的 1 位,时长是 1.5 倍。
  3. 2 个停止位,那停止位时长就是 2 倍。
  4. 0.5 个停止位,时长就是 0.5 倍。

就是控制停止位的时长的,一般选择 1 位停止位就行了。其他的参数不太常用。

3.2 USART 电路输入数据的一些策略

3.2.1 起始位侦测

USART 串口协议-stm32入门_第10张图片

3.2.2 数据采样

USART 串口协议-stm32入门_第11张图片

你可能感兴趣的:(stm32,stm32,嵌入式硬件,单片机)