89C52中SCON的SM2、TB8、RB8有何作用

学习了条件语句用多个条件语呴能实现多方向条件分支,但是能发现使用过多的 条件语句实现多方向分支会使条件语句嵌套过多程序冗长,这样读起来也很不好读這个时候 使用开关语句同样能达到处理多分支选择的目的,又能使程序结构清晰它的语法为下:

运行中 switch 后面的表达式的值将会做为条件,与 case 后面的各个常量表达式的值相 对比如果相等时则执行 case 后面的语句,再执行 break(间断语句)语句跳出 switch 语句。如果 case 后没有和条件相等的值时僦执行 default 后的语句当要求没有符合的条 件时不做任何处理,则能不写 default 语句

在上面的章节中我们一直在用 printf 这个标准的 C 输出函数做字符的输絀,使用它当 然会很方便但它的功能强大,所占用的存储空间自然也很大要 1K 左右字节空间,如果 再加上 scanf 输入函数就要达到 2K 左右的字节这样的话如果要求用 2K 存储空间的芯片时 就无法再使用这两个函数,例如 AT89C2051在这些小项目中,通常我们只是要求简单的字 符输入输出这裏以笔者发表在本人网站的一个简单的串行口应用实例为例,一来学习使用开 关语句的使用二来简单了解 51 芯片串行口基本编程。这个实唎是用 PC 串行口通过上位机程序 与由 AT89c51 组成的下位机相通信实现用 PC 软件控制 AT89c51 芯片的 IO 口,这样也就可 以再通过相关电路实现对设备的控制为叻方便实验,在此所使用的硬件还是用回以上课程 中做好的硬件以串行口和  PC  连接,用  LED  查看实验的结果原代码请到在笔者的网站 下载,仩面有  单片机c语言  下位机源码、PC 上位机源码、电路图等资料

代码中有多处使用开关语句的,使用它对不一样的条件做不一样的处理如茬 CSToOut 函数 中根据 CN[1]来选择输出到那个 IO 口,CN[1]=0 则把 CN[2]的值送到 P0CN[1]=1 则送到 P1, 这样的写法比起用 if (CN[1]==0)这样的判断语句来的清晰明了当然它们的效果没有太大 嘚差别(在不考虑编译后的代码执行效率的情况下)。

在这段代码主要的作用就是通过串行口和上位机软件进行通信跟据上位机的命令字串, 对指定的 IO 端口进行读写InitCom 函数,原型为 void InitCom(unsigned char BaudRate) 其作用为初始化串行口。它的输入参数为一个字节程序就是用这个参数做为开关语句的选择 參数。如调用 InitCom(6),函数就会把波特率设置为 9600当然这段代码只使用了一种波特 率,能用更高效率的语句去编写这里就不多讨论了。

看到这里你也许会问函数中的 SCON,TCONTMOD,SCOM 等是代表什么它们是特殊 功能寄存器。

SBUF    数据缓冲寄存器    这是一个能直接寻址的串行口专用寄存器有朋友這样问起 过“为何在串行口收发中,都只是使用到同一个寄存器 SBUF而不是收发各用一个寄存器。” 实际上 SBUF 包含了两个独立的寄存器一个昰发送寄存,另一个是接收寄存器但它们都 共同使用同一个寻址地址-99H。CPU 在读 SBUF 时会指到接收寄存器在写时会指到发送寄

存器,而且接收寄存器是双缓冲寄存器这样能避免接收中断没有及时的被响应,数据没

有被取走下一帧数据已到来,而造成的数据重叠问题发送器则不需要用到双缓冲,一般 情况下我们在写发送程序时也不必用到发送中断去外理发送数据操作 SBUF 寄存器的方法 则很简单,只要把这个 99H 哋址用关键字 sfr 定义为一个变量就能对其进行读写操作了

SCON    串行口控制寄存器    通常在芯片或设备中为了监视或控制接口状态,都会引用 到接ロ控制寄存器SCON 就是 51 芯片的串行口控制寄存器。它的寻址地址是 98H是一个 能位寻址的寄存器,作用就是监视和控制 51 芯片串行口的工作状态51 芯片的串行口能 工作在几个不一样的工作模式下,其工作模式的设置就是使用 SCON 寄存器它的各个位的具 体定义如下:

SM0、SM1  为串行口工作模式设置位,这样两位能对应进行四种模式的设置看表  8

-2 串行口工作模式设置。

在这里只说明最常用的模式 1其它的模式也就一一略过,囿兴趣的朋友能找相关的 硬件资料查看表中的  fosc  代表振荡器的频率,也就是晶体震荡器的频率UART  为(Universal Asynchronous  Receiver)的英文缩写。

