stm32学习笔记---USART串口协议(理论部分)
通信的目的将一个设备的数据传送到另一个设备,扩展硬件系统比如STM32芯片它里面集成了很多功能模块,比如定时器计数,PWM输出、AD采集等等。这些都是芯片内部的电路,这些电路的配置寄存器,数据寄存器都在芯片里面,操作这些寄存器非常简单,直接读写就行了。但是也有些功能是STM32内部没有的,比如我们想要蓝牙无线遥控的功能,想要陀螺仪加速度计测量姿态的功能。STM32没有这些功能,所以就只能外挂芯片来
目录
声明:本专栏是本人跟着B站江科大的视频的学习过程中记录下来的笔记,我之所以记录下来是为了方便自己日后复习。如果你也是跟着江科大的视频学习的,可以配套本专栏食用,如有问题可以QQ交流群:963138186
本节开始来学习STM32的通信接口。
在STM32中集成了很多用于通信的外设模块。之前我在51单片机专栏写过USART和I2C的介绍,没有基础的学习者可以先去稍微了解一下
单片机学习笔记---串口通信(1)_单片机db9-CSDN博客
单片机学习笔记---串口通信(2)_为什么ri=0且sm2=0,才将数据移入-CSDN博客
单片机学习笔记---AT24C02(I2C总线)_i2c发送应答和接收应答区别-CSDN博客
首先我们来了解一下通信接口
通信
我们为什么要通信?
通信的目的
将一个设备的数据传送到另一个设备,扩展硬件系统
比如STM32芯片它里面集成了很多功能模块,比如定时器计数,PWM输出、AD采集等等。这些都是芯片内部的电路,这些电路的配置寄存器,数据寄存器都在芯片里面,操作这些寄存器非常简单,直接读写就行了。
但是也有些功能是STM32内部没有的,比如我们想要蓝牙无线遥控的功能,想要陀螺仪加速度计测量姿态的功能。
STM32没有这些功能,所以就只能外挂芯片来完成。外挂的芯片的数据都在STM32外面。STM32如何才能获取到这些数据?
这就需要我们在这两个设备之间连接上一根或多根通讯线,通过通信线路发送或者接收数据,完成数据交换,从而实现控制外挂模块和读取外挂模块数据的目的。所以在这里通信的目的是将一个设备的数据传送到另一个设备。单片机有了通信的功能,就能与众多别的模块互联,极大的扩展了硬件系统。
通信需要遵守通信协议
通信协议
制定通信的规则,通信双方按照协议规则进行数据收发
比如说你考试的时候想给别人传答案,你就可以和对方约定一个通信协议。比如先咳嗽一声,代表通信开始,然后竖一个手指,代表发生a,竖两个手指代表发生b,竖三个手指代表发送c,然后挥一挥手,代表通讯结束。这就是一种通信方式。
通信的目的是进行信息传递。双方约定的规则,就是通信协议。当然,考试作弊是不对的!这里只是打个比方!
STM32的通信协议
以上这些通信接口,我们这个C8T6芯片是全部都支持的。
这个表只是列了一个最典型的参数。因为各种通讯协议应用都非常宽泛,参数也很多。所以这里列出的仅是它最常用最简单的配置。
各种协议的通信引脚介绍
USART串口通信,它的引脚是TX和RX,有的地方也叫TXD和RXD,这两种名称是一个意思,TX是数据发送脚,RX是数据接收脚。
I2C通信,引脚SCL是时钟,SDA是数据。
SPI通信,引脚SCLK是时钟,MOSI(Mater Output Slave Input)是主机输出数据脚,MISO(Mater Input Slave Output)是主机输入数据脚,CS是片选,用于指令通信的对象。
CAN通信,引脚是CAN_H和CAN_L这两个是差分数据脚,用两个引脚表示一个差分数据。
USB通信,引脚是DP(Data Positive)和DM(Data Minus),或者叫D+和D-,也是一对差分数据脚。
这就是这些通信协议规定的引脚,数据按照协议的规定,在这些引脚上进行输入和输出,从而实现通信。
通信空间和时间
全双工就是指通信双方能够同时进行双向通信。一般来说,传双工的通信都有两根通信线,比如串口通信,一根TX发送,一根RX接收。SPI通信,一根MOSI发送,一根MISO接收。发送线路和接收线路互不影响全双工(双向,同时)。
剩下的这些I2C、CAN看和USB都只有一根数据线,CAN和USB两根差分线也是组合成一根数据线的,所以都是半双工(双向,分时)。
单工(单向)是指数据只能从一个设备到另一个设备,而不能反着来。比如把串口的RX引脚去掉,串口就退化成单工了。
时钟特性
关于时钟特性,比如发送一个波形高电平,然后低电平,接收方怎么知道是1、0还是1、1、0、0?
这就需要有一个时钟信号来告诉接收方什么时候需要采集数据。时钟特性分为同步和异步。
I2C和SPI有单独的时钟线,所以它们是同步的,接收方可以在时钟信号的指引下进行采样。
串口、CAN和USB没有时钟线,所以需要双方约定一个采样频率,这就是异步通信,并且还需要加一些帧头、帧尾等,进行采样位置的对齐。
电平特性
关于电平特性,USART、I2C、SPI都是单端信号,也就是它们引脚的高低电平都是对GND的电压差,所以单端信号通信的双方必须要供地,就是把GND接在一起。所以说USART、I2C、SPI通信的引脚除了表格中列出的几个,还应该加一个GND引脚,不接GND是没法通信的。
CAN和USB是差分信号,它是靠两个差分引脚的电压差来传输信号的,指差分信号在通信的时候可以不需要GND,不过USB协议里面也有一些地方需要单端信号,所以USB还是需要供地的。使用差分信号可以极大的提高抗干扰特性。所以差分信号一般传输速度和距离都会非常高,性能也是很不错的。
设备特性
关于设备特性,USART串口和USB属于点对点的通信。I2C、SPI和CAN是可以在总线上挂载多个设备的。点对点通信就相当于老师找你去办公室谈话,只有两个人直接传输数据就可以了。多设备就相当于老师在教室里面对所有同学谈话,需要有一个寻址的过程,以确定通信的对象。
然后我们就来学习一下串口的知识点。接下来的内容主要分为两个部分。
串口通信
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
它的协议相比较I2C、SPI等,串口是非常简单的。而且一般单片机它里面都会有串口的硬件,外设使用也是非常方便的。一般串口都是点对点的通信,所以是两个设备之间的互相通信。
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力
其中单片机和电脑通信是串口的一大优势,可以接电脑屏幕,非常适合调试程序打印信息。像I2C和SPI这些一般都是芯片之间的通信,不会接在电脑上。
然后看下面这几个串口的设备,
第一个是USB转串口模块,上面有个芯片,型号是CH340,这个芯片可以把串口协议转换为USB协议,它一边是USB口可以插在电脑上。另一边是串口的引脚,可以和支持串口的芯片接在一起,这样就能实现串口和电脑的通信了。
第二个是一个陀螺仪传感器的模块,可以测量角速度、加速度这些姿态参数,它左右各有四个引脚,一边是串口的引脚,另一边是I2C的引脚。
第三个是蓝牙串口模块,下面四个脚是串口通信的引脚,上面的芯片可以和手机互联,实现手机遥控单片机的功能。
这些就是串口通信和一些使用串口通信的模块。
硬件电路
如何来接这个串口的线?
简单双向串口通信有两根通信线(发送端TX和接收端RX)
这里是简单的串口通信,复杂一点的串口通信,还有其它引脚,比如时钟引脚,硬件流控制的引脚,这些引脚,STM32的串口也有。不过我们最常用的还是简单的串口通信,也就是VCC、GND、TX、RX这四个引脚。
TX与RX要交叉连接
肯定得是一个设备的发送接另一个设备的接收,一个设备的接收接另一个设备的发送。
当只需单向的数据传输时,可以只接一根通信线
比如你只需要设备一向设备二的单向通信,就可以只接一根TX到RX的线,另一根就可以不接,这就变成了单工的通信方式。
下面这个图就是串口的接线图,
一般串口通信的模块都有四个引脚,VCC和GND是供电,TX和RX是通信的引脚,TX和RX是单端信号,它们的高低电平都是相对于GND的,所以严格上来说GND应该也算是通信线。所以串口通信的RX、TX、GND是必须要接的。如果两个设备都有独立供电,VCC可以不接。
如果其中一个设备没有供电,比如这里设备1是STM32,设备是蓝牙串口模块。STM32有独立供电,蓝牙串口没有独立供电,就需要把蓝牙串口的VCC和STM32的VCC接在一起。STM32通过VCC-VCC这根线向右边的子模块供电。
当然供电的电压也需要注意一下,要按照子模块的要求来,这就是供电要求。
当电平标准不一致时,需要加电平转换芯片
串口也是有很多电平标准的,像我们这种直接从控制器里出来的信号,一般都是TTL电平,相同的电平才能互相通信,不同的电平信号需要加一个电平转换芯片转接一下。
电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系。
在单片机电路中最常见的是TTL电平,也就是5V或者3.3V表示逻辑1,0V表示逻辑0,这是我们最多遇到的电平标准。
但是串口还有一些其它的电平标准,稍微了解一下,串口常用的电平标准有如下三种:
TTL电平:+3.3V或+5V表示1,0V表示0
RS232电平:-3~-15V表示1,+3~+15V表示0
这种电平一般在大型的机器上使用,由于环境可能比较恶劣,静电干扰比较大,所以这里电平的电压都比较大,而且允许波动的范围也很大。
RS485电平:两线压差+2~+6V表示1,-2~-6V表示0(差分信号)
电平参考是两线压差,所以这种电平是差分信号。差分信号抗干扰能力非常强。
使用RS485电平电平标准时,通信距离可以达到上千米。
TTL电平和RS232电平最远只能达到几十米,再远就传不了了。
以上这些电平在软件层面,它们都属于串口,所以程序并不会有什么变化。
串口参数及时序
时序
这是串口发送一个字节的格式,这个格式是串口协议规定的。
串口中每一个字节都装载在一个数据帧里面,每个数据帧都由起始位、数据位和停止位组成。这里数据位有八个代表一个字节的八位
在下面这个数据帧里面还可以在数据位的最后加一个奇偶校验位,这样数据位总共就是九位,其中有效载荷是前八位代表一个字节,校验位跟在有效载核后面占一位。
这就是串口数据帧的整体结构。
串口的参数
波特率:串口通信的速率
串口一般是使用异步通信,所以需要双方约定一个通信速率。比如每隔一秒发送一位,就也得每隔一秒接收一位。如果接收快了,就会重复接收某些位。如果接收慢了,就会漏掉某些位,所以说发送和接收必须要约定好速率。这个速率参数就是波特率。波特率的意思是每秒传输码元的个数。单位是码元每秒,或者直接叫波特。
另外还有个速率表示叫比特率。比特率的意思是每秒传输的比特数,单位是bit/s或者叫bps。
在二进制调制的情况下,一个码元就是一个比特,此时波特率就等于比特率。单片机的串口通信基本都是二进制调制,也就是高电平表示1低电平表示0,一位就是1bit。所以说这个串口的波特率经常会和比特率混用,不过这也是没关系的,因为这两个说法的数值相等,如果是多进制调制,波特率就和比特率不一样了。
反映到波形上,比如我们双方规定波特率为1000bps,就表示一秒要发1000位,每一位的时间就是一毫秒,也就是这里这一段时间是一毫秒:
发送方每隔一毫秒发送一位,接收方每隔一毫秒接收一位,这就是波特率,它决定了每隔多久发送一位。
起始位:标志一个数据帧的开始,固定为低电平
首先串口的空闲状态是高电平,也就是没有数据传输的时候,引脚必须要置高电平,作为空闲状态。然后需要传输的时候,必须要先发送一个起始位。这个起始位必须是低电平,来打破空闲状态的高电平产生一个下降沿,这个下降沿就告诉接收设备,这一帧数据要开始了。
如果没有起始位,当发送八个1的时候,数据线就一直都是高电平,没有任何波动,这样接收方不知道我们发送数据了。所以这里必须要有一个固定为低电平的起始位产生下降沿来告诉接收设备我们要发送数据了。
同理在一个字节数据发送完成后,必须要有一个停止位。
停止位:用于数据帧间隔,固定为高电平
停止位也是为下一个起止位做准备的。如果没有停止位,当数据最后一位是0的时候,下次再发动新的一帧,是不是就没法产生下降沿了,这就是起始位和停止位的作用。
起始位固定为零,产生下降沿,表示传输开始,停止位固定为1,把引脚恢复成高电平,方便下一次产生下降沿。如果没有数据了,正好引脚也为高电平,代表空闲状态。
数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
比如要发送一个字节是0x0F,就首先把0F转换为二进制,就是0000 1111,然后低位先行,所以数据要从低位开始发送,也就是1111 0000像这样依次放在发送引脚上,所以最终引脚的波形就是这样的。
所以说如果你想发送0x0F这一个字节数据,就按照波特率要求定时翻转引脚电平,产生一个这样的波形就行了。
校验位:用于数据验证,根据数据位计算得来
串口使用的是一种叫奇偶校验的数据验证方法,奇偶校验可以判断数据传输是不是出错了,如果数据出错了,可以选择丢弃或者要求重传。校验可以选择三种方式,无校验、奇校验和偶校验。无校验就是不需要校验位,就是只有起始位、数据位、停止位总共三个部分。奇校验和偶校验就是起始位、数据位、校验位、停止位总共四个部分:
如果使用了奇校验,那包括校验位在内的九个数据会出现奇数个1。比如,如果传输0000 1111,目前总共四个1,是偶数个,则校验位就需要再补一个1,连同校验位就是,0000 1111 1,总共五个1,保证1为奇数。如果数据是0000 1110,此时3个1,是奇数个,则校验位就补一个0,连同校验位就是0000 1110 0,总共还是三个1,1的个数为奇数。
发送方在发送数据后会补一个校验位,保证1的个数为奇数。接收方在接收数据后会验证数据位和校验位。如果1的个数还是奇数,就认为数据没有出错。如果在传输中,因为干扰有一位由1变成0或者由0变成1了,那么整个数据的奇偶特性就会变化。接收方一验证发现1的个数不是奇数,就认为传输出错,就可以选择丢弃或者要求重传,这就是奇校验的差错控制方法。
如果选择双方约定偶校验,就是保证1的个数是偶数,校验方法也是一样的道理。
当然,奇偶校验的检出率并不是很高。比如如果有两位数据同时出错。奇偶特性不变,就校验不出来了。所以奇偶校验只能保证一定程度上的数据校验。如果想要更高的检出率,可以了解一下CRC校验。这个校验会更加好用,当然也会更复杂。我们这个STM32内部也有CRC的外设,可以了解一下。
最后再说明一下,我们这里的数据位有两种表示方法。
一种是把校验位作为数据位的一部分,就像上面的时序图一样,分为八位数据和九位数据,其中九位数据就是八位有效载荷和一位校验位。
另一种就是把数据位和校验位独立开,数据位就是有效载荷,校验位就是独立的1位。
像上面的描述就是把数据位和校验位分开描述了。在串口助手软件里也是用的这种分开描述的方法,数据位八位,校验位一位。
总之无论是合在一起还是分开描述,描述的都是同一个东西。
最后我们来看几个串口通信的实际波形。
串口通信的实际波形
第一个波形
这个波形是发送一个字节数据0x55时在TX引脚输出的波形。波特率是9600,所以每一位的时间就是1/9600,大概是104us。在示波器上可以看到一位就是一百微秒多一点,就是一百零四微秒。
没发送数据的时候是空闲状态,高电平。数据帧开始先发送起始位,产生下降沿代表数据帧开始。数据0x55转为二进制,低位先行,就是依次发送1010 1010。这个参数是八位数据,1位停止,无校验。没有校验位,所以之后就是停止位,把引脚置回高电平,这样一个数据帧就完成了。
在STM32中,根据字节数据翻转高低电平是由USART外设自动完成的,不用我们操心。当然也可以软件模拟产生这样的波形,就是定时器定一个104us的时间。时间到之后,按照数据帧的要求,调用GPIO_WriteBit置高低电平产生一个和这一模一样的波形,这样也是可以完成串口通信的。
TX引脚发送就是置高低电平,RX引脚接收就是读取高低电平,这也可以由USART外设自动来完成,不用我们操心。如果想软件模拟的话,就是定时调用GPIO_ReadInuputDataBit来读取每一位,最终拼接成一个字节。当然接收的时候应该还需要一个外部中断,在起始位的下降沿触发,进入接收状态,并且对齐采样时钟,然后依次采样八次,这就是接收的逻辑。
第二个波形
这个把波特率改成4800,也就是波特率变为一半,相应的波形时长就会变为原来的二倍。再示波器上可以看到这里,十位数据总共大概两毫秒多一点,具体应该在2.08ms,一位就是208us,是之前的二倍。数据波形的时间拉宽,波形的变化趋势是不变的。
第三个波形
这个波形加了一个偶校验位,数据是0x55,1的个数是四个,已经是偶数,所以输出的校验位是0,低电平,此时包括校验位在内的数据总共是偶数个1。
接下来看一下停止位不同波形。
串口的停止位是可以进行配置的,可以选择1位,1.5位,2位等。
第四个波形
这上面的波形是1位停止位,连续发送两个0x55,两个数据帧会接在一起,中间没有空闲状态。
第五个波形
这个波形是2位停止位,连续发送两个0x55,可以看到停止位是2位的宽度,中间也没有空间状态,不过这样数据分隔的就更宽一些。
这就是不同长度停止位的现象。
总结:TX引脚输出定时翻转的高低电平,RX引脚定时读取引脚的高低电平。每个字节的数据加上起始位、停止位、可选的校验位,打包成数据帧依次输出在TX引脚,另一端RX引脚依次接收,这样就完成了字节数据的传递。这就是串口通信。
QQ交流群:963138186
本篇就到这里,下篇继续!欢迎点击下方订阅本专栏↓↓↓
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)