前面两个章节全部讲解了单片机串口的相关理论基础,本章节突出讲解一下单片机串口通信的实际操作。这章写完才发现,写的有点多!!!但是这里面的东西确实值得大家学习,有个思想特别重要,写代码就是一个不断完善的过程。下面请跟随我的脚步,一步一步的来完善串口控制的程序。
其实不太想使用 51单片机的串口来作为讲解的例子,因为它的串口设计的有点垃圾。功能上需要定时器来进行相关的辅助。一个功能掺杂了两块硬件功能。这在程序上就叫做杂糅!但是苦于其他类型的单片机对于首次编程的各位又不太友好。所以万般无奈之下还是强忍着巨大的难受使用 51 单片机作为本章主角。
如上图:现在我们最关心的问题就是:如何把 A 中的 110 数据传递到 B 当中去???
上面这个问题就是我们本次学习的重点。有人会问?那如何把 B 的数据传递给 A 呢?傻小子,你把上面的问题搞会了,反过来是不是就可以了?如果你不会反过来,那我只能说一句,你那么多头发给我吧。
编程简介:
你和别人远程说话,需要什么?(电话呀!)我擦咧,你怎么这么厉害?对了,你们需要一个交流的工具。好,51单片机也需要一个交流的工具:它就是 SBUF,SBUF,SBUF 重要的东西讲三遍。它是个什么玩意呢?首先我先将上面的图优化一下
这幅图怎么理解呢?A和自己的SBUF交流。B和SBUF交流。而(A的SBUF) 通过 tx,rx 连接(B的SBUF)。这样就间接的实现了 A 和 B 交流。
类似于:小红和小红的iphone说话,小明和小明的华为说话。他们两部手机通过电磁波连接在了一起。就间接的实现了小红和小明说话。 -------- 一般这里要跟上作者名字,卒于 xxxx 年。
很显然,如果A想发数据给B,它就要告诉 SBUF 想发的数据是什么!比如发送 110 ,那么 A 的程序就应该写成 SBUF = 110;而 B 想要知道 A 传输过来的数据是什么,它就要问 SBUF,刚刚传过来的数字是多少,并且B需要给 SBUF 盛放数据的地方?程序就是:data = SBUF。这里的 data 就能读取到刚刚 A 那边发过来的数据了,也就是 110.
程序也就可以这么写。
是不是突然觉得很简单?那当然啦,这种只能算是示意程序,就是有了大致功能,但是根本没用。为什么呢?因为你见过一个手机没有开机,就能和别人打电话的?千万别和我说什么乔布斯的 iphone 1000 。我没用过,我也不知道。
下面,我们需要做的,就是让 SBUF 可以正常开机工作。怎么开机呢?这就要说到 51 单片机串口最奇葩的地方,它需要使用定时器来驱动串口,跟个傻子似的!!!一个一个来吧。
首先我们介绍以下 51 串口的控制器:
很简单,就一个 SCON 控制单元。我们需要关注的就是 SM0 和 SM1 ,REN,TI,RI。
1,SM0 和 SM1 的设置
其实我们用的最多的就是方式 1 :10位异步收发器(8位数据)。这是什么意思呢?还记得上节说的,我们传输的是1个字节的数据 = 8位,再加上起始,停止,一共 10 位,这样,和方式 1 完全吻合。(那我们如何确定什么时候用哪一种呢?这就需要根据双方的设置来确定了,双方只要传输位数和采样波特率两个东西一致的话,就是可以进行通讯的)。
2,REN ,
REN 代表这 rec enable :也就是说,如果打开了 REN(REN = 1),那么串口就可以实现接受的功能了,这是什么意思呢?其实 SBUF 上面的 tx 和 rx ,只有 tx 是默认打开可以直接用的,而 rx 默认关闭,需要人为设置一下。
3,TI ,RI。
还记得A,B之间是如何通信的吗?就是通过两者的 SBUF 来进行通信的。那么我们怎么才能知道 SBUF 到底有没有发送完成或则接收到数据呢?这就要 TI 和 RI 的闪亮登场了。比如 A 给 B 发送 110,A先把110传给SBUF,当 SBUF 把数据传输出去以后,A 的 TI 就被设置成了 1.(这个过程是自动的,不需要管,你只要知道,TI变成1了就可以发送下一个数据了。)而 B 的 SBUF 在接受到数据之后就会把 RI 设置成 1.(这个过程也是自动的,你只要知道,RI 变成 1,你就能读取 SBUF 中接受的数据了)。
到这里我们就能再把程序进行一下变形了:
这时候程序可以正常运行了吗? --- 当然还差一点点,就差给它点最核心的东西了,它的动力源泉。
========================== 最恶心的波特率设置。
这里我还是在调侃一下,51 单片机这种硬件设计还是挺恶心的。好了,不扯了,我们再来看看什么叫波特率或则为什么要设置波特率。
讲个简单的故事。上课做笔记的时候,老师在黑板上写字,你在往本子上记录。会出现一下三种情况:
- 老师写字比你快,这样擦黑板的时候,你就还没写完。
- 老师写字和你一样块,这样他写一个字,你写一个字,你们刚好同时结束。(最理想的情况)
- 老师写字比你慢,这样你每次抬头只能看到同一个字,你就会发现,你的笔记上都是重复的字啥的,根本不是有效的信息。
波特率其实就是单片机之间通信的速率,它就是为了保证 A 和 B 之间可以同步进行通信。这样我们这么来讲,最关键,最装逼的地方要来了!注意,注意(重要的事情我说三遍),我要开始装逼了。大家最长看到波特率为 9600,38400,115200.这是什么意思呢?就是 1s 中传输 9600,38400,115200 个位。(1位 = 1个高低信号)。
下面以 9600 的波特率来说明:请记住这个公式:
暂时先让 SMOD = 0,那么就可以变形为: 波特率 = T1 溢出率 / 32。那么简单了,我要开始出题考试了,小学三年级的题目:已知波特率 9600,求 T1 的溢出率。(T1溢出率也就是定时器 1 每次运行到最大值的时间)。T1溢出率 = 9600 * 32 = 307200。(T1 的溢出率也就是 T1运行到最大值的频率)。也就是说,T1运行的时间 = 1 / T1频率(T1的溢出率)。那么 T1 需要运行的时间 t = 1 / 307200 = 3us。那好,还记得单片机每运行一步是多久吗?对于 12 Mhz 的晶振来说,就是 1us。至于为什么,这里补充说明下:{51 单片机的晶振一般是 12Mhz 和 11.0592Mhz。不知道有没有人知道一件事,51单片机的 CPU 时钟是晶振的 12 分频。(啥?不知道?去把你妈叫来)。我们可以简单的理解为:如果使用 51单片机,那么它的 CPU 频率就是 1Mhz(此时晶振 12Mhz)。上狗头铡(错了,再来,上公式:时间 = 1 / 周期),CPU运行一步的时间 = 1 / 1Mhz = 1us (这个说法有点不准确,但是易于理解),而且我瞧瞧告诉你们,单片机的定时器走一步和CPU走一步时间是一样的!!!}。那么我们最终的程序就是:
至此,经过以上不懈的努力,我们终于让 A , B 有情人终成眷属了。