单片机xpl是什么意思_单片机与上位机的串行通信

本文介绍了51单片机中串行通信的工作方式,着重讲解了如何通过定时器产生固定波特率,以及单片机与上位机的串行通信过程。讲解了波特率计算公式,举例说明了如何设置定时器初值以实现9600波特率,并提到了涉及的相关寄存器和中断标志位。此外,概述了单片机接收和发送数据的基本步骤。
摘要由CSDN通过智能技术生成
330bccd2c4de425898b4cb5cbd2fd30f.png点击“蓝字”关注我们吧 这篇文章主要记录下单片机是如何通过TXD、RXD与上位机进行数据交换的。
  先介绍下51单片机中与串口通信有关的各种寄存器。
  首先,上位机如果要发送数据给单片机,单片机接收到数据之后,会存入到SBUF这个发送/接收寄存器,这个寄存器非常特殊,兼具发送和接收时存放数据的功能。如果是data = SBUF,则会把SBUF接收到上位机发送过来的数据存入到data中;如果是SBUF = data,则会把单片机想要发送的数据即data中的数据送入到SBUF中,然后再通过串口发送到上位机。
  在接收数据时,单片机会产生中断,不然单片机不知道什么时候接收完一位数据,这个中断叫做串口中断,服务程序是interrupt4,标志位是RI,所以进入串口中断服务程序时一定要记得把RI清零,不然程序就会一直进入串口中断服务程序。控制串口中断的寄存器叫SCON,它的每一位如下:

edbbe845b0a132d8546456779d941523.png

ba4a368c6c10cf1eb51eac0a80812e76.png

  这里关于4种工作方式如果展开了讲的话,实在太庞大,所以读者如果有疑惑可以自行百度。这里解释一下用定时器产生固定波特率的问题,我翻看了很多其他同学写的博客,发现他们有很多都不清楚方式1和3中为啥要给TH1、TL1(这里用定时器1举例)一个固定的初值。其实这个固定的初值是很多其他前辈算出来的初值,如果要自己计算也是完全可以的,公式如下(戴胜华教授《单片机原理与应用》):

374c9cab1549bfdefd070b4199f2b748.png

 上式中出现到SMOD1,这一位是由电源寄存器PCON的第七位来控制的,假设我们规定好串行口工作在方式1或3的一个初值,原本波特率为9600,SMOD置1后,波特率翻倍,会变为19200,,很好理解。
  注意注意:这里的串行口工作方式0123跟定时器工作方式0123不是同一个东西,一定要分开。
  串行口工作方式为0123任意一种都能通过使用定时器1工作在方式2来产生相应的波特率。
  这里给出常用波特率相对应的定时器初值:

837304de297422e3abf9d667704f100b.png

举例假如我要让串口产生9600的波特率,我使用串口工作方式1、3,定时器1工作在方式2,那么公式就等于 波特率(9600)=2^0/32 * fosc/12 * 1/(2^k-初值) ,这里我们晶振频率为11.0592MHz,波特率为9600Hz,注意单位转换,K是计数器的计数为啥,定时器方式2为八位自动重装,所以K=8,那么等式就变为了 9600 = 1/32 * 11059200/12 * 1/(256-初值) ,化简一下 1/3 = 1/256-初值,那么初值就要为253,十六进制则是0xFD,则定时器每次放进TL1的初值就要为0xFD,这样就能产生9600的波特率。
  再解释一下为什么定时器中的高八位和低八位相同,以定时器1举例,如果定时器1工作在方式2即八位自动重装模式,会用低八位TL1来计数,用高八位来保存计数初值。TL1计数回到0时自动将TH1中的初值送回TL1中,完成自动重装。
  回到正题,SCON中REN这一位为允许接收控制位,置0则禁止串口接收数据,置1则反之。TB8和RB8是用于方式2和3中发送和接收数据的第9位,我这里不在过多解释,需要用的时候,再仔细百度。TI是发送中断标志位,发送完毕会自动置1,在发送数据前一定要先清零TI,发送完后可根据TI来判断是否发送完毕。RI则是接收中断标志位,可以根据RI的值来判断单片机是否接受完上位机发送来的数据。
  总结一下,串口发送和接收涉及到的寄存器相应的位有:PCON中的SMOD,SCON中的SM0、SM1、REN、TI、RI,TH0、TL0(TH1、TL1),TMOD中的M1、M0(控制定时器的工作方式),IE中的EA、ES(允许总中断、允许串口中断),TCON中的TR0(TR1)。
  单片机接收上位机数据工作过程大致为:定时器产生一定波特率——单片机与上位机通过TXD、RXD开始通信——单片机允许串口中断,允许接收数据——单片机接收到数据,进入串口中断服务程序,并将RI置1,软件将RI清零,读取SBUF。
  单片机发送数据到上位机工作过程大致为:定时器产生一定波特率——单片机与上位机通过TXD、RXD开始通信——单片机赋值给TI——单片机发送数据给上位机——上位机接收到数据。
  下面这两段程序是在郭天祥《新概念51单片机C语言教程》以及参考其他同学的博客写的。
  郭天祥:

