首页 单片机串口通信

单片机串口通信

举报
开通vip

单片机串口通信AT89C51串口编程 AT89C51串口编程 前言 本文档是为单片机初学者写的有关串口通讯编程的说明文档。使用的单片机硬件是最通用的AT89C51单片机,编程语言为c语言。本文档不是系统的介绍单片机知识的教程,而是为了使您尽快掌握串口编程方法的技术说明。 本文档前几部分大量内容摘自平凡老师的单片机教程,此教程是单片机入门的良好教材,但由于那本教程是由汇编语言描述的,对于时间不充足的同学来说,学习汇编会浪费一些时间,所以我还是整理了我们要了解的内容写到了本文档中。对于时间比较充分,也有兴趣学习汇编语言的同学可以先阅...

单片机串口通信
AT89C51串口编程 AT89C51串口编程 前言 本文档是为单片机初学者写的有关串口通讯编程的说明文档。使用的单片机硬件是最通用的AT89C51单片机,编程语言为c语言。本文档不是系统的介绍单片机知识的 教程 人力资源管理pdf成真迷上我教程下载西门子数控教程protel99se入门教程fi6130z安装使用教程 ,而是为了使您尽快掌握串口编程 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 的技术说明。 本文档前几部分大量内容摘自平凡老师的单片机教程,此教程是单片机入门的良好教材,但由于那本教程是由汇编语言描述的,对于时间不充足的同学来说,学习汇编会浪费一些时间,所以我还是整理了我们要了解的内容写到了本文档中。对于时间比较充分,也有兴趣学习汇编语言的同学可以先阅读平凡老师的“单片机教程”,然后从本文档第六部分看起。该教程网址:http://www.21icsearch.com/pmcu/dpjjx/ndpjjx2.htm 我也已经下载了此教程,存在本实验室电脑中。 单片机的基本认识 一台能够工作的计算机要有这样几个部份构成: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//c51单片机编程特有的头文件 #define uint unsigned int #define uchar unsigned char sbit P10=P1^0; //sbit是单片机c程序新的关键字,用于定义位变量 void Delay(uint i)//延时程序,i是时间参数 { uint j; for(;i>0;i--) for(j=0;j<125;j++) {;} } void main() { 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格式文件,此步骤,用keil c软件。然后将.hex文件用编程器写到单片机里,把单片机插回板子,加上电,就可以看到小灯在闪烁了。Keil c和编程器的用法语言描述不太直观,如果您没有用过, 建议 关于小区增设电动车充电建议给教师的建议PDF智慧城市建议书pdf给教师的36条建议下载税则修订调整建议表下载 您现场请教实验室其他同学。 三、几个基本概念 1、位的含义 通过上面的实验我们已经知道:一盏灯亮或者说一根线的电平的高低,可以代表两种状态:0和1。实际上这就是一个二进制位,因此我们就把一根线称之为一“位”,用BIT表示。上面程序中的语句sbit P10=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(READ ONLY MEMORY)我们只有用编程器对之进行编程。 所谓随机存取存储器,即随时可以改写,也可以读出里面的数据,它类似于我们的黑板,我可以随时写东西上去,也可以用黑板擦擦掉重写。随机存储器的英文缩写为RAM(READ RANDOM MEMORY)这两种存储器的英文缩写一定要记牢。 4、寄存器的认识 单片机中的寄存器多数是八位的,也就是每个寄存器可以放8个二进制数,每个二进制数就是一位了。下面的文档中会直接用到几个单片机中的特殊寄存器,这些寄存器都有自己的名字,如TMOD,SCON,IP,PSW,ACC等,他们都有自己特定的功能,我想等到用到那一个在说哪一个,如果你不习惯可以去查单片机的书。 5、晶振频率、机器周期,指令周期 单片机是时序电路,必然会有产生时序脉冲的装置,这个任务交给了晶振。本实验用的晶振是11.0592MH的,也就是每秒钟产生11.0592M个脉冲。单片机的机器周期是晶振振动周期的十二倍,也就是十二分频。一个机器周期也就是12/11.0592us大概是1us。指令周期是一条指令的执行时间,单片机中的指令周期按指令不同有单周期,双周期,和四周期指令等,这些一般不用记,用到了查单片机公司给的手册就可以了。 4、​ 记数器与定时器介绍 鉴于初进实验室的同学可能尚未接触数字电路中计数器的概念,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//头文件 #define uint unsigned int sbit P10=P1^0;//定义P1^0为位变量P10 void main(void) { uint k=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来控制的。见下表 EA ES ET1 EX1 ET0 EX0 中断允许寄存器IE示意表 其中EA是总开关,如果它等于0,则所有中断都不允许。 ES-串行口中断允许 : ES=1,串口允许中断;ES=0,串口不允许中断。 ET1-定时器1中断允许 (以下的含义和ES的解释相同) EX1-外中断1中断允许。 ET0-定时器0中断允许 EX0-外中断0中断允许。 如果我们要设置允许外中断1,定时器1中断允许,其它不允许,则IE可以是 EA ES ET1 EX1 ET0 EX0 1 0 0 0 1 1 0 0 用c语句 IE=0x8c;即可完成上述对IE的编程。当然也可以分别对每一位编程:EA=1; ET1=1;EX1=1; 3、五个中断源的自然优先级 外中断0>定时器0>外中断1>定时器1>串口 优先级:单片机采用了自然优先级和人工设置高、低优先级的策略,即可以由程序员设定那些中断是高优先级、哪些中断是低优先级,由于只有两级,必有一些中断处于同一级别,处于同一级别的,就由自然优先级确定。 开机时,每个中断都处于低优先级,我们可以用指令对优先级进行设置。看下表。 PS PT1 PX1 PT0 PX0 中断优先级寄存器IP示意表 中断优先级中由中断优先级寄存器IP来设置的,IP中某位设为1,相应的中断就是高优先级,否则就是低优先级。 例:设有如下要求,将T0、外中断1设为高优先级,其它为低优先级,求IP的值。 IP的首3位没用,可任意取值,设为000,后面根据要求写就可以了 PS PT1 PX1 PT0 PX0 0 0 0 0 0 1 1 0 因此,最终,IP的值就是十六进制数0x06。. 本串口通讯实验中,因为只用到了串口中断,所以没必要设优先级寄存器IP,本段内容可以只作一般了解。 4、MCS-51的中断响应过程: 1、中断响应的条件:讲到这儿,我们依然对于计算机响应中断感到神奇,我们人可以响应外界的事件,是因为我们有多种“传感器“――眼、耳可以接受不同的信息,计算机是如何做到这点的呢?其实说穿了,一点都不希奇,MCS51工作时,在每个机器周期中都会去查询一下各个中断标记,看他们是否是“1“,如果是1,就说明有中断请求了,所以所谓中断,其实也是查询,不过是每个周期都查一下而已。这要换成人来说,就相当于你在看书的时候,每一秒钟都会抬起头来看一看,查问一下,是不是有人按门铃,是否有电话。。。。很蠢,不是吗?可计算机本来就是这样,它根本没人聪明。 了解了上述中断的过程,就不难解中断响应的条件了。在下列三种情况之一时,CPU将封锁对中断的响应: A、CPU正在处理一个同级或更高级别的中断请求。 B、现行的机器周期不是当前正执行指令的最后一个周期。我们知道,单片机有单周期、双周期、三周期指令,当前执行指令是单字节没有关系,如果是双字节或四字节的,就要等整条指令都执行完了,才能响应中断(因为中断查询是在每个机器周期都可能查到的)。 C、正在执行的指令是返回批令(RETI)或访问IP、IE寄存器的指令,则CPU至少再执行一条指令才应中断。这些都是与中断有关的,如果正访问IP、IE则可能会开、关中断或改变中断的优先级,而中断返回指令则说明本次中断还没有处理完,所以都要等本指令处理结束,再执行一条指令才可以响应中断。 后两条理解不太直观,没关系,最重要的是第一条。 2、中断响应过程 用c语言编程时,我们不用中断具体怎样响应,我们只要在程序中预先设置好了有关中断的寄存器,那么一但出现了中断请求,单片机硬件会自动跳出主函数去执行中断函数。中断函数的格式为: 返回值 函数名 interrupt n n对硬中断源的编号。比如,我们要设置一个串口的中断程序: void chuankou(void) interrupt 4 {。。。。。。 } 注意,当程序中有两个以上中断源时,要涉及到寄存器组切换的问题,此时中断函数要写成void chuankou(void) interrupt 4 using 1 {。。。。。。 } 由于本串口通讯实验只用一个中断源,所以用不到寄存器组的切换,故不再讲述。你可以在做完实验以后查阅单片机c语言的书籍。同样,讲述完了中断,我们用中断来做个程序,程序的功能仍然是使小灯每隔0.5s闪烁一次,只不过这次用中断来做。我们用定时器1的中断来做,由于前面提到的原因,定时间隔太小小灯闪烁不明显,要用到“软件计数器”,本例中同样要遇到这种情况。请看程序: 实验三 #include//头文件 #define uint unsigned int uint i =0 ; sbit P10=P1^0;// 定义P1^0为位变量P10 void timer1(void) interrupt 3//用定时器1的中断,此中断的编号是3 { TF1=0;//清除定时器1的中断标志 While(++i==1800)//当中断1800(每隔0.5s左右)次时进入循环体 { P10=!P10;//P10电平取反,控制小灯闪烁 i=0;//软件计数标志清零 } } void main (void) { TMOD=0x20;//设置定时器1的工作方式2 TH1=ox00;TL1=0x00;//预置计数初值 IE=0x88;//打开定时器1的中断,开总中断 TR1=1;//定时器1开始工作 While(1)//无限循环,实际工作中此处可加其他功能的代码(注1) {; } } 这是用中断来实现的对小灯闪烁的控制,没有中断发生时,程序一直在主函数的空循环里空转圈,当定时器1溢出,TF1置一时(由硬件完成),硬件自动向cpu提出中断的请求,cpu自动的跳出主函数去执行中断函数中的代码,执行完中断以后又回到主函数。请注意,此处的中断函数和一般的子函数不同,一般的子函数须要主函数来调用,而中断函数是一但有中断发生,硬件自动执行中断中的代码,这个过程是硬件自动实现的,无须人工调用。 以上这个程序和前面的程序所不同的是,程序不只是可以控制小灯,还可以在注1出的while空循环处加入具有其他功能的代码。 到现在,串口通讯的前期准备工作基本完成,你可以有很多地方不理解,没关系,只要你感觉对单片机的c编程有了一个基本的认识,基本上掌握了大致的思路,那么,请接着看下一部分:串口通讯概念和基本实验。如果你感觉还是对单片机很模糊,建议你直接去看平凡老师的教程和北航的“单片机的c语言程序设计”教程。(教研室有这本书) 串口通讯概念和基本实验 1、串行接口的一般概念 单片机与外界进行信息交换称之为通讯。 89c51单片机的通讯方式有两种: A、并行通讯:数据的各位同时发送或接收。本文档不涉及并行通讯,只将串行通讯。 B、串行通讯:数据一位一位顺序发送或接收。 串行通讯的方式: 异步通讯:它用一个起始位表示字符的开始,用停止位表示字符的结束。其每帧的格式如下: 在一帧格式中,先是一个起始位0,然后是8个数据位,规定低位在前,高位在后,接下来是奇偶校验位(可以省略),最后是停止位1。用这种格式表示字符,则字符可以一个接一个地传送。 在异步通讯中,CPU与外设之间必须有两项规定,即字符格式和波特率。字符格式的规定是双方能够在对同一种0和1的串理解成同一种意义。原则上字符格式可以由通讯的双方自由制定,但从通用、方便的角度出发,一般还是使用一些标准为好,如采用ASCII标准。 波特率即数据传送的速率,其定义是每秒钟传送的二进制数的位数。例如,数据传送的速率是12 0字 个人自传范文3000字为中华之崛起而读书的故事100字新时代好少年事迹1500字绑架的故事5000字个人自传范文2000字 符/s,而每个字符如上述规定包含10数位,则传送波特率为1200波特。 同步通讯:在同步通讯中,每个字符要用起始位和停止位作为字符开始和结束的标志,占用了时间;所以在数据块传递时,为了提高速度,常去掉这些标志,采用同步传送。由于数据块传递开始要用同步字符来指示,同时要求由时钟来实现发送端与接收端之间的同步,故硬件较复杂。本文档不讨论同步通讯。 2.89c51单片机的串行接口结构 89c51单片机通过引脚RXD(P3.0,串行数据接收端)和引脚TXD(P3.1,串行数据发送端)与外界通讯。SBUF是串行口缓冲寄存器,包括发送寄存器和接收寄存器。它们有相同名字和地址空间,但不会出现冲突,因为它们两个一个只能被CPU读出数据,一个只能被CPU写入数据。所以,语句SBUF=SBUF;是有意义的。它并不是将本身的值赋给了本身,而是将一个寄存器的值赋给了另一个寄存器,并且单片机不会搞错哪个是发送的,哪个是接受的。 3、串行口的控制与状态寄存器 ​ 串行口控制寄存器SCON 它用于定义串行口的工作方式及实施接收和发送控制。其各位定义如下表: SM0 SM1 SM2 REN TB8 RB8 TI RI 串口控制寄存器SCON示意表 各位的说明如下 SM0.SM1:工作方式控制位(其中fosc为晶振频率) SM0 SM1 工作方式 说 明 波特率 0 0 0 同步移位寄存器 Fosc/12 0 1 1 10位异歩收发 由定时器控制 1 0 2 11位异步收发 Fosc/32或Fosc/64 1 1 3 11位异步收发 由定时器控制 注意,由于实验条件本文档只有方式1和方式3的例程。 SM2:多机通讯控制位。本文档不使用,编程时置0即可。 REN:接收允许控制位。由软件置位以允许接收,又由软件清0来禁止接收。 TB8: 是要发送数据的第9位。在方式2或方式3中,要发送的第9位数据,根据需要由软件置1或清0。例如,可约定作为奇偶校验位,或在多机通讯中作为区别地址帧或数据帧的标志位。 RB8:接收到的数据的第9位。在方式0中不使用RB8。在方式1中,若(SM2)=0,RB8为接收到的停止位。在方式2或方式3中,RB8为接收到的第9位数据。 TI: 发送中断标志。在方式0中,第8位发送结束时,由硬件置位。在其它方式的发送停止位前,由硬件置位。TI置位既表示一帧信息发送结束,同时也是申请中断,可根据需要,用软件查询的方法获得数据已发送完毕的信息,或用中断的方式来发送下一个数据。TI必须用软件清0。 RI: 接收中断标志位。在方式0,当接收完第8位数据后,由硬件置位。在其它方式中,在接收到停止位的中间时刻由硬件置位(例外情况见于SM2的说明)。RI置位表示一帧数据接收完毕,可用查询的方法获知或者用中断的方法获知。RI也必须用软件清0。 ​ 电源控制寄存器PCON: SMOD 此寄存器只有第一位SMOD和本文档有关。 SMOD:串行口波特率加倍位 1――方式1,3波特率=定时器1溢出率/16;方式2波特率为Fosc/32。 0――方式1,3波特率=定时器1溢出率/32;方式2波特率为Fosc/64 8051单片机的全双工串行口可编程为4种工作方式,现分述如下: 方式0为移位寄存器输入/输出方式。本文档不用,故不叙述,有兴趣的话可以看教程。 方式1为波特率可变的10位异步通讯接口方式。发送或接收一帧信息,包括1个起始位0,8个数据位和1个停止位1。 输出: 当CPU执行一条指令将数据写入发送缓冲SBUF时,就启动发送。串行数据从TXD引脚输出,发送完一帧数据后,就由硬件置位TI。 输入: 在(REN)=1时,串行口采样RXD引脚,当采样到1至0的跳变时,确认是开始位0,就开始接收一帧数据。只有当(RI)=0且停止位为1或者(SM2)=0时,停止位才进入RB8,8位数据才能进入接收寄存器,并由硬件置位中断标志RI;否则信息丢失。所以在方式1接收时,应先用软件清零RI和SM2标志。 方式2 方式2为固定波特率的11位异步通讯接口方式。它比方式1增加了一位可程控为1或0的第9位数据。输出: 发送的串行数据由TXD端输出一帧信息为11位,附加的第9位来自SCON寄存器的TB8位,用软件置位或复位。它可作为多机通讯中地址/数据信息的标志位,也可以作为数据的奇偶校验位。当CPU执行一条数据写入SUBF的指令时,就启动发送器发送。发送一帧信息后,置位中断标志TI。 输入: 在(REN)=1时,串行口采样RXD引脚,当采样到1至0的跳变时,确认是开始位0,就开始接收一帧数据。在接收到附加的第9位数据后,当(RI)=0或者(SM2)=0时,第9位数据才进入RB8,8位数据才能进入接收寄存器,并由硬件置位中断标志RI;否则信息丢失。且不置位RI。再过一位时间后,不管上述条件时否满足,接收电路即行复位,并重新检测RXD上从1到0的跳变。工作方式3 方式3为波特率可变的11位异步通讯接口方式。除波特率外,其余与方式2相同。 4、波特率的选择 如前所述,在串行通讯中,收发双方的数据传送率(波特率)要有一定的约定。在89C51串行口的四种工作方式中,方式0和2的波特率是固定的,而方式1和3的波特率是可变的,由定时器T1的溢出率控制。以下讨论中,FOSC是晶振的频率。 A、方式0 方式0的波特率固定为晶振频率的1/12。 B、方式2 方式2的波特率由PCON中的选择位SMOD来决定,可由下式表示: 波特率=2的SMOD次方除以64再乘一个fosc,也就是当SMOD=1时,波特率为1/32fosc,当SMOD=0时,波特率为1/64fosc C、方式1和方式3 定时器T1作为波特率发生器,其公式如下: 波特率=定时器T1溢出率乘2的SMOD次方除以32 波特率=(2^SMOD)*(定时器1的溢出率)/32 T1溢出率= T1计数率/产生溢出所需的周期数 式中T1计数率的含义是:一秒钟计数的次数。它取决于它工作在定时器状态还是计数器状态。当工作于定时器状态时,T1计数率为fosc/12(即一个机器周期);当工作于计数器状态时,T1计数率为外部输入频率,此频率应小于fosc/24。产生溢出所需周期与定时器T1的工作方式、T1的预置值有关。 定时器T1工作于方式0:溢出所需周期数=8192-x (X为预置数) 定时器T1工作于方式1:溢出所需周期数=65536-x 定时器T1工作于方式2:溢出所需周期数=256-x 因为方式2为自动重装入初值的8位定时器/计数器模式,所以用它来做波特率发生器最恰当。 当时钟频率选用11.0592MHZ时,容易获得标准的波特率,所以很多单片机系统选用这个频率的晶振。 好了,先面我们给出串口初始化的过程,前面讲的几个寄存器会在下面用到。 串口初始化的歩骤: a) 确定定时器1的工作方式――编程TMOD寄存器; b) 计算定时器1的初值――装载TH1,TL1; c) 启动定时器1――编程TCON中的TR1位; d) 确定串行口的工作方式――编程SCON; e)​ 串行口在中断方式工作时,须开CPU和源中断――编程IE寄存器。 为了说明以上的基本过程,请看串口通讯的第一个实验。本实验的目的很简单,就是从pc机向单片机发送数据,然后单片机紧接着把pc发送的数据送回pc在显示器上显示出来。我们目前所要做的工作只是给单片机编程,让单片机能够接收到pc发送的数据,并且接收到pc发送的数据以后在送给pc,至于pc怎样发送,接受,由串口调试助手来完成。串口调试助手要陪伴我们整个实验过程,让我们先认识一下吧. 从上图我们可以看见,左上角第一个设置是串口的选择,计算机上有两个串口,我也分不清那个是COM1那个是COM2,你可以试一下。波特率的设置必须和你已经写到单片机里的程序设置的波特率一致!校验位也要和单片机程序一至,数据位是八位,停止位是一位。一切设置好后,在助手的下面的文本区填入要发送的数据,点击发送后如果上面的大文本框内能够正确的显示出来的话,实验就成功了。以后我们描述调试助手的设置用下面的格式: (波特率,校验位,数据位,停止位) 比如上图的设置描述为(9600,n,8,1)其中,n为无校验。 下面请看程序: 实验四 #include //头文件 void main(void) //主程序(判断单片机串口是否正常工作) { unsigned char a; TMOD=0x20; // 采用定时器1的工作方式2 TL1=0xfd; //计算定时器1的初值,装载TL1,TH1 TH1=0Xfd; //波特率(9600)=(2^SMOD)*(定时器1的溢出率)/32 //溢出速率=(计数速率)/ [256-(TH1)] //计数速率与TMOD寄存器中C/T(TMOD.6)的状态有关。当C/T=0时,//计数速率为Fosc/12,当C/T=1时计数速率取决与外部输入时钟频率,//但此频率不能超过Fosc/24。 SCON=0X50; //允许串口接受数据,工作方式为1,无奇偶校验位。 PCON=0x00; //串口波特率不加倍。 TR1=1; //启动定时器1计数,TR1是TCON.6 while(1) { while(RI==0) //判断串口缓冲区是否接受完数据(RI==1表示接受完) {; } //接受完了跳出循环,没接收完等待接受 RI=0; //硬件置位,软件清零 a=SBUF; //接受串口缓冲区数据。 SBUF=a; //通过串口缓冲区向外发送数据。 while(TI==0) //判断串口缓冲区是否发送完数据(TI=1时表示发送完) { ; // 发送完跳出循环,没发送完等待发送 } TI=0; //硬件置位,软件清零。 } } 调试助手设置 :(9600,n,8,1) 把这个程序编译,烧进单片机,就可以通过调试助手向单片机发送数据了。上面的助手有一个自动发送的选项,用这个选项可以方便调试过程。如果没有回显或显是不正确,请检查: 1、​ 单片机是否插上了板子,并且给板子加上了电。 2、​ 串口调试助手的设置是否正确(波特率,停止位,校验位,以及串口是否打开) 3、​ 程序是否烧写正确。 上面的程序使用查询方式做得,所谓查询,就是单片机不停的查询RI是否为1,TI是否为1。。。。。。这样单片机出了处理串口的数据别的什么都干不了了,所以我们下面有了另一中方式――――中断方式。此种方式,一旦串口请求中断,就处理串口。其他时间单片机可以干别的事情。请看程序: 实验五 #pragma small //存储模式定义(一般不必深究) #include //头文件 unsigned char a; void initmpu(void)//串口、中断、初始化设置子函数 //11.0592MH晶振下,波特率9600,无奇偶校验 { TMOD=0x20;//定时器1的工作方式2 TL1=0xfd; //装载计数初值 TH1=0xfd; SCON=0x50; //采用串口工作方式1,无奇偶校验 PCON=0x00;//串口波特率不加倍 IE=0x90;//开总中断,开串口中断 TR1=1;//启动定时器1 } void getch(void) interrupt 4//中断源编号为4,即串口中断 { RI=0;//清除中断标志,硬件置位,软件清零 a=SBUF; //接受串口缓冲区数据。 SBUF=a; //通过串口缓冲区向外发送数据。 while(TI==0)//判断是否发送结束:TI==1为结束。 {; //等待发送结束 } TI=0; //发送结束标志清零 } void main(void) //主函数,中断方式串口通讯 { initmpu(); //调用初始化串口子函数 while(1)//无限空循环,此处可以加其它功能 {; } } 调试助手设置 :(9600,n,8,1) 上面这个程序就是用的中断方式,我们说过,中断方式可以同时做其它事情,现在把上面的程序稍加改写,请看边让小灯闪烁边进行串口通讯的程序。 实验六 #pragma small //存储模式定义 #include //头文件 unsigned char a; sbit P10=P1^0; //定义P10 void initmpu(void)//串口、中断、初始化设置子函数 //11.0592MH晶振下,波特率9600,无奇偶校验 { TMOD=0x20; //定时器1的工作方式2 TL1=0xfd; //装载计数初值 TH1=0xfd; SCON=0x50; //采用串口工作方式1,无奇偶校验 PCON=0x00; //串口波特率不加倍 IE=0x90; //开总中断,开串口中断 TR1=1; //启动定时器1 } void getch(void) interrupt 4//中断源编号为4,即串口中断 { RI=0; //清除中断标志,硬件置位,软件清零 a=SBUF; //接受串口缓冲区数据。 SBUF=a; //通过串口缓冲区向外发送数据。 while(TI==0) //判断是否发送结束:TI==1为结束。 {; //等待发送结束 } TI=0; //发送结束标志清零 } void main(void) //主函数,中断方式串口通讯 { unsigned char j, k; P10=0; initmpu(); //调用初始化串口子函数 while(1) //无限空循环,此处可以加其它功能 { for(j=0;j<500;j++) for(k=0;k<200;k++) {; } //软件延时 P10=!P10; //控制小灯 } } 调试助手设置 :(9600,n,8,1) 好了,如果以上几个实验你都实验成功并且掌握了串口通讯的流程,基本任务完成了,下面一部分是我在做串口通讯实验时遇到的几个问题,有的解决了,有的还没有解决,我都记录了下来,请您参考。相信您如果认真的做了如下几个实验,你将会对串口通讯有更深入一些的理解。 有关串口通讯试验的几个问题的思考 前一章中用的是串口的方式1,即无奇偶校验位,如果想要加进奇偶校验,就要采用方式2或方式三。本实验采用方式三。 前一章的实验全是用的是9600的波特率,这是为了入门的方便。在实际的工作中对波特率是有更高要求的。单片机串口通讯的波特率高低对整个系统性能有着重要影响。所以,能获得多高的稳定波特率、怎样获得较高的稳定的波特率是接下来要讨论的。 ​ 用查询方式实现57600的波特率(加奇偶校验) 奇偶校验是为了发送接收数据的过程中不出错的一种设置。其基本思想是:计算出发送的每一帧数据“1”的个数,如果为奇数个,则校验位置1,如果为偶数个,则校验位置0,这样每帧数据加上自己的校验位1的个数都是偶数个。此种方式叫偶校验。反之,是奇校验。在单片机中,硬件自己可以进行奇偶校验。单片机的PSW寄存器的P位就是用来做奇偶校验的。当累加寄存器ACC(是八位寄存器)中1的个数是奇数时,P的值是1,当ACC中1的个数是偶数时,P的值是0。这样其实硬件自己完成了偶校验。 1 0 0 1 0 1 0 1 累加器ACC示意表 当ACC中的值按如上设置时,PSW中的P位应是0。我们前面提到过,串口控制寄存器SCON中的TB8位用于发送校验位,只要把硬件统计出来的校验值赋给TB8就可以了。C语句实现如下: ACC=SBUF; TB8=P; 奇偶校验中每一帧数据格式如下: 起始 数据 。。。 。。。 。。。 。。。 。。。 。。。 数据 校验 停止 其中的校验位就是TB8的数据。 奇偶校验的实现过程是这样的(以偶校验为例):串口调试助手每发送一个字节(8位)数据,就统计这八位中1的个数,并且自己记录下。单片机收到这个字节的8位数据后,把它放进ACC,然后把P的值给发送的第九位TB8,串口调试助手接收到单片机送回的一帧数据后,检测TB8,看是否和自己刚才计算的校验值相等,如相等,则此帧数据发送,回显正确;如不等,则回显是错误的。 好了,有了这些,请看以下程序: 实验七 #include void main(void)//波特率57600,加偶校验,采用查询方式 { TMOD=0x20;//定时器1方式2 TL1=0xff;//置数,波特率57600 TH1=0xff; SCON=0xd8;//串口工作方式3有奇偶校验 PCON=0x80;//波特率加倍 TR1=1;//启动定时器 while(1)//无限循环 { while(RI==0)//等待接收完毕 { } RI=0;//清除接收标志 ACC=SBUF;//将接收到的数据送给累加器ACC TB8=P;//将校验位赋给要发送的第九位 SBUF=ACC;//向pc发送刚接收到的数据 while(TI==0)//等待发送结束 { } TI=0;//清零结束标志 } } 调试助手设置 :(57600,e,8,1) 经调试,查询方式可以达到57600的波特率,并且可以加奇偶校验,这就是说,比以前的9600的
本文档为【单片机串口通信】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_899773
暂无简介~
格式:doc
大小:362KB
软件:Word
页数:26
分类:
上传时间:2011-09-24
浏览量:62