SM2 在模式 2、模式 3 中为多处理機通信使能位在模式 0 中要求该位为 0。

REM 为允许接收位REM 置 1 时串行口允许接收,置 0 时禁止接收REM 是由软件置位或 清零。如果在一个电路中接收和发送引脚 P3.0,P3.1 都和上位机相连在软件上有串行口中断 处理程序,当要求在处理某个子程序时不允许串行口被上位机来的控制字符产生中斷那么可 以在这个子程序的开始处加入 REM=0 来禁止接收,在子程序结束处加入 REM=1 再次打开串行口 接收大家也能用上面的实际源码加入 REM=0 来进行實验。

TB8 发送数据位 8在模式 2 和 3 是要发送的第 9 位。该位能用软件根据需要置位或 清除通常这位在通信协议中做奇偶位,在多处理机通信中這一位则用于表示是地址帧还是 数据帧

RB8 接收数据位 8,在模式 2 和 3 是已接收数据的第 9 位该位可能是奇偶位,地址/ 数据标识位在模式 0 中,RB8 為保留位没有被使用在模式 1 中,当 SM2=0RB8 是已接 收数据的停止位。

TI 发送中断标识位在模式 0,发送完第 8 位数据时由硬件置位。其它模式中則是在 发送停止位之初由硬件置位。TI 置位后申请中断,CPU 响应中断后发送下一帧数据。 在任何模式下TI 都必须由软件来清除,也就是說在数据写入到 SBUF 后硬件发送数据,

中断响应(如中断打开)这个时候 TI=1,表明发送已完成TI 不会由硬件清除,所以这个时候必须

RI 接收中断标識位在模式 0,接收第 8 位结束时由硬件置位。其它模式中则是在接 收停止位的半中间由硬件置位。RI=1申请中断,要求 CPU 取走数据但在模式 1 中,SM2=1 时当未收到有效的停止位,则不会对 RI 置位同样 RI 也必须要靠软件清除。

常用的串行口模式 1 是传输 10 个位的1 位起始位为 0,8 位数据位,低位在先1 位停止 位为 1。它的波特率是可变的其速率是取决于定时器 1 或定时器 2 的定时值(溢出速率)。 AT89c51 和 AT89C2051 等 51 系列芯片只有两个定时器定時器 0 和定时器 1,而定时器 2

是 89C52 系列芯片才有的

波特率    在使用串行口做通信时,一个很重要的参数就是波特率只有上下位机的波特率 一样時才能进行正常通信。波特率是指串行端口每秒内能传输的波特位数有一些开始学习 的朋友认为波特率是指每秒传输的字节数,如标准  9600  會被误认为每秒种能传送  9600 个字节而实际上它是指每秒能传送 9600 个二进位,而一个字节要 8 个二进位如用串 口模式 1 来传输那么加上起始位和停止位,每个数据字节就要占用 10 个二进位9600 波特 率用模式 1 传输时,每秒传输的字节数是 9600÷10=960 字节51 芯片的串行口工作模式 0 的波特率是固定嘚,为 fosc/12以一个 12M 的晶体震荡器来计算,那么它的波特率能达到 1M 模式 2 的波特率是固定在 fosc/64 或 fosc/32,具体用那一种就取决于 PCON 寄存器中的 SMOD 位如 SMOD 为 0,波特率为 focs/64,SMOD 为 1波特率为 focs/32。模式 1 和模式 3 的波 特率是可变的取决于定时器 1 或 2(52 芯片)的溢出速率。那么我们怎么去计算这两个模 式的波特率设置時相关的寄存器的值呢能用以下的公式去计算。

上式中如设置了 PCON 寄存器中的 SMOD 位为 1 时就能把波特率提升 2 倍通常会使用 定时器 1 工作在定时器工作模式 2 下,这个时候定时值中的 TL1 做为计数TH1 做为自动重装值    , 这个定时模式下定时器溢出后,TH1 的值会自动装载到 TL1再次开始计数,這样能不 用软件去干预使得定时更准确。在这个定时模式 2 下定时器 1 溢出速率的计算公式如下:

溢出速率=(计数速率)/(256-TH1) 上式中的“计数速率”与所使用的晶体振荡器频率有关在 51 芯片中定时器启动后会

在每一个机器周期使定时寄存器 TH 的值增加一,一个机器周期等于十二个振蕩周期所以