0de0819bd2ad41b8fb0b8c1e33779d4f.png

824997c20c5465c158f8037e4e09f559.png

结合按键,按一下发送一行字符:

6a68d1e16ad0c1506502591880568961.png

03f36f83d64ceb8ae04d15ff41e7f6f4.png

8585ad155a02b20f7b2c25b2315e0426.png

 上面郭天祥那段代码中,只接收了上位机发送的一位数据,我又花了点时间改出了一段程序,分别是可以接受多位数据以及根据上位机送来的数据控制流水灯,两段代码就综合到一起了,注释部分是接收多位数据。

bf1c07107db7651d54001525a21237d0.png

71dcc9464425b8e2bb4ac86966d6839d.png

018762fdc05ae53ca53a35b24368a362.png

 目前程序中我觉得不足的地方是发送代码中的while(!TI),这里会把单片机一直占用住,按照之前按键扫描延时尽量不用delay的惯例,这里的while等待我觉得也有不妥,但是不确定是不是我自己想多了,还需要以后深入学习才能得出结论。
  如有错误,欢迎评论指正,本人也是边学边总结,一方面检验自己是否真的理解,另一方面如有错误理解也能及时发现及时改正。
  为什么串口的波特率与定时器有关?
  最近再次看回这篇博客不禁思考,这两者有什么联系吗?为什么要用定时器1来控制波特率为什么不能用定时器2,百度了一下发现原来51单片机串口的波特率是与定时器1的溢出率有关,这一点在上面计算波特率的时候的公式里面有体现。定时器的溢出率顾名思义就是与定时器的溢出速率有关,大概意思可能是定时器溢出一次的时间,那么晶振频率如果为11.0592MHz,时钟周期就是1/11.0592,机器周期为12/11.0592,则单片机定时器+1的时间为12/11.0592us,溢出率=溢出一次的时间=计数次数*机器周期,所以通过改变定时器的初值就能改变定时器的溢出率,也就改变了串口的波特率。
  波特率这里也顺带解释一下,就是串口每秒能接受的比特数bit,因为串口是一位一位数据按顺序发送,波特率9600就是串口每秒钟能接收的bit数为9600位,如果上位机的波特率大于9600,那么通信就会失败,因为单片机来不及接收这么多的数据量。所以串口通信要求上下位机的波特率要一致,才能保证数据传送不出错。

往期回顾

f3bcdd5f312e3100a4af7bfd2d16beae.gif

C#做一个简单的进行串口通信的上位机

f3bcdd5f312e3100a4af7bfd2d16beae.gif

阿里云服务器 + WinServer 2012 搭建Git服务器

f3bcdd5f312e3100a4af7bfd2d16beae.gif

【完整视频】手把手教你搭建西门子PLC仿真环境

f3bcdd5f312e3100a4af7bfd2d16beae.gif

西门子S7通信协议底层原理及抓包分析

da9034e0e2325e1907708ec170bcf066.gif

点击下方“阅读原文”了解更多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值