AT89C51串口通讯教程.docx
- 文档编号:5549203
- 上传时间:2022-12-19
- 格式:DOCX
- 页数:28
- 大小:247.17KB
AT89C51串口通讯教程.docx
《AT89C51串口通讯教程.docx》由会员分享,可在线阅读,更多相关《AT89C51串口通讯教程.docx(28页珍藏版)》请在冰豆网上搜索。
AT89C51串口通讯教程
AT89C51串口通信编程
一、前言
本文档是为单片机初学者写的有关串口通讯编程的说明文档。
使用的单片机硬件是最通用的AT89C51单片机,编程语言为c语言。
本文档不是系统的介绍单片机知识的教程,而是为了使您尽快掌握串口编程方法的技术说明。
本文档前几部分大量内容摘自平凡老师的单片机教程,此教程是单片机入门的良好教材,但由于那本教程是由汇编语言描述的,对于时间不充足的同学来说,学习汇编会浪费一些时间,所以我还是整理了我们要了解的内容写到了本文档中。
对于时间比较充分,也有兴趣学习汇编语言的同学可以先阅读平凡老师的“单片机教程”,然后从本文档第六部分看起。
二、单片机的基本认识
一台能够工作的计算机要有这样几个部份构成:
CPU(进行运算、控制)、RAM(数据存储)、ROM(程序存储)、输入/输出设备(例如:
串行口、并行输出口等)。
在个人计算机上这些部份被分成若干块芯片,安装一个称之为主板的印刷线路板上。
而在单片机中,这些部份,全部被做到一块集成电路芯片中了,所以就称为单片(单芯片)机,而且有一些单片机中除了上述部份外,还集成了其它部份如A/D,D/A等。
天!
电脑中的CPU一块就要卖上千块钱,这么多东西做在一起,还不得买个天价!
再说这块芯片也得非常大了。
不,价格并不高,从几元人民币到几十元人民币,体积也不大,一般用40脚封装,当然功能多一些单片机也有引脚比较多的,如68引脚,功能少的只有10多个或20多个引脚,有的甚至只8只引脚。
为什么会这样呢?
功能有强弱,另外这种芯片的生产量很大,技术也很成熟,51系列的单片机已经做了十几年,所以价格就低了。
既然如此,单片机的功能肯定不强,干吗要学它呢?
话不能这样说,实际工作中并不是任何需要计算机的场合都要求计算机有很高的性能,一个控制电冰箱温度的计算机难道要用P4?
应用的关键是看是否够用,是否有很好的性能价格比。
实现一个发光二极管的闪烁体会对单片机的c语言编程
买回来一块c51单片机,要想使用它首先要做必要的连线。
我们实验室通常会给我们提供已经接好线的板子,所以我们不必自己去连线,这里需要说明的一点是,一块单片机要工作起来首先需要复位,所谓复位就是在单片机的RST引脚持续的加上两个机器周期的高电平,使单片机回到工作的状态。
(机器周期在串口波特率的计算中介绍)我做实验时使用的板子是一块较复杂的板子的一部分,那块板子的复位方式是其他器件的程序给单片机复位,可是我做实验时那个器件不需要工作,所以,单片机一直不能复位。
如果你遇到这种情况,请按任何一本书上介绍的加电复位选择合适的电容和电阻,按书上的连线图焊接好,如果你用的是我以前用过的板子,这块板子已经接好了复位电路,无须多考虑。
请打开一本单片机的书,找到单片机的引脚图。
我们用的板子在p1.0脚接有一个发光二极管,当p1.0为高电压时,二极管点亮,为低电压时,二极管熄灭。
我们现在想让小灯每隔0.5s闪烁一次,实际上就是要灯亮0.5s,再灭0.5s,也就是说要P10不断地输出高和低电平。
怎样实现这个要求呢?
我们首先给出程序,然后对照程序分析。
实验1//程序开始
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitP10=P1^0;//sbit是单片机c程序新的关键字,用于定义位变量
voidDelay(uinti)//延时程序,i是时间参数
{
uintj;
for(;i>0;i--)
for(j=0;j<125;j++)
{;}
}
voidmain()
{
for(;;)
{
P10=0;//单片机内部给p10脚加低电平,关闭小灯
Delay(500);//延时0.5s
P10=1;//单片机内部给p10脚加高电平,点亮小灯
Delay(500);//延时0.5S
}
}
在以上程序中,我们可以看出,p10=1这条语句的含义就是p10加高电压,这个高电压不是1v,而是5v。
p10=0则是p10加低电压。
为什么是p10=1是给p10加5v电压而不是1v,我们不用管。
现在从主函数看起,主函数内部是个for循环,此循环是让程序不停的在循环体内部转圈。
循环体中,首先让灯暗,然后调用延时函数delay,此函数的作用是延时0.5s,然后点亮小灯,然后又是延时,延时完了进入下一次的循环……这样,程序就每隔0.5s就给p10加一次电压,加的电压高低更替,并且永远循环下去。
其结果是让小灯不停的闪烁。
Delay函数纯粹是用软件的运行来消耗时间以达到延时的目的,至于为什么参数是500时,延时为0.5s,以后再谈。
写好了程序,下一步我们的任务是把程序烧写到单片机的存储器中去,但是单片机是不认识c语言的,所以需要我们预先编译成单片机认识的.hex格式文件,此步骤,用keilc软件。
然后将.hex文件用编程器写到单片机里,把单片机插回板子,加上电,就可以看到小灯在闪烁了。
Keilc和编程器的用法语言描述不太直观,如果您没有用过,建议您现场请教实验室其他同学。
三、几个基本概念
1、位的含义
通过上面的实验我们已经知道:
一盏灯亮或者说一根线的电平的高低,可以代表两种状态:
0和1。
实际上这就是一个二进制位,因此我们就把一根线称之为一“位”,用BIT表示。
上面程序中的语句sbitP10=P1^0中,sbit就是定义位变量的新的关键字。
2、字节的含义
一根线可以表于0和1,两根线可以表达00,01,10,11四种状态,也就是可以表于0到3,而三根可以表达0-7,计算机中通常用8根线放在一起,同时计数,就可以表过到0-255一共256种状态。
这8根线或者8位就称之为一个字节(BYTE)。
为什么一个字节是8位数而不是其它数,这只是人为地规定。
3、存储器简介
存储器就是用来存放数据的地方。
它是利用电平的高低来存放数据的,也就是说,它存放的实际上是电平的高、低,而不是我们所习惯认为的1234这样的数字。
存储器按功能可以分为只读和随机存取存储器两大类。
所谓只读,从字面上理解就是只可以从里面读,不能写进去,它类似于我们的书本,发到我们手回之后,我们只能读里面的内容,不可以随意更改书本上的内容。
只读存储器的英文缩写为ROM(READONLYMEMORY)我们只有用编程器对之进行编程。
所谓随机存取存储器,即随时可以改写,也可以读出里面的数据,它类似于我们的黑板,我可以随时写东西上去,也可以用黑板擦擦掉重写。
随机存储器的英文缩写为RAM(READRANDOMMEMORY)这两种存储器的英文缩写一定要记牢。
4、寄存器的认识
单片机中的寄存器多数是八位的,也就是每个寄存器可以放8个二进制数,每个二进制数就是一位了。
下面的文档中会直接用到几个单片机中的特殊寄存器,这些寄存器都有自己的名字,如TMOD,SCON,IP,PSW,ACC等,他们都有自己特定的功能,我想等到用到那一个在说哪一个,如果你不习惯可以去查单片机的书。
5、晶振频率、机器周期,指令周期
单片机是时序电路,必然会有产生时序脉冲的装置,这个任务交给了晶振。
本实验用的晶振是11.0592MH的,也就是每秒钟产生11.0592M个脉冲。
单片机的机器周期是晶振振动周期的十二倍,也就是十二分频。
一个机器周期也就是12/11.0592us大概是1us。
指令周期是一条指令的执行时间,单片机中的指令周期按指令不同有单周期,双周期,和四周期指令等,这些一般不用记,用到了查单片机公司给的手册就可以了。
四、记数器与定时器介绍
鉴于初进实验室的同学可能尚未接触数字电路中计数器的概念,1-5条对记述和定时作详细介绍,如已学习过数字电路,可快速浏览以下1-5条。
1、计数概念的引入
从选票的统计谈起:
画“正”。
这就是计数,生活中计数的例子处处可见。
例:
录音机上的计数器、家里面用的电度表、汽车上的里程表等等,再举一个工业生产中的例子,线缆行业在电线生产出来之后要计米,也就是测量长度,怎么测法呢?
用尺量?
不现实,太长不说,要一边做一边量呢,怎么办呢?
行业中有很巧妙的方法,用一个周长是1米的轮子,将电缆绕在上面一周,由线带轮转,这样轮转一周不就是线长1米嘛,所以只要记下轮转了多少圈,就可以知道走过的线有多长了。
2、计数器的容量
从一个生活中的例子看起:
一个水盆在水龙头下,水龙没关紧,水一滴滴地滴入盆中。
水滴不断落下,盆的容量是有限的,过一段时间之后,水就会逐渐变满。
录音机上的计数器最多只计到999….那么单片机中的计数器有多大的容量呢?
89c51单片机中有两个计数器,分别称之为T0和T1,这两个计数器分别是由两个8位的RAM单元组成的,即每个计数器都是16位的计数器,最大的计数量是65536。
3、定时
89c51中的计数器除了可以作为计数之用外,还可以用作时钟,时钟的用途当然很大,如打铃器,电视机定时关机,空调定时开关等等,那么计数器是如何作为定时器来用的呢?
一个闹钟,我将它定时在1个小时后闹响,换言之,也可以说是秒针走了(3600)次,所以时间就转化为秒针走的次数的,也就是计数的次数了,可见,计数的次数和时间之间的确十分相关。
那么它们的关系是什么呢?
那就是秒针每一次走动的时间正好是1秒。
结论:
只要计数脉冲的间隔相等,则计数值就代表了时间的流逝。
由此,单片机中的定时器和计数器是一个东西,只不过计数器是记录的外界发生的事情,而定时器则是由单片机提供一个非常稳定的计数源。
提供给定时器的计数源是由单片机的晶振经过12分频后获得的一个脉冲源(12分频是指晶振频率的12分之一)。
晶振的频率当然很准,所以这个计数脉冲的时间间隔也很准。
例如,一个12M的晶振,它提供给计数器的脉冲时间间隔是12M/12等于1M,也就是记数周期为1个微秒。
结论:
计数脉冲的间隔与晶振有关,12M的晶振,计数脉冲的间隔是1微秒。
4、溢出
让我们再来看水滴的例子,当水不断落下,盆中的水不断变满,最终有一滴水使得盆中的水满了。
这时如果再有一滴水落下,就会发生什么现象?
水会漫出来,用个术语来讲就是“溢出”。
水溢出是流到地上,而计数器溢出后将使得TF0变为“1”。
至于TF0是什么我们稍后再谈。
一旦TF0由0变成1,就是产生了变化,产生了变化就会引发事件,就象定时的时间一到,闹钟就会响一样。
至于会引发什么事件,我们下次再介绍,现在我们来研究另一个问题:
要有多少个计数脉冲才会使TF0由0变为1。
5、任意定时及计数的方法
刚才已研究过,计数器的容量是16位,也就是最大的计数值到65536,因此计数计到65536就会产生溢出。
这个没有问题,问题是我们现实生活中,经常会有少于65536个计数值的要求,如包装线上,一打为100瓶,一瓶药片为100粒,怎么样来满足这个要求呢?
我们采用预置数的方法,我要计100,那我就先放进65436,再来100个脉冲,不就到了65536了吗。
定时也是如此,每个脉冲是1微秒,则计满65536个脉冲需时65.536毫秒,但现在我只要10毫秒就可以了,怎么办?
10个毫秒为10000个微秒,所以,只要在计数器里面放进55536就可以了。
6、计数/定时器的方式控制字
我们上面说过,c51中有两个计数/定时器T1和T0;每个计数器都有两个八位寄存器,即是十六位的寄存器。
TH1、TL1分别是计数器T1的高八位和低八位存储区,TH0、TL0分别是计数器0的高八位和低八位存储区。
在单片机中有两个特殊功能寄存器与定时/计数有关,这就是TMOD和TCON。
TMOD和TCON是寄存器的名称,我们在写程序时就可以直接用这个名称来指定它们。
GATE
C/T
M1
M0
GATE
C/T
M1
M0
图1寄存器TMOD示意图
SM0
SM1
SM2
REN
TB8
RB8
TI
RI
图2串行口控制寄存器SCON:
示意图
从图1中我们可以看出,TMOD被分成两部份,每部份4位。
分别用于控制T1,T0,(前四位控制T1,后四位控制T0)至于这里面是什么意思,我们下面介绍。
可以看出,TCON也被分成两部份,高4位用于定时/计数器,低4位则用于中断(我们暂不管)。
而TF1(0)我们上节课已提到了,当计数溢出后TF1(0)就由0变为1。
原来TF1(0)在这儿!
TR0、TR1分别是控制T0和T1工作状态的位。
我们用图1来讨论以下问题:
1、M1M0:
定时/计数器一共有四种工作方式,就是用M1M0来控制的,2位正好是四种组合(00方式1,01方式1,10方式2,11方式3)。
2、C/T:
前面我们说过,定时/计数器即可作定时用也可用计数用,到底作什
用,由我们根据需要自行决定,也说是决定权在我们编程者。
如果C/T为0就是用作定时器,如果C/T为1就是用作计数器。
3、GATE:
门控信号
GATE=1时,定时器/计数器的启动受到双重控制,即要求TR0/TR1和INT0/INT1同时为高电平时,定时器/计数器才可工作。
GATE=0时,T/C的启动仅受TR0或TR1控制。
看到这里,我们先不管四种工作方式是什么意思,我们举例讨论两个计数/定时器和工作方式的选择。
例如,如果我们要使T1工作在方式2,那么只需要给M1M0赋值10(见上面第一点),我们还想只用TR1控制T1,那么给GATE赋0即可(见以上第三点),如果我们把T1用做一个定时器,则给C/T赋0就可以了(见以上第二点条)。
T0部分我们先不使用,全部赋值0。
给这么好几个东西赋值,其实只需要一条c语言语句。
对照着表一,我们只需要把二进制数00100000赋给寄存器TMOD,即可实现以上全部的赋值。
而二进制数00100000就是十六进制数0x20(0x为十六进制数的标志)。
所用的赋值语句为:
TMOD=0x20;。
简单吧?
现在,只需要一条语句TR1=1;就可以启动定时器1,使其工作起来了。
下面我们来介绍定时/计数器的四种工作方式。
1、方式0(M1M0=00)
定时器/计数器的工作方式0称之为13位定时/计数方式。
它由TL(1/0)的低5位和TH(0/1)的8位构成13位的计数器,此时TL(1/0)的高3位未用。
2、方式1(M1M0=01)
工作方式1是16位的定时/计数方式,将M1M0设为01即可,其它特性与工作方式0相同。
满计数值是2的16次方。
3、工作方式2(M1M0=10)
在介绍这种式方式之前先让我们思考一个问题:
上一次课我们提到过任意计数及任意定时的问题,比如我要计1000个数,可是16位的计数器要计到65536才满,怎么办呢?
我们讨论后得出的办法是用预置数,先在计数器里放上64536,再来1000个脉冲,不就行了吗?
是的,但是计满了之后我们又该怎么办呢?
要知道,计数总是不断重复的,流水线上计满后马上又要开始下一次计数,下一次的计数还是1000吗?
当计满并溢出后,计数器里面的值变成了0(为什么,可以参考前面课程的说明),因此下一次将要计满65536后才会溢出,这可不符合要求,怎么办?
当然办法很简单,就是每次一溢出时执行一段程序可以在这段程序中做把预置数64536送入计数器中的事情。
所以采用工作方式0或1都要在溢出后做一个重置预置数的工作,做工作当然就得要时间,软件也要费一些事情,为了省时省力,有了此种方式:
自动再装入预置数的工作方式。
既然要自动得新装入预置数,那么预置数就得放在一个地方,要不然装什么呢?
那么预置数放在什么地方呢?
它放在T(0/1)的高8位,这样高8位不就不参与计数了。
在工作方式2中,只有低8位参与计数,而高8位不参与计数,用作预置数的存放,这样计数范围就小多了,当然做任可事总有代价的,关键是看值不值,如果我根本不需要计那么多数,那么就可以用这种方式。
每当计数溢出,高八位中的预置的数值自动进入低8位。
这是由硬件自动完成的,不需要由人工干预。
通常这种式作方式用于波特率发生器,也是本文档程序中用的最多的一种方式。
用于这种用途时,定时器就是为了提供一个时间基准。
计数溢出后不需要做事情,要做的仅仅只有一件,就是重新装入预置数,再开始计数,而且中间不要任何延迟,可见这个任务用工作方式2来完成是最妙不过了。
定时器/计数器的定时/计数范围
工作方式0:
13位定时/计数方式,因此,最多可以计到2的13次方,也就是8192次。
工作方式1:
16位定时/计数方式,因此,最多可以计到2的16次方,也就是65536次。
工作方式2和工作方式3,都是8位的定时/计数方式,因此,最多可以计到2的8次方,也说是256次。
预置值计算:
用最大计数量减去需要的计数次数即可。
例:
流水线上一个包装是12盒,要求每到12盒就产生一个动作,用单片机的工作方式0来控制,应当预置多大的值呢?
对了,就是8192-12=8180。
以上是计数,明白了这个道理,定时也是一样。
这在前面的课程已提到,我们不再重复,请参考前面的例子。
下面我们用定时器1实现小灯的闪烁,来放松一下。
如果想要小灯每隔0.5s闪烁一次,如前面所述,也就是让P10每隔0.5s改变一次电平的高低。
前面的实验是纯粹用软件来消磨时间,这次我们用定时器1来预定时间控制P10的电平。
定时器的方式2是自动装入预置数的八位定时器,最大定时间隔是计满2的8次方也就是计满256个数就要溢出并开始下一次定时。
前面提到,11.059M的晶振提供的计数周期是0.92us,那么最大的定时间隔是256*0.92us=235.52us,显然,如果这样短的时间小灯就闪烁一次的话,那么人眼是分辨不出来的。
怎样获得更大的时间间隔呢?
可以采用软件计数的办法,也就是说,预先设置一个变量,每当一个定时周期到了,不急于给p10赋值,而是先给变量加一,当这个变量达到某一个数值时,就给p10电平取反.比如在以下程序中,我们准备让小灯每隔0.5s闪烁一次,则0.5*1000000/235.52=2123,也就是说,如果预先设置变量的值从零变到2123,这时候就标志着0.5s的时间间隔到了,就可以给p10赋值了。
在执行中,每次定时器定时时间到了总要执行几条语句,执行这些语句也需要一定时间,当然,相对于256个计数周期这些时间是不长的,为了明确概念初学者可以先不仔细算。
本程序中我们取软件计数到2000时电平变化,以补偿代码执行的时间。
说了这么多,如果你已经不知道我再说什么了,那请看完以下程序在看上面这段话。
实验二
#include
#defineuintunsignedint
sbitP10=P1^0;//定义P1^0为位变量P10
voidmain(void)
{
uintk=0;//定义用于软件计数的变量k并赋初值
TMOD=0x20;//使用定时器1的方式2
TR1=1;//启动定时器1
P10=0;//给P10赋初值,关闭小灯
TH1=0X00;TL1=0X00;//装载计数初值
while
(1)//不停的循环
{
while(!
TF1);//检查是否定时器溢出,如溢出则向下执行
TF1=0;//溢出标志位清0
while(++k==2000)//当定时器1溢出2000次时进入循环体
{
P10=!
P10;//使P10电位反向,控制小灯明暗
k=0;//软件计数标志清零,准备下一次计数
}
}
}
由以上的程序我们可以看出使用计数/定时器的一般步骤为:
1、确定T/C的工作方式――编程TMOD寄存器
2、计算T/C中的计数初值,并装载到TH和TL
3、T/C在中断方式工作时,须开CPU中断源――编程IE寄存器(下节讲)
4、启动定时/计数器――编程TCON中的TR1和TR0位。
上面第三条中提到中断,休息一会,我们来看单片机中另一个重要的内部资源――中断。
五、中断介绍
1、有关中断的概念
什么是中断,我们从一个生活中的例子引入。
你正在家中看书,突然电话铃响了,你放下书本,去接电话,和来电话的人交谈,然后放下电话,回来继续看你的书。
这就是生活中的“中断”的现象,就是正常的工作过程被外部的事件打断了。
仔细研究一下生活中的中断,对于我们学习单片机的中断也很有好处。
第一、什么可经引起中断,生活中很多事件可以引起中断:
有人按了门铃了,电话铃响了,你的闹钟闹响了,你烧的水开了….等等诸如此类的事件,我们把可以引起中断的称之为中断源,单片机中也有一些可以引起中断的事件,89c51中一共有5个:
两个外部中断,两个计数/定时器中断,一个串行口中断。
第二、中断的嵌套与优先级处理:
设想一下,我们正在看书,电话铃响了,同时又有人按了门铃,你该先做那样呢?
如果你正是在等一个很重要的电话,你一般不会去理会门铃的,而反之,你正在等一个重要的客人,则可能就不会去理会电话了。
如果不是这两者(即不等电话,也不是等人上门),你可能会按你通常的习惯去处理。
总之这里存在一个优先级的问题,单片机中也是如此,也有优先级的问题。
优先级的问题不仅仅发生在两个中断同时产生的情况,也发生在一个中断已产生,又有一个中断产生的情况,比如你正接电话,有人按门铃的情况,或你正开门与人交谈,又有电话响了情况。
考虑一下我们会怎么办吧。
第三、中断的响应过程:
当有事件产生,进入中断之前我们必须先记住现在看书的第几页了,或拿一个书签放在当前页的位置,然后去处理不同的事情(因为处理完了,我们还要回来继续看书):
电话铃响我们要到放电话的地方去,门铃响我们要到门那边去,也说是不同的中断,我们要在不同的地点处理,而这个地点通常还是固定的。
计算机中也是采用的这种方法,五个中断源,每个中断产生后都到一个固定的地方去找处理这个中断的程序,当然在去之前首先要保存下面将执行的指令的地址,以便处理完中断后回到原来的地方继续往下执行程序。
具体地说,中断响应可以分为以下几个步骤:
1、保护断点,即保存下一将要执行的指令的地址,就是把这个地址送入堆栈。
2、寻找中断入口,根据5个不同的中断源所产生的中断,查找5个不同的入口地址。
以上工作是由计算机自动完成的,与编程者无关。
在这5个入口地址处存放有中断处理程序(这是程序编写时放在那儿的,如果没把中断程序放在那儿,就错了,中断程序就不能被执行到)。
3、执行中断处理程序。
4、中断返回:
执行完中断指令后,就从中断处返回到主程序,继续执行。
MCS-51中断系统的结构:
如图(抱歉,本图请找本51书看一下)所示,由与中断有关的特殊功能寄存器、中断入口、顺序查询逻辑电路等组成,包括5个中断请求源,4个用于中断控制的寄存器IE、IP、ECON和SCON来控制中断。
1、中断请求源:
(1)外部中断请求源:
即外中断0和1,经由外部引脚引入的,在单片机上有两个引脚,名称为INT0、INT1,也就是P3.2、P3.3这两个引脚。
在内部的TCON中有四位是与外中断有关的。
IT0:
INT0触发方式控制位,可由软件进和置位和复位,IT0=0,INT0为低电平触发方式,IT0=1,INT0为负跳变触发方式。
这两种方式的差异可暂不考虑。
IE0:
INT0中断请求标志位。
当有外部的中断请求时,这位就会置1(这由硬件来完成),在CPU响应中断后,由硬件将IE0清0。
IT1、IE1的用途和IT0、IE0相同。
(2)内部中断请求源
TF0:
定时器T0的溢出中断标记,当T0计数产生溢出时,由硬件置位TF0。
当CPU响应中断后,再由软件将TF0清0。
TF1:
与TF0类似。
TI、RI:
串行口发送、接收中断,在串口中再仔细讲解。
2、中断允许寄存器IE
在MCS-51中断系统中,中断的允许或禁止是由片内可进行位寻址的8位中断允许寄存器IE来控制的。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AT89C51 串口 通讯 教程