能得知 51 芯片的计数速率为晶体振荡器频率的 1/12,一个 12M 的晶体震荡器用在 51 芯片上 那么 51 的计数速率就为 1M。通常用 11.0592M 晶体是为了得到標准的无误差的波特率那 么为何呢?计算一下就知道了如我们要得到 9600 的波特率,晶体震荡器为 11.0592M 和 12M定 时器 1 为模式 2,SMOD 设为 1分别看看那所要求的 TH1

上面的计算能看出使用 12M 晶体的时候计算出来的 TH1 不为整数,而 TH1 的值只能取

整数这样它就会有一定的误差存在不能产生精确的 9600 波特率。当然一定的误差是能 在使用中被接受的就算使用 11.0592M 的晶体振荡器也会因晶体本身所存在的误差使波特

率产生误差,但晶体本身的误差對波特率的影响是十分之小的能忽略不计。

}

单片机串口通信理解(一)

  • 串行ロ数据缓冲器SBUF

SBUF(serial data buffer)用于串口数据传输在51单片机内部分为两个物理上独立的8位缓冲器:发送缓冲器和接收缓冲器。而这两个缓冲器共用一個名称SBUF共用一个地址99H,这意味着在程序中对SBUF进行修改时发送缓冲器和接收缓冲器的值都会改变,且发送缓冲器与接受缓冲器的值始终楿等
那么物理上独立是什么意思呢?物理上独立指的是在51单片机的硬件中存在发送缓冲器和接收缓冲器其中,
在执行写指令 MOV SBUF , A 时发送缓沖器起作用
在执行读指令 MOV A , SBUF 时接受缓冲器起作用
这意味着通过物理上独立的SBUF缓冲器可以实现全双工通信

  • 串行口控制寄存器SCON

SM2:多机通信控制位

用于多机通信中的从机,仅用于从机被寻址的阶段在一次通信过程正式开始前,从机接收并侦测主机发出的每一个信息帧试图寻找呼叫自身的地址码。换句话说SM2位用于从机筛选自身,一旦筛选完毕该位的使命就完成了。

REN:串口接受允许位

对于单片机来说数据的發送过程是主动的,只要将发送数据送入SBUF发送过程就开始了。但数据的接收是被动的一旦数据到来,串口便会自动接收而不管CPU是否需偠接收因此需要有控制的接收行为。REN=1允许串口接收;REN=0,不允许串口接收

TB8:发送的第9位数据

在方式2和方式3中发送的第9位数据,TB8=1说明主机发送的是地址;TB8=0,说明主机发送的是数据

RB8:接收的第9位数据

在方式2和方式3中接收的第9位数据。RB8=1说明从机接收到的是地址帧;RB8=0,说奣从机接收的是数据帧

在第8位发送结束时自动置位,需软件清零

在第8位接收结束时自动置位,需软件清零

  • 电源控制寄存器PCON

仅D7位与穿孔通信有关,为波特率倍增位SMOD在方式1,方式2方式3中波特率倍增。

在工作方式1和3中会会涉及TMODTCON寄存器,这里不提想看自己去别的地方看


从网上找不到好图就自己拍了

在图上发现一个很有趣的地方,在接收时需要一个移位寄存器而发送时没有。因为发送时CPU是主动的不會发生帧重叠错误,而接收时CPU是被动的通过移位寄存器与接收缓冲器的双缓冲结构可以避免在数据接收过程中产生帧重叠。

接下来介绍串口通信的数据格式方式0为8位同步首发,直接传送8位数据
方式1为10位异步收发,第一位为起始位第二至第九位为传送的8位数据,第十位为停止位
方式2和方式3为11位异步收发,第一位为起始位第二至第九位为传送的8位数据,第十位为传输数据的第九位当发送数据时第⑨位为TB8,接收数据时第九位为RB8TB8和RB8用来判断数据位的前8位为数据还是地址,第十一位为停止位

串口通信的数据格式可以如下表示

方式0:數据位(8位)
方式1:起始位+数据位(8位)+停止位
方式2:起始位+数据位(8位)+第九位数据位+停止位
方式3:起始位+数据位(8位)+第九位数据位+停止位

比特率的单位是bps(bit per second),为每秒传输的位的数量例如4000bps意味着一秒钟传送4000个位。

波特率的单位是bd(boud)意为每秒传输码元的数量,码え指的是携带信息的信号对于方式0,8bit(位)=1码元对于方式1,10bit=1码元对于方式2和方式3,11bit=1码元所以对于方式1,4000bps=400bd

不过多数搞单片机的人認为波特率=比特率,我翻的书上也确实都是这么写的他们说波特率4800的意思是4800bps,不过上应该是比特率4800可能这也是约定俗成,将错就错

這篇文章仅涉及单机通信,我认为双机通信原理更加简单本文不涉及

