前言
通信是建立在多个对象的基础之上,本文您将了解到
- 通信的七种方式
- 波特率和比特率区别
- 异步通信为何要设置波特率
- SBUF寄存器
- 波特率如何计算
1、通信方式
通信的方式有很多种,比如单工、半双工、全双工、串行通信、并行通信、异步通信、同步通信
等等.可能听到这么多专有名词觉得头大,其实很简单,具体举几个例子你就能明白了:
单工
:一端接收,一端发送.比如电视,广播;半双工
:A可以发送信息到B,B也可以发送到A,但是不能同时进行,比如对讲机,每次结束都会加上一句over;全双工
:AB可以同时收发数据,这就很厉害了,比如手机.串行通信
:一根线传输,适用于长距离传输,比如当前计算机网络均为串行通信并行通信
:多根线传输数据,速率比串行大.但是长距离传输时信道相互之间的干扰大, 只适合短距离传输,比如计算机内部总线的数据传输.异步通信
:双方各自时间可以不同,是通过起始位和停止位来辅助同步的,也就是A发送一段数据,结束之后会有一个停止字符告知B这段数据到此为止.同步通信
:双方提前设置好时钟频率,保持发送和接收数据的频率是一样的,如果同步通信的A和B时钟不同,传输过来的数据就会乱码.
这几种通信方式有交集也有相互独立的部分,由此可见,我们的单片机的通过TX
端和RX
端的通信方式是全双工串行异步通信,而IIC
、SPI
等通信是串行同步通信。
2、波特率和比特率区别
比特率
:比特率(Bit rate,变量Rbit)是单位时间内传输或处理的比特的位数。单位
:通常单位为“位每秒”( bit/s, b/s),也写作bps(bit per second)。“b” 应该总是小写,以避免与“字节每秒”(Bytes/s, B/s)混淆。波特率
:单位时间内载波参数变化的次数。它反应的是一种调制速率,通过不同的调制方式,可以在一个码元符号上负载多个bit位信息。
单位“波特”本身就已经是代表每秒的调制数,以“波特每秒”(Baud per second)为单位是一种常见的错误。一个信号码元可以用多个二进制代码组成,也就是调制方式的不同,在单片机的UART通信中,它是按一个一个二进制位发送数据的,因此这种状态下,波特率和比特率是数值相同,但是内涵不同,想要具体地了解可以看看这篇文章,写得比较详细:比特率与波特率的区别
3、异步通信为何要设置波特率
那么既然说了我们的TX和RX这样的异步通信方式,通信的双方时钟可以不一样,但是为什么在串口通信的时候我们还需要在串口助手里面设置相同的波特率呢?网上找到一篇文章:异步通信还要设置波特率?_深入理解同步/异步通信
但是觉得文章没有讲明白。这里我认为设置波特率有两点原因:
1、通信的双方都需要一定的时钟同步,只不过同步通信是按照帧来传输数据的,帧的数据量是远远大于字节的,它对于时钟要求很高,需要时钟完全同步,不能有半点差池。而异步通信,因为多了起始符、结束符、校验位等等,容错率比较大,可以容忍波特率较小的差异,但是也不能差别太大。这也就是为什么,IIC和SPI等有时钟线,时钟可以完全同步,不需要设置波特率,但是异步通信而言,就需要我们手动设置波特率,来减小他们的时钟差距。
2、设置了波特率,接收器就能决定采样频率,在某个比波特率高的频率下采集RX线上电平,这样效率比较高。
4、SBUF寄存器
接下来看看串口的缓存区,以51单片机为例,串行口中有两个缓冲寄存器SBUF
,一个是发送寄存器,一个是接收寄存器,在物理结构上是完全独立的。它们都是字节寻址的寄存器,字节地址均为99H
。这个重叠的地址靠读/写指令区分:串行发送时,CPU
向SBUF
写入数据,此时99H表示发送SBUF
;串行接收时,CPU
从SBUF
读出数据,此时99H
表示接收SBUF
。 我觉得这是两个寄存器的段地址相同但是偏移地址不同,在不同的时间两个SBUF
可以分别工作。
5、波特率如何计算
最后来看看波特率是如何计算的,51单片机的波特率是根据定时器溢出而来的,而定时器的时钟又与晶振和分频系数有关。如果要产生波特率,最好是将定时器设置在自动重装的工作方式1,防止其他操作指令延时导致波特率不准确。
- 方式1的波特率 =(2^SMOD/32)*(T1溢出率)
- SMOD是PCON寄存器的最高位,这个公式与硬件电路有关,不必深究。
- 对于T1的溢出率公式可以好好理解一下:T1 溢出率 = fosc /{12×[256 -(TL1)]},fosc是晶振频率,也就是对应的时钟周期(一个机器周期对应12个时钟周期),也就是机器周期采用了分频处理,因为TL1寄存器为八位,最多可计数到256,先装入初值TL1,根据频率计算出定时器的溢出时间,以此来计算波特率,应该不难理解。
- 12M的晶振如果把波特率设置为4800,则计算的初值约为0xf3不过不要紧,波特率和上位机的相差不大即可,毕竟是异步通信。如果想要精确设置波特率的话,就可以采用11.0592M的晶振,计算得到的TL1的值为精准的0xF4。