单片机串口总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
51单片机串口总结
有句话说“尽信书不如无书”,要学好单片机就要不断的、大胆的实验,要多怀疑,即使我们的怀疑最终被证明是错误的那么这也是进步(人们认识事物很多情况下来源于怀疑),当怀疑出现时就要去实践。有很多东西如果不通过实践是不可能掌握其中隐藏的奥秘,就拿51单片机串口通讯这一块,我认为掌握很好了,可以很轻松的实现数据的接收、发送,但这段时间当我重新学习串口时,我才发现里面还有很多小细节从没注意,更别说研究了。对于接收发送程序永远是按照别人的模式来编写程序,并没有真真正正的挖掘深层次的内容。我身边太多的人在临摹别人的程序,当然我不反对,但是希望自己多问几个问什么,单纯的会编程是学不好单片机的,毕竟单片机有自己独特的硬件结构。
开讲之前先简要说一下同步、异步通信:
同步通信:发送方时钟对接收方时钟控制,使双方达到完全同步。
异步通信:发送与接受设备使用各自的时钟控制数据的发送和接受过程(虽然时钟不同,但一般相差不大)。
51单片机串行口结构
从上图中我们看到,51单片机有两个物理上独立的接收、发送缓冲器SBUF,它们共用同一个地址99H,但是请注意:接收缓冲器只能读而不能写,发送缓冲器只写不读。单片机可以同时实现数据的发送与接收功能。
特别注意:接收器是双缓冲结构:当前一个字节从接收缓冲区取走之前,就已经开始接收第
二个字节(串行输入至移位寄存器),此时如果在第二个字节接收完毕而前一个字节还未被读走,那么就会丢失前一个字节。
51单片机串口控制寄存器
关于51单片机的控制寄存器各个位表示的含义在这里我只谈SM2。
SM2为多机控制位,主要用于工作方式2和3,当接收机的SM2=1时,可以利用接收到的RB8来控制是否激活RI(RB8=0不激活RI,收到的数据丢失;RB8=1时收到的数据进入SBUF,并激活RI ,进而在中断服务程序中将数据从SBUF中读走)。当SM2=0时,不论收到的RB8为何值都将使接收到的数据进入SBUF,,并激活RI,通过控制SM2实现多机通信。
51单片机串口通讯方式
51串口通讯方式有3种,方式0、方式1、方式2与方式3,他们的工作模式不尽相同。
首先他们的波特率很容易忽视。方式0与方式2的波特率固定,而方式1和3的波特率由T1的溢出率决定。
方式0的波特率=f/12 系统晶振的12分频,换句话说12M晶振的情况下,其波特率可达1M,速度是很高的(当我们在选用串行器件并采用方式0时需要特别注意器件所能允许的最大时钟频率)。
方式2 =f/64或f/32(当SMOD=1时为f/32,SMOD=0时为f/64)。
曾经我用方式2进行MODBUS通信时,总是通讯失败,我仔细检查程序,没有发现逻辑错误,特别是当我参考别人的程序时,发现很少有人用方式2进行MODBUS通讯,所以当时自己妄下结论51单片机的串行方式2不可用,直到有一天夜里我突然想起方式2的波特率是固定的,试想晶振11.0592M/32或11.0592M/64怎么也不可能是9600啊,怎么可能通信成功。这才恍然大悟,看来还是自己太武断了,没有认真看书啊。有时我们认为我们犯这样的错误很低级,其实我们很多次都是因为这样的小细节导致我们整个系统不正常,正所谓“千里之堤毁于蚁穴”,这些细节真的伤不起啊。
方式1、3波特率=(2smod/32)*T1的溢出率,其中TI的溢出率=f/{12*[256-(TH1)]}.
关于3种通讯方式其中有几点特别容易出错:
1、无论采用哪种通讯方式,数据发送和接受都是低位在先,高位在后。
2 、3种方式作为输出,由于输出是CPU主动发送,不会产生重叠错误,当数据写入SBUF 后,发送便启动(通过单片机内部逻辑控制,与程序无关),当该字节发送结束(SBUF空),
置TI。不要理解为当数据一写入SBUF就置位TI,如果中断允许则在中断中发送数据,这就大错特错了。
3 同样作为输入,可能会产生重叠错误(主要依赖于特定的环境),当一个字节的数据接收完毕(SBUF满)置位RI,表示缓冲区有数据提示CPU读取。
接下来通过一些实验具体说明串口通信中需要注意的地方
1 方式0输出
方式0主要功能是作为移位寄存器,将数据从SBUF中逐位移出,最常见的用法就是外接串入并出的移位寄存器,如74LS164。之前在做这一部分实验时总是利用单片机I/O端口模拟实现,现在想想在串口未被占用的情况下,方式0是最好的实现方式。
利用串口方式0,向74LS164输出字符“0”的编码,程序如下:
该程序采用了中断方式实现,结果是通过74LS164使数码管显示“0”。
实验结果如下:
这里我说明几点:
1 如果采用查询方式,并且只发送一遍,那么程序最后的while(1);不可以省略,否则会出现数码管闪烁的现象(在KEIL环境下,main()函数也是作为一个调用函数,最后也有返回RET,它不像C中的main()函数,当执行完毕后就停止,而是重新复位执行,如此反复,这一点要特别注意)
这是查询方式下不加while(1);的现实效果
2 如果采用中断方式发送,请记得中断中清除TI,仅仅是为了解除中断标志,而不是等待发送结束,因为此时数据早已离开了SBUF跑到外边去了。
3 74LS164最高25MHZ,采用方式0,没有问题。
方式0作为输入模式
以74ls165(最高时钟25MHZ)为例,可以满足要求。
对应结果如下:
(注意:74ls165线传送高位,而串口通信低位在先,所以显示的数据和实际数据高低位正好相反P1.7---P1.0对应D0---D7)。
本程序只接收一次,也许有人会问,中断程序中REN=0,表示什么意思?可不可以改成ES=0?
这个问题很好,首先REN=0表示接收禁止,即不允许串口接收数据;ES=0是禁止中断和单片机是否接收数据没有关系,不接收数据自然中断允许也是徒劳,这两者有很大的区别。我们在很多接收程序中经常可以看到在判断RI标志后紧跟着清除标志位,我想问一下,为什么?????)
如果我们也按照这种模式改写会怎样呢?
实验结果如下