单片机的串口通信是一位一位输入,在单片机时钟周期的下降沿读絀或写入数据其中,TI置位条件是数据位全部发送完成停止位发送之前。RI置位条件是停止位发送结束后换句话说,除方式0其他3种方式TI置位提前于RI,提前量为1个时钟周期

上图为单片机中断原理图,在第1个机器周期的第5个时钟周期的第1个振荡周期结束后进行采样在第2個机器周期的第6个时钟周期的第1个振荡周期结束后进入中断。(为了方便我将用X表示机器周期,S表示时钟周期P表示振荡周期,X1S5P2即为上圖中的采样置标志)

1.中断响应条件是在采样置标志采集成功在下一个机器周期查询标志转入处理(该处理是为了确定先响应哪个中断),之后根据中断优先级进入中断即使只有一个中断信号,也必须在下一个机器周期结束后进入中断
2.采样置标志在每个机器周期的S5P2都会查询。
3.中断的响应必须在该条语句结束后
4.若当前执行的指令是RETI或对IE/IP寄存器进行修改时,不响应中断
5.在中断中只响应中断优先级高于正茬执行的中断的中断。
6.存在这样一种情况中断标志位被置位但由于某种条件没有被响应,在下一个机器周期中断置位标志消失(对说嘚就是你,低电平触发的外部中断)此时该中断被忽略(!)换句话说,如果未及时响应虽然曾经产生过中断信号,我们不予处理

峩们给出这样的一个程序段:

接下来开始分析,对于方式1共有10位数据需要发送,MOV SBUF , A 这条语句将会占用2个机器周期在S3结束时TI置位,S4结束时RI置位由于查询标志在S5P2,此时TIRI均置位,在MOV SBUF , A 语句结束后因为单片机还没有运行到查询标志转入处理(X2S6P2),下一机器周期执行JNB TI , $ 指令由于此时TI为1,所以顺序执行的下一条语句为CLR TI但此时必须进行中断响应,此时TI仍然为1程序跳转到EXIT清空TI。

此时出现了一个很不可思议的情况:雖然在中断返回时他应该执行CLR TI指令,但在中断中TI被清零了所以JNB TI,$指令被重新判断此时TI为零,所以单片机将停在JNB TI$这条语句,而非SJMP $

实际上,在单片机执行过程中由于RI=1,所以单片机还能继续进入中断在JNB TI,$和中断程序中不断反复这很奇怪,我在中断中清空RITI也為0,为什么还会进入中断呢因为虽然我们通过软件清空了RI,但由于SBUF寄存器未清零单片机将一直认为有数据发送至单片机,将有硬件自動将RI置位

最后捎带扯一下多机通信,多机通信极极极极极极极极极极极极少出现TIRI同时置1的情况(我认为可能性为0),在实际实现过程Φ若RI或TI置1那么单片机将不再写或读,上述例子只是为了理解


由于作者本人单片机水平着实有限(低得可怕),且结论得出仅通过keil软件汸真如有理解不当之处请指出。

}

定时器/计数器模式控制寄存器TMOD是┅个逐位定义的8位寄存器但只能使用字节寻址,其字节地址为89H

GATE  :为门控位,GATE=0时只要在编写程序时,使TCON中的TRO或TR1为1就可以启动定时器/計数器工作。

M1M0:用来选择定时计/计数器的工作方式,一般使用都是采用16位的计时计数器

定时器控制寄存器,作用是控制定时器的启、停标志定时器溢出和中断情况。

TR1  :TR1=1表示T1开始运行(单片机中T0引脚,需要高低电平的驱动)

TR0  :TR0=1表示T0开始运行(单片机中T1引脚,需要高低电平的驱动)


在程序中通过设订两个8位寄存器中TH与TL的值,来决定定时值和计数值TH与TL的计算过程如下:

假设定时器的时间常数为X,定时器的位数为N
N为定时器的工作方式(关于定时/计数器的4中工作方式,以下会有具体介绍):


根据定时时间和工作方式通过公式:定时时间T=(2的N次方-X)12/单片机晶振频率,计算出时间常数X
把X转换成二进制数高8位送给TH1,低8位送给TL1,就可以启动定时器开始定时了。

定时器的3种工作方式图解:

总結定时器的操作步骤如下:

2.选择控制方式GATE(为0是只要软件设定好参数即可为1则需要软件设定参数,且定时器/计数器的中断引脚需要为高電平)

3.确定定时器的工作模式是定时模式还是计数模式 C/T.

4.给定时器设初值(设置THX与TLX)

5.开启定时器中断(设置ET0或ET1)

6.开启总中断(设置EA的值)

7.萣时器/计数器的选择T0/T1(设置TR1或TR0的值)

例:设置一个LED灯每500ms的评率闪烁

选择工作方式(设置M1,M0)

选择控制方式(设置GATE)

选择定时器还是计数器模式(设置C/T)

给定时/计数器赋初值(设置THx和TLx

开启定时器中断(设置ET0或ET1

开启总中断(设置EA)

打开计数器(设置TR1或TR0)

选择控制方式(设置GATE)

选择萣时器还是计数器模式(设置C/T)

给定时/计数器赋初值(设置THx和TLx

开启定时器中断(设置ET0或ET1)

开启总中断(设置EA)

打开计数器(设置TR1或TR0)

定时器操作步骤 

选择工作方式(设置M1M0)

选择控制方式(设置GATE)

选择定时器还是计数器模式(设置C/ 

给定时/计数器赋初值(设置THx和TLx)

开启定时器中断(設置ET0或ET1

开启总中断(设置EA)

打开计数器(设置TR1或TR0)

由TL0的低5位(高3位未用)和TH0的8位组成。TL0的低5位溢出时向TH0进位TH0溢出时,置位TCON中的TF0标志向CPU發出中断请求。由TL0的低5位(高3位未用)和TH0的8位组成TL0的低5位出时向TH0进位,TH0溢出时置位TCON中的TF0标志,向CPU发出中断请求,由TL0的低5位(高3位未鼡)和TH0的8位组成TL0的低5位溢出时向TH0进位,TH0溢出时置位TCON中的TF0 
————————————————

SM0、SM1工作方式控制位

SM2:多机通信控制位,1-允許、0-不允许

REN:串行接收允许位1-允许、0-不允许

TB8:发送数据第九位

RB8:接收数据第九位

①SM0和SM1 :串行口工作方式选择位 ,两个选择位对应四种通信方式如下图所示,其中fosc是振荡频率

SM2:多机通信控制位主要用于方式2和方式3。

1;则允许多机通信多机通信协议规定,第9位数据(D8)為1说明本帧数据为地址帧;若第9位数据为0,则本帧数据为数据帧当一个89c51(主机)与多个89c51(从机)通信时,所有从机的SM2位都置1主机首先发送的一帧数据为地址,即某从机号其中第9位为1,所有的从机接收数据后将其中第9位数据装入RB8中。各个从机根据接收到的第9位数据(RB8中)的值来决定从机是否再接收主机的信息、若(RB8)= 0说明是数据帧,则使接收中断标志位RI = 0信息丢失,若RB8 = 1说明是地址帧,数据装入SBUF並置RI = 1中断所有从机,被寻址的目标从机清除SM2以接收主机发来的一帧数据,其它从机仍然保持SM2 = 1

若SM2 = 0,即不属于多机通信情况则接收完┅帧数据后,不管第9位数据是0还是1都置RI = 1,接收到的数据装入SBUF中在方式0时SM2必须置0。在方式1时若SM2 = 1,则只有接收到有效停止位时RI才置1,鉯便接收下一帧数据

REN:允许接收控制位,由软件置1或清0

REN = 1时允许接收,相当于串行接收的开关

在串行通信接收控制过程中如果满足RI = 0和REN = 1嘚条件,就允许接收

TB8:发送数据的第9位(D8)装入TB8中。在方式2或方式3中根据发送数据的需求由软件置位或复位。在许多通信协议中可用莋奇偶校验位也可以在多机通信中作为发送地址帧或者数据帧的标志位。

RB8:接收数据的第9位原理同TB8

TI:发送中断标志位,在一帧数据发送完时被置位在串行发送到停止位的开始时由硬件置位,可用软件查询它同时也申请中断。TI置位意味着向CPU提供“发送缓冲器SBUF已空”的信息CPU可以准备发送下一帧数据。串行口发送中断被响应后TI不会自动清0,必须软件清0.

RI:接收中断标志在接收到一帧数据后由硬件置位。当RI = 1时申请中断,表示一帧数据接收结束并已装入接收SBUF中,要求CPU取走数据CPU响应中断,取走数据RI位也必须由软件来清0,。

串行发送中斷标志TI和接收中断标志RI是同一个中断源CPU事先不知道是发送中断TI还是接收中断RI产生的中断请求,所以在全双工通信时,必须由软件来判別复位时SCON所有位都清0.

电源控制位寄存器PCON中只有SMOD位与串口工作有关,如下图所示

SMOD:波特率倍增位在方式1、2、3中,当SMOD = 1时波特率提高一倍。

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信