在串行通信中,收发双方对发送或接收的数据速率要有一定的约定,我们通过软件对MCS—51串行口编程可约定四种工作方式。其中,方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T1的溢出率决定。
串行口的四种工作方式对应着三种波特率。由于输人的移位时钟的来源不同,所以,各种方式的波特率计算公式也不同。 一、方式0的波特率
方式0时,移位时钟脉冲由S6(即第6个状态周期,第12个节拍)给出,即每个机器周期产生一个移位时钟,发送或接收一位数据。所以,波特率为振荡频率的十二分之一,并不受 PCON寄存器中SMOD的影响,即: 方式0的波特率=fosc/12
三、方式l和方式3的波特率
方式1和方式3的移位时钟脉冲由定时器T1的溢出率决定,故波特宰由定时器T1的 溢出率与SMOD值同时决定,即:
方式1和方式3的波特率=2SMOD/32·T1溢出率
其中,溢出率取决于计数速率和定时器的预置值。计数速率与TMOD寄存器中C/T的状态有关。当C/T=0时,计数速率=fosc/2;当C/T=1时,计数速率取决于外部输入时钟频率。
当定时器Tl作波特率发生器使用时,通常选用可自动装入初值模式(工作方式2),在 工作方式2中,TLl作为计数用,而自动装入的初值放在THl中,设计数初值为x,则每过“256一x”个机器周期,定时器T1就会产生一次溢出。为了避免因溢出而引起中断,此时应禁止T1中断。这时,溢出周期为:
系统晶振频率选为11.0592MHZ就是为了使初值为整数,从而产生精确的波特率。 如果串行通信选用很低的波特率,可将定时器Tl置于工作方式0或工作方式1,但在 这种情况下,T1溢出时,需用中断服务程序重装初值。中断响应时间和执行指令时间会使波特率产生一定的误差,可用改变初值的办法加以调整。 表6—2列出了各种常用的波特率及其初值。
51单片机串口通信及波特率设置
2010-05-21 14:131653人阅读评论(0)收藏举报
MCS-51单片机具有一个全双工的串行通信接口,能同时进行发送和接收。它可以作为UART(通用异步接收和发送器)使用,也可以作为同步的移位寄存器使用。
1. 数据缓冲寄存器SBUF
SBUF是可以直接寻址的专用寄存器。物理上,它对应着两个寄存器,即一个发送寄存器一个接收寄存器,CPU写SBUF就是修改发送寄存器;读SBUF就是读接收寄存器。接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时的响应接收器的中断,没有把上一帧的数据读走而产生两帧数据重叠的问题。对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生重叠问题。
2. 状态控制寄存器SCON
SCON是一个逐位定义的8位寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态,SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。它的各个位定义如下:
MSB LSB
SM0和SM1是串口的工作方式选择位,2个选择位对应4种工作方式,如下表,其中Fosc是振荡器的频率。
SM2在工作方式2和3中是多机通信的使能位。在工作方式0中,SM2必须为0。在工作方式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。在工作方式2和3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。此功能可用于多处理机通信。
REN为允许串行接收位,由软件置位或清除。置位时允许串行接收,清除时禁止串行接收。 TB8是工作方式2和3要发送的第9位数据。在许多通信协议中该位是奇偶位,可以按需要由软件置位或清除。在多处理机通信中,该位用于表示是地址帧还是数据帧。
RB8是工作方式2和3中接收到的第9位数据(例如是奇偶位或者地址/数据标识位),在工作方式1中若SM2=0,则RB8是已接收的停止位。在工作方式0中RB8不使用。
TI 为发送中断标志位,由硬件置位,软件清除。工作方式0中在发送第8位末尾由硬件置位;在其他工作方式时,在发送停止位开始时由硬件置位。TI=1时,申请中断。CPU响应中断后,发送下一帧数据。在任何工作方式中都必须由软件清除TI。
RI为接收中断标志位,由硬件置位,软件清除。工作方式0中在接收第8位末尾由硬件置位;在其他工作方式时,在接收停止位的中间由硬件置位。RI=1时,申请中断,要求CPU取走数据。但在
工作方式1中,SM2=1且未接收到有效的停止位时,不会对RI置位。在任何工作方式中都必须由软件清除RI。
系统复位时,SCON的所有位都被清除。
控制寄存器PCON也是一个逐位定义的8位寄存器,目前仅仅有几位有定义,如下所示: MSB LSB
仅最高位SMOD与串口的控制有关,其他位与掉电方式有关。PCON的地址为87H只能按字节寻址,SMOD是串行通信波特率系数控制位,当串口工作在工作方式1、2时,若使用T1作为波特率发生器其SMOD=1则波特率加倍(见下面详述)。
GF1 和GF0用于一般的用途,对于AT89系列为通用的标志位,PD为电源下降位,对于AT89系列,PD为1进入掉电状态,IDL为IDLE模式位,对于AT89系列,IDL为1进入空闲工作方式,在PD和IDL同时为1时,PD优先。
(1)工作方式0
SM0=0且SM1=0时,串口选择工作方式0,实质这是一种同步移位寄存器模式。
其数据传输的波特率固定为Fosc/12,数据由RXD引脚输入或输出,同步时钟由TXD引脚输出。接收/发送的是8位数据,传输是低位在前,帧格式如下:
(2)工作方式1
当SM0=0且SM1=1时,串口选择工作方式1,其数据传输的波特率由定时/计数器T1、T2的溢出速率决定,可通过程序设定。当T2CON寄存器中的RCLK和TCLK置位时,用T2作为发送和接收波特率发生器,而RCLK=TCLK=0时,用T1作为波特率发生器,两者还可以交叉使用,即发送和接收采用不同的波特率。数据由TXD引脚发送,由RXD引脚接收。
发送或接收一帧的数据为10位,即1位起始位(0)、8位数据位(低位在先)和1位停止位(1)。真格式如下:
类似于工作方式0,当执行任一条SBUF指令时,就启动串行数据的发送。在执行写入SBUF的指令时,也将“1”写入发送移位寄存器的第9位,并通知发送控制器有发送请求。实际上,发送过程始于内部的16分频计数器下次满度翻转(全“1”变全“0”)后的那几个机器周期的开始。所以,每位的发送过程与16分频计数器同步,而不是与“写SBUF”同步。
此方式的工作过程包括发送和接收两部分。
当执行任一条写SBUF指令时,就启动串行数据的发送。在执行写入SBUF的指令时,也将“1”写入发送移位寄存器的第9位,并使发送控制器开始发送。在这期间,内部的定时保证写入SBUF与激活发送之间有一个完整的机器周期。当发送脉冲有效后,移位寄存器的内容由RXD引脚串行移位输出,移位脉冲由TXD引脚输出。
在发送有效的每个机器周期,发送移位寄存器右移一位,就在其左边补“0 ”。当数据的最高位移到移位寄存器的输出时,原写入第9位的“1”正好移到最高位的左边一位,由此向左的所有位都为“0”,这标志着发送控制器要进行最后依次移位,并撤消发送有效,同时使发送中断标志TI置位。
当REN=1且接收中断标志RI位清除时,即启动一个接收过程。在下一个机器周期,接收控制器将“11111110”写入接收移位寄存器,并在下一周期内激发接收有效,同时由TXD引脚输出移位脉冲。在移位脉冲的控制下,接收移位寄存器的内容每一个机器周期左移一位,同时由RXD引脚接收一位输入信号。
每当接收移位寄存器左移一位,原写入的“11111110”也左移一位。当最右边的“0”移到最左边时,标志着接收控制器要进行最后一次移位。在最后移位即将结束时,接收移位寄存器的内容送入到接收数据缓冲寄存器SBUF,然后在启动接收的第10个机器周期时,清除接收信号,将RI置位。
如果在第一个时钟周期中接收到的不是起始位(“0”),就复位接收电路,继续检测RXD引脚上1到0的跳变。如果接收到的是起始位,就将其移入接收移位寄存器,然后接收该帧的其他位。接收到的位从右边移入,原来写入的1从左边移出,当起始位移到最左边时,接收控制器将控制进行最后一次移位,把接收到的第9为数据送到接收数据缓冲器SBUF和RB8,同时置位RI。
在进行最后一次移位时,能将数据送入到接收数据缓冲器SBUF和RB8而且置位RI的条件如下: ● RI=0,即上一真数据接收完成时,发出的中断请求已经被响应,SBUF中的上一帧数据已经被取走。
● SM2=0或接收到的停止位为1。
这两个条件有一个不满足接收到的数据就有可能丢失,并且无法修复;如两者都满足则数据装入SBUF,停止位装入RB8且置位RI。
开始发送后的一个位周期,发送信号有效,开始将起始位送TXD引脚。一位时间后,数据信号有效。发送移位寄存器将数据由低位到高位顺序输出至TXD引脚。一位时间后第一个移位脉冲出现,将最低数据位从右边移出,同时从左边补上“0”。当数据的最高位移到移位寄存器的输出端时,先前写入第9位的“1”正好移到最高位的左边一位,而它的左区全部为“0”。在第10个位周期(16分频计数器回0时),发送控制器要进行最后一次清除发送信号,同时使发送中断标志TI置位。
当REN=1且接收中断标志RI位清除后,若在RXD引脚上检测到一个由“1”到“0”的跳变,立即启动一次接收的过程。同时复位16分频计数器,使输入位的边沿与时钟对齐,并将1FFH(9个“1”)写入接收移位寄存器。接收控制器继续以波特率的16倍的速率继续对RXD引脚进行检测,对每一位时间的第7、8、9个计数状态的采样值用多数表决法,当2次或2次以上的采样值相同时,采样值被接受。
(1)工作方式2和3
当SM0=1且SM1=0时,串口选择工作方式2,当SM0=1且SM1=1时,串口选择工作方式3。数据由TXD引脚发送由RXD引脚接收。
发送和接收的一帧信息为11位,即1位起始位(0),9位数位(低位在前,第9位数据位是可编程位)1位停止位(1)。发送时,可编程位(TB8)可赋0或1,接收时可编程位进入SCON中的RB8。帧的格式如下:
1. #include "Reg52.H"
2. /******************************************************************* 3. 请提前计算一下所选晶振能达到的最高速度,波特率不能超过最高速度 4. (1) 波特率加倍(SMOD=1):Max_Baud = FOSC/12/16 5. (2) 波特率不加倍(SMOD=0):Max_Baud = FOSC/12/32
6. 例如:22.1184MHz晶振,波特率加倍时,最大波特率=22118400/12/16=115200 7. *******************************************************************/ 8. #define FOSC 22118400 //振荡频率 9. #define BAUD 9600 //波特率 10. #define SMOD 1 //是否波特率加倍 11. #if SMOD
12. #define TC_VAL (256-FOSC/16/12/BAUD) 13. #else
14. #define TC_VAL (256-FOSC/32/12/BAUD) 15. #endif 16.
17. typedef unsigned char uint8; 18. typedef unsigned int uint16; 19.
20. code constchar str1[] = "Ther string is transmitted from 80C51!\r\n"; 21. code constchar str2[] = "Author: xqlu(at)ysu.edu.cn\r\n"; 22.
23. /***************函数声明*******************/ 24. voidInitUART(void); 25. voidSendOneByte(uint8);
26. voidSendrStr(const uint8 *ptr); 27.
28. /****************主函数********************/ 29. void main(void) 30. {
31. uint8 i=0; 32. InitUART(); 33.
34. while(str2[i]!='\0') 35. {
36. SendOneByte(str2[i++]); 37. } 38.
39. SendrStr(str1); 40.
41. while(1); 42. } 43.
44. /****************中断服务函数***************/
45. void UART_ISR(void) interrupt 4 46. {
47. uint8 RX_Data;
48. //只响应“接收”中断,“发送”中断来了就直接抹掉 49. if(RI) 50. {
51. RI = 0; //串口中断标志不能自己清除,需要手动清除 52. RX_Data=SBUF;
53. SendOneByte(RX_Data); 54. } 55. else
56. TI = 0; //串口发中断是发送完缓冲区数据之后产生 57. } 58.
59. /****************串口初始化函数*************/ 60. voidInitUART(void) 61. {
62. TMOD = 0x20; 63. SCON = 0x50; 64. TH1 = TC_VAL; 65. TL1 = TH1;
66. PCON = 0x80; //发送速率加倍 67. ES = 1; 68. EA = 1; 69. TR1 = 1; 70. }
71. /**************串口发送字符函数*************/ 72. voidSendOneByte(uint8 c) 73. {
74. ES = 0; //禁止发送中断 75. SBUF = c; 76. while(!TI); 77. TI = 0;
78. ES = 1;
79. }
80. /**************串口发送字符串函数*************/
81. voidSendrStr(const uint8 *ptr)
82. {
83. do
84. {
85. SendOneByte(*ptr);
86. }while(*ptr++!='\0');
87. }
通常情况下,8051系列单片机外接晶振频率一般是12MHz、24MHz、48MHz如图7-6-1,为什么会这样选取呢?从前面的章节已经介绍8051系列单片机的每12个时钟周期为一个指令周期,当8051系列单片机外接12MHz晶振时,指令周期=12/12MHz=1us;若外接24MHz晶振时,指令周期
=12/24MHz=0.5us;若外接48MHz晶振时,指令周期=12/48MHz=0.25us。8051系列单片机外接能够被除尽的晶振,在使用单片机内部的定时器/计数器资源时作定时器使用时能够得到精确定时应用;当使用汇编语言编程时,可以清楚知道当前每一行代码执行的时间。
8051系列单片机外接能够被除尽的晶振即12MHz、24MHz、48MHz这些晶振时,波特率的精确性就得不到保证。
假若现在单片机外接的晶振为12MHz时,以T/C2作波特率发生器,根据波特率公式:
波特率=Fosc/2x16x(65536-t)
9600=12MHz/2x16x(65536-t)
t=65496.9375
“65496.9375”不是一个整数值,是一个带有小数点的数值。对于常用的8位、9位、11位一帧的数据接收与传输,最大的允许误差分别是6.25%、5.56%、4.5%。虽然波特率允许误差,但是这样
通信时便会产生积累误差,进而影响数据的正确性。唯一的解决办法就是更改单片机外接的晶振频率,更改为常用于产生精确波特率的晶振如11.0592MHz、22.1184MHz。
假若现在单片机外接的晶振为11.0592MHz时,以T/C2作波特率发生器,根据波特率公式: 波特率=Fosc/2x16x(65536-t)
9600=11.0592MHz/2x16x(65536-t)
t=65500=0xFFDC
虽然使用11.0592MHz、22.1184MHz的晶振能够产生精确的波特率,但是用于系统精确的定时服务不是十分的理想。例如单片机外接11.0592MHz晶振时,指令周期=12/11.0592MHz≈1.085us,是一个无限循环的小数。当单片机外接22.1184MHz晶振时,指令周期
=12/22.1184MHz≈0.5425us,也是一个无限循环的小数。
串口工作在方式1时分别采用T/C1和T/C2产生常用波特率初值表如下。
MCS-51单片机串行口工作方式与波特率计算举例
1)方式0 方式0是外接串行移位寄存器方式。工作时,数据从RXD串行地输入/输出,TXD输出移位脉冲,使外部的移位寄存器移位。波特率固定为fosc/12(即,TXD每机器周期输出一个同位脉冲时,RXD接收或发送一位数据)。每当发送或接收完一个字节,硬件置TI=1或RI=1
1)方式0
方式0是外接串行移位寄存器方式。工作时,数据从RXD串行地输入/输出,TXD输出移位脉冲,使外部的移位寄存器移位。波特率固定为fosc/12(即,TXD每机器周期输出一个同位脉冲时,RXD接收或发送一位数据)。每当发送或接收完一个字节,硬件置TI=1或RI=1,申请中断,但必须用软件清除中断标志。
实际应用在串行I/O口与并行I/O口之间的转换。
2)方式1
方式1是点对点的通信方式。8位异步串行通信口,TXD为发送端,RXD为
接收端。一帧为10位,1位起始位、8位数据位(先低后高)、1位停止位。波特率由T1或T2的溢出率确定。
在发送或接收到一帧数据后,硬件置TI=1或RI=1,向CPU申请中断;但必须用软件清除中断标志,否则,下一帧数据无法发送或接收。
(1)发送:CPU执行一条写SBUF指令,启动了串行口发送,同时将1写入
输出移位寄存器的第9位。发送起始位后,在每个移位脉冲的作用下,输出移位寄存器右移一位,左边移入0,在数据最高位移到输出位时,原写入的第9位1的左边全是0,检测电路检测到这一条件后,使控制电路作最后一次移位,/SEND和DATA无效,发送停止位,一帧结束,置TI=1。
(2)接收:REN=1后,允许接收。接收器以所选波特率的16倍速率采样RXD
端电平,当检测到一个负跳变时,启动接收器,同时把1FFH写入输入移位寄存器(9位)。由于接、发双方时钟频率有少许误差,为此接收控制器把一位传送时间16等分采样RXD,以其中7、8、9三次采样中至少2次相同的值为接收值。接收位从移位寄存器右边进入,1左移出,当最左边是起始位0时,说明已接收8位数据,再作最后一次移位,接收停止位。此后:
A、若RI=0、SM2=0,则8位数据装入SBUF,停止位入RB8,置RI=1。
B、若RI=0、SM2=1,则只有停止位为1时,才有上述结果。
C、若RI=0、SM2=1,且停止位为0,则所接数据丢失。
D、若RI=1,则所接收数据丢失。
无论出现那种情况,检测器都重新检测RXD的负跳变,以便接收下一帧。
3)方式2、方式3
方式2和方式3是9位异步串行通信,一般用在多机通信系统中或奇偶校验的通信过程。在通讯中,TB8和RB8位作为数据的第9位,位SM2也起作用。方式2与方式3的区别只是波特率的设置方式不同。
(1)发送
向SBUF写入一个数据就启动串口发送,同时将TB8写入输出移位寄存器第9位。开始时,SEND和DATA都是低电平,把起始位输出到TXD。DATA为高,第一次移位时,将‘1’移入输出移位寄存器的第9位,以后每次移位,左边移入‘0’,当TB8移到输出位时,其左边是一个‘1’和全‘0’。检测到此条件,再进行最后一次移位,/SEND=1,DATA=0,输出停止位,置TI=1。
(2)接收
置REN=1,与方式1类似,接收器以波特率的16倍速率采样RXD端。。。在
起始位0移到输入寄存器的最左边时,进行最后一次移位。在RI=0,SM2=0或接收到的第9位=1时,收到的一字节数据装入SBUF,第9位进入RB8,置RI=1;然后又开始检测RXD端负跳变。
3、多机通信
在这里,多机系统是指‘一主多从’。51系列单片机中,利用第9位TB8/RB8
来区分地址与数据信息,用位SM2确定接收方是否对地址或数据帧敏感。其原则是:
1)发送方用第9位TB8=1标志地址帧,TB8=0标志数据帧。
2)接收方若设置SM2=1,则只能接收到地址信息,若设SM2=0,则不管是地址还是数据帧,都能接收到。
利用方式2、3的特点,在点对点的通讯中,在发送方可以用第9位TB8
作为奇偶校验位。在接收方,SM2位必须清0。
4、波特率
1)方式0的波特率=fosc/12
2)方式2的波特率=2^smod*fosc/64
3)方式1、3的波特率由T1或T2的溢出率和SMOD位确定:
(1)用T1:波特率=2^smod*T1定时器的溢出率/32,T1为方式2
T1定时器溢出率=1/((12/fosc)*(256-X))
例:已知fosc=6MHz,SMOD=0,设置波特率为2400,求T1的计数初值X。
波特率=1/((12/fosc)*(256-X))/32=fosc/12*32(256-X)
(256-X)=fosc/2400/384=6M/2400/384;256-X~=6.5104
X~=250=FAH 只能近似计算。
若fosc=11.0592MHz, 则256-X=11.0592M/2400/384=4068/384=12 X=F4H;可精确算出,对其它常用的标准波特率也是能正确算出。所以这个晶振频率是最常用的。
如果SMOD=1,则同样的X初值得出的波特率加倍。
(3)用T2:
在52型单片机中,串口方式1、3的波特率发生器选择由TCLK、RCLK位
确定是T1还是T2。若TCLK=1,则发送器波特率来自T2,否则来自T1。若RCLK=1,则接收器波特率来自T2,否则来自T1。
由T2产生的波特率与SMOD无关。T2定时的最小单元=2/fosc。T2的溢出脉冲16分频后作为串口的发送或接收脉冲。
波特率=(1/((2/fosc)(65536-X)))/16=fosc/(32(65536-X))
例:已知fosc=11.0592MHz,求波特率=2400时的X
2400=11059200/(32(65536-X)) 65536-X=144 X=65392=FF70H
计数器初值寄存器:RCAP2H=0FFH,RCAP2L=70H。
在串行通信中,收发双方对发送或接收的数据速率要有一定的约定,我们通过软件对MCS—51串行口编程可约定四种工作方式。其中,方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T1的溢出率决定。
串行口的四种工作方式对应着三种波特率。由于输人的移位时钟的来源不同,所以,各种方式的波特率计算公式也不同。 一、方式0的波特率
方式0时,移位时钟脉冲由S6(即第6个状态周期,第12个节拍)给出,即每个机器周期产生一个移位时钟,发送或接收一位数据。所以,波特率为振荡频率的十二分之一,并不受 PCON寄存器中SMOD的影响,即: 方式0的波特率=fosc/12
三、方式l和方式3的波特率
方式1和方式3的移位时钟脉冲由定时器T1的溢出率决定,故波特宰由定时器T1的 溢出率与SMOD值同时决定,即:
方式1和方式3的波特率=2SMOD/32·T1溢出率
其中,溢出率取决于计数速率和定时器的预置值。计数速率与TMOD寄存器中C/T的状态有关。当C/T=0时,计数速率=fosc/2;当C/T=1时,计数速率取决于外部输入时钟频率。
当定时器Tl作波特率发生器使用时,通常选用可自动装入初值模式(工作方式2),在 工作方式2中,TLl作为计数用,而自动装入的初值放在THl中,设计数初值为x,则每过“256一x”个机器周期,定时器T1就会产生一次溢出。为了避免因溢出而引起中断,此时应禁止T1中断。这时,溢出周期为:
系统晶振频率选为11.0592MHZ就是为了使初值为整数,从而产生精确的波特率。 如果串行通信选用很低的波特率,可将定时器Tl置于工作方式0或工作方式1,但在 这种情况下,T1溢出时,需用中断服务程序重装初值。中断响应时间和执行指令时间会使波特率产生一定的误差,可用改变初值的办法加以调整。 表6—2列出了各种常用的波特率及其初值。
51单片机串口通信及波特率设置
2010-05-21 14:131653人阅读评论(0)收藏举报
MCS-51单片机具有一个全双工的串行通信接口,能同时进行发送和接收。它可以作为UART(通用异步接收和发送器)使用,也可以作为同步的移位寄存器使用。
1. 数据缓冲寄存器SBUF
SBUF是可以直接寻址的专用寄存器。物理上,它对应着两个寄存器,即一个发送寄存器一个接收寄存器,CPU写SBUF就是修改发送寄存器;读SBUF就是读接收寄存器。接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时的响应接收器的中断,没有把上一帧的数据读走而产生两帧数据重叠的问题。对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生重叠问题。
2. 状态控制寄存器SCON
SCON是一个逐位定义的8位寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态,SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。它的各个位定义如下:
MSB LSB
SM0和SM1是串口的工作方式选择位,2个选择位对应4种工作方式,如下表,其中Fosc是振荡器的频率。
SM2在工作方式2和3中是多机通信的使能位。在工作方式0中,SM2必须为0。在工作方式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。在工作方式2和3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。此功能可用于多处理机通信。
REN为允许串行接收位,由软件置位或清除。置位时允许串行接收,清除时禁止串行接收。 TB8是工作方式2和3要发送的第9位数据。在许多通信协议中该位是奇偶位,可以按需要由软件置位或清除。在多处理机通信中,该位用于表示是地址帧还是数据帧。
RB8是工作方式2和3中接收到的第9位数据(例如是奇偶位或者地址/数据标识位),在工作方式1中若SM2=0,则RB8是已接收的停止位。在工作方式0中RB8不使用。
TI 为发送中断标志位,由硬件置位,软件清除。工作方式0中在发送第8位末尾由硬件置位;在其他工作方式时,在发送停止位开始时由硬件置位。TI=1时,申请中断。CPU响应中断后,发送下一帧数据。在任何工作方式中都必须由软件清除TI。
RI为接收中断标志位,由硬件置位,软件清除。工作方式0中在接收第8位末尾由硬件置位;在其他工作方式时,在接收停止位的中间由硬件置位。RI=1时,申请中断,要求CPU取走数据。但在
工作方式1中,SM2=1且未接收到有效的停止位时,不会对RI置位。在任何工作方式中都必须由软件清除RI。
系统复位时,SCON的所有位都被清除。
控制寄存器PCON也是一个逐位定义的8位寄存器,目前仅仅有几位有定义,如下所示: MSB LSB
仅最高位SMOD与串口的控制有关,其他位与掉电方式有关。PCON的地址为87H只能按字节寻址,SMOD是串行通信波特率系数控制位,当串口工作在工作方式1、2时,若使用T1作为波特率发生器其SMOD=1则波特率加倍(见下面详述)。
GF1 和GF0用于一般的用途,对于AT89系列为通用的标志位,PD为电源下降位,对于AT89系列,PD为1进入掉电状态,IDL为IDLE模式位,对于AT89系列,IDL为1进入空闲工作方式,在PD和IDL同时为1时,PD优先。
(1)工作方式0
SM0=0且SM1=0时,串口选择工作方式0,实质这是一种同步移位寄存器模式。
其数据传输的波特率固定为Fosc/12,数据由RXD引脚输入或输出,同步时钟由TXD引脚输出。接收/发送的是8位数据,传输是低位在前,帧格式如下:
(2)工作方式1
当SM0=0且SM1=1时,串口选择工作方式1,其数据传输的波特率由定时/计数器T1、T2的溢出速率决定,可通过程序设定。当T2CON寄存器中的RCLK和TCLK置位时,用T2作为发送和接收波特率发生器,而RCLK=TCLK=0时,用T1作为波特率发生器,两者还可以交叉使用,即发送和接收采用不同的波特率。数据由TXD引脚发送,由RXD引脚接收。
发送或接收一帧的数据为10位,即1位起始位(0)、8位数据位(低位在先)和1位停止位(1)。真格式如下:
类似于工作方式0,当执行任一条SBUF指令时,就启动串行数据的发送。在执行写入SBUF的指令时,也将“1”写入发送移位寄存器的第9位,并通知发送控制器有发送请求。实际上,发送过程始于内部的16分频计数器下次满度翻转(全“1”变全“0”)后的那几个机器周期的开始。所以,每位的发送过程与16分频计数器同步,而不是与“写SBUF”同步。
此方式的工作过程包括发送和接收两部分。
当执行任一条写SBUF指令时,就启动串行数据的发送。在执行写入SBUF的指令时,也将“1”写入发送移位寄存器的第9位,并使发送控制器开始发送。在这期间,内部的定时保证写入SBUF与激活发送之间有一个完整的机器周期。当发送脉冲有效后,移位寄存器的内容由RXD引脚串行移位输出,移位脉冲由TXD引脚输出。
在发送有效的每个机器周期,发送移位寄存器右移一位,就在其左边补“0 ”。当数据的最高位移到移位寄存器的输出时,原写入第9位的“1”正好移到最高位的左边一位,由此向左的所有位都为“0”,这标志着发送控制器要进行最后依次移位,并撤消发送有效,同时使发送中断标志TI置位。
当REN=1且接收中断标志RI位清除时,即启动一个接收过程。在下一个机器周期,接收控制器将“11111110”写入接收移位寄存器,并在下一周期内激发接收有效,同时由TXD引脚输出移位脉冲。在移位脉冲的控制下,接收移位寄存器的内容每一个机器周期左移一位,同时由RXD引脚接收一位输入信号。
每当接收移位寄存器左移一位,原写入的“11111110”也左移一位。当最右边的“0”移到最左边时,标志着接收控制器要进行最后一次移位。在最后移位即将结束时,接收移位寄存器的内容送入到接收数据缓冲寄存器SBUF,然后在启动接收的第10个机器周期时,清除接收信号,将RI置位。
如果在第一个时钟周期中接收到的不是起始位(“0”),就复位接收电路,继续检测RXD引脚上1到0的跳变。如果接收到的是起始位,就将其移入接收移位寄存器,然后接收该帧的其他位。接收到的位从右边移入,原来写入的1从左边移出,当起始位移到最左边时,接收控制器将控制进行最后一次移位,把接收到的第9为数据送到接收数据缓冲器SBUF和RB8,同时置位RI。
在进行最后一次移位时,能将数据送入到接收数据缓冲器SBUF和RB8而且置位RI的条件如下: ● RI=0,即上一真数据接收完成时,发出的中断请求已经被响应,SBUF中的上一帧数据已经被取走。
● SM2=0或接收到的停止位为1。
这两个条件有一个不满足接收到的数据就有可能丢失,并且无法修复;如两者都满足则数据装入SBUF,停止位装入RB8且置位RI。
开始发送后的一个位周期,发送信号有效,开始将起始位送TXD引脚。一位时间后,数据信号有效。发送移位寄存器将数据由低位到高位顺序输出至TXD引脚。一位时间后第一个移位脉冲出现,将最低数据位从右边移出,同时从左边补上“0”。当数据的最高位移到移位寄存器的输出端时,先前写入第9位的“1”正好移到最高位的左边一位,而它的左区全部为“0”。在第10个位周期(16分频计数器回0时),发送控制器要进行最后一次清除发送信号,同时使发送中断标志TI置位。
当REN=1且接收中断标志RI位清除后,若在RXD引脚上检测到一个由“1”到“0”的跳变,立即启动一次接收的过程。同时复位16分频计数器,使输入位的边沿与时钟对齐,并将1FFH(9个“1”)写入接收移位寄存器。接收控制器继续以波特率的16倍的速率继续对RXD引脚进行检测,对每一位时间的第7、8、9个计数状态的采样值用多数表决法,当2次或2次以上的采样值相同时,采样值被接受。
(1)工作方式2和3
当SM0=1且SM1=0时,串口选择工作方式2,当SM0=1且SM1=1时,串口选择工作方式3。数据由TXD引脚发送由RXD引脚接收。
发送和接收的一帧信息为11位,即1位起始位(0),9位数位(低位在前,第9位数据位是可编程位)1位停止位(1)。发送时,可编程位(TB8)可赋0或1,接收时可编程位进入SCON中的RB8。帧的格式如下:
1. #include "Reg52.H"
2. /******************************************************************* 3. 请提前计算一下所选晶振能达到的最高速度,波特率不能超过最高速度 4. (1) 波特率加倍(SMOD=1):Max_Baud = FOSC/12/16 5. (2) 波特率不加倍(SMOD=0):Max_Baud = FOSC/12/32
6. 例如:22.1184MHz晶振,波特率加倍时,最大波特率=22118400/12/16=115200 7. *******************************************************************/ 8. #define FOSC 22118400 //振荡频率 9. #define BAUD 9600 //波特率 10. #define SMOD 1 //是否波特率加倍 11. #if SMOD
12. #define TC_VAL (256-FOSC/16/12/BAUD) 13. #else
14. #define TC_VAL (256-FOSC/32/12/BAUD) 15. #endif 16.
17. typedef unsigned char uint8; 18. typedef unsigned int uint16; 19.
20. code constchar str1[] = "Ther string is transmitted from 80C51!\r\n"; 21. code constchar str2[] = "Author: xqlu(at)ysu.edu.cn\r\n"; 22.
23. /***************函数声明*******************/ 24. voidInitUART(void); 25. voidSendOneByte(uint8);
26. voidSendrStr(const uint8 *ptr); 27.
28. /****************主函数********************/ 29. void main(void) 30. {
31. uint8 i=0; 32. InitUART(); 33.
34. while(str2[i]!='\0') 35. {
36. SendOneByte(str2[i++]); 37. } 38.
39. SendrStr(str1); 40.
41. while(1); 42. } 43.
44. /****************中断服务函数***************/
45. void UART_ISR(void) interrupt 4 46. {
47. uint8 RX_Data;
48. //只响应“接收”中断,“发送”中断来了就直接抹掉 49. if(RI) 50. {
51. RI = 0; //串口中断标志不能自己清除,需要手动清除 52. RX_Data=SBUF;
53. SendOneByte(RX_Data); 54. } 55. else
56. TI = 0; //串口发中断是发送完缓冲区数据之后产生 57. } 58.
59. /****************串口初始化函数*************/ 60. voidInitUART(void) 61. {
62. TMOD = 0x20; 63. SCON = 0x50; 64. TH1 = TC_VAL; 65. TL1 = TH1;
66. PCON = 0x80; //发送速率加倍 67. ES = 1; 68. EA = 1; 69. TR1 = 1; 70. }
71. /**************串口发送字符函数*************/ 72. voidSendOneByte(uint8 c) 73. {
74. ES = 0; //禁止发送中断 75. SBUF = c; 76. while(!TI); 77. TI = 0;
78. ES = 1;
79. }
80. /**************串口发送字符串函数*************/
81. voidSendrStr(const uint8 *ptr)
82. {
83. do
84. {
85. SendOneByte(*ptr);
86. }while(*ptr++!='\0');
87. }
通常情况下,8051系列单片机外接晶振频率一般是12MHz、24MHz、48MHz如图7-6-1,为什么会这样选取呢?从前面的章节已经介绍8051系列单片机的每12个时钟周期为一个指令周期,当8051系列单片机外接12MHz晶振时,指令周期=12/12MHz=1us;若外接24MHz晶振时,指令周期
=12/24MHz=0.5us;若外接48MHz晶振时,指令周期=12/48MHz=0.25us。8051系列单片机外接能够被除尽的晶振,在使用单片机内部的定时器/计数器资源时作定时器使用时能够得到精确定时应用;当使用汇编语言编程时,可以清楚知道当前每一行代码执行的时间。
8051系列单片机外接能够被除尽的晶振即12MHz、24MHz、48MHz这些晶振时,波特率的精确性就得不到保证。
假若现在单片机外接的晶振为12MHz时,以T/C2作波特率发生器,根据波特率公式:
波特率=Fosc/2x16x(65536-t)
9600=12MHz/2x16x(65536-t)
t=65496.9375
“65496.9375”不是一个整数值,是一个带有小数点的数值。对于常用的8位、9位、11位一帧的数据接收与传输,最大的允许误差分别是6.25%、5.56%、4.5%。虽然波特率允许误差,但是这样
通信时便会产生积累误差,进而影响数据的正确性。唯一的解决办法就是更改单片机外接的晶振频率,更改为常用于产生精确波特率的晶振如11.0592MHz、22.1184MHz。
假若现在单片机外接的晶振为11.0592MHz时,以T/C2作波特率发生器,根据波特率公式: 波特率=Fosc/2x16x(65536-t)
9600=11.0592MHz/2x16x(65536-t)
t=65500=0xFFDC
虽然使用11.0592MHz、22.1184MHz的晶振能够产生精确的波特率,但是用于系统精确的定时服务不是十分的理想。例如单片机外接11.0592MHz晶振时,指令周期=12/11.0592MHz≈1.085us,是一个无限循环的小数。当单片机外接22.1184MHz晶振时,指令周期
=12/22.1184MHz≈0.5425us,也是一个无限循环的小数。
串口工作在方式1时分别采用T/C1和T/C2产生常用波特率初值表如下。
MCS-51单片机串行口工作方式与波特率计算举例
1)方式0 方式0是外接串行移位寄存器方式。工作时,数据从RXD串行地输入/输出,TXD输出移位脉冲,使外部的移位寄存器移位。波特率固定为fosc/12(即,TXD每机器周期输出一个同位脉冲时,RXD接收或发送一位数据)。每当发送或接收完一个字节,硬件置TI=1或RI=1
1)方式0
方式0是外接串行移位寄存器方式。工作时,数据从RXD串行地输入/输出,TXD输出移位脉冲,使外部的移位寄存器移位。波特率固定为fosc/12(即,TXD每机器周期输出一个同位脉冲时,RXD接收或发送一位数据)。每当发送或接收完一个字节,硬件置TI=1或RI=1,申请中断,但必须用软件清除中断标志。
实际应用在串行I/O口与并行I/O口之间的转换。
2)方式1
方式1是点对点的通信方式。8位异步串行通信口,TXD为发送端,RXD为
接收端。一帧为10位,1位起始位、8位数据位(先低后高)、1位停止位。波特率由T1或T2的溢出率确定。
在发送或接收到一帧数据后,硬件置TI=1或RI=1,向CPU申请中断;但必须用软件清除中断标志,否则,下一帧数据无法发送或接收。
(1)发送:CPU执行一条写SBUF指令,启动了串行口发送,同时将1写入
输出移位寄存器的第9位。发送起始位后,在每个移位脉冲的作用下,输出移位寄存器右移一位,左边移入0,在数据最高位移到输出位时,原写入的第9位1的左边全是0,检测电路检测到这一条件后,使控制电路作最后一次移位,/SEND和DATA无效,发送停止位,一帧结束,置TI=1。
(2)接收:REN=1后,允许接收。接收器以所选波特率的16倍速率采样RXD
端电平,当检测到一个负跳变时,启动接收器,同时把1FFH写入输入移位寄存器(9位)。由于接、发双方时钟频率有少许误差,为此接收控制器把一位传送时间16等分采样RXD,以其中7、8、9三次采样中至少2次相同的值为接收值。接收位从移位寄存器右边进入,1左移出,当最左边是起始位0时,说明已接收8位数据,再作最后一次移位,接收停止位。此后:
A、若RI=0、SM2=0,则8位数据装入SBUF,停止位入RB8,置RI=1。
B、若RI=0、SM2=1,则只有停止位为1时,才有上述结果。
C、若RI=0、SM2=1,且停止位为0,则所接数据丢失。
D、若RI=1,则所接收数据丢失。
无论出现那种情况,检测器都重新检测RXD的负跳变,以便接收下一帧。
3)方式2、方式3
方式2和方式3是9位异步串行通信,一般用在多机通信系统中或奇偶校验的通信过程。在通讯中,TB8和RB8位作为数据的第9位,位SM2也起作用。方式2与方式3的区别只是波特率的设置方式不同。
(1)发送
向SBUF写入一个数据就启动串口发送,同时将TB8写入输出移位寄存器第9位。开始时,SEND和DATA都是低电平,把起始位输出到TXD。DATA为高,第一次移位时,将‘1’移入输出移位寄存器的第9位,以后每次移位,左边移入‘0’,当TB8移到输出位时,其左边是一个‘1’和全‘0’。检测到此条件,再进行最后一次移位,/SEND=1,DATA=0,输出停止位,置TI=1。
(2)接收
置REN=1,与方式1类似,接收器以波特率的16倍速率采样RXD端。。。在
起始位0移到输入寄存器的最左边时,进行最后一次移位。在RI=0,SM2=0或接收到的第9位=1时,收到的一字节数据装入SBUF,第9位进入RB8,置RI=1;然后又开始检测RXD端负跳变。
3、多机通信
在这里,多机系统是指‘一主多从’。51系列单片机中,利用第9位TB8/RB8
来区分地址与数据信息,用位SM2确定接收方是否对地址或数据帧敏感。其原则是:
1)发送方用第9位TB8=1标志地址帧,TB8=0标志数据帧。
2)接收方若设置SM2=1,则只能接收到地址信息,若设SM2=0,则不管是地址还是数据帧,都能接收到。
利用方式2、3的特点,在点对点的通讯中,在发送方可以用第9位TB8
作为奇偶校验位。在接收方,SM2位必须清0。
4、波特率
1)方式0的波特率=fosc/12
2)方式2的波特率=2^smod*fosc/64
3)方式1、3的波特率由T1或T2的溢出率和SMOD位确定:
(1)用T1:波特率=2^smod*T1定时器的溢出率/32,T1为方式2
T1定时器溢出率=1/((12/fosc)*(256-X))
例:已知fosc=6MHz,SMOD=0,设置波特率为2400,求T1的计数初值X。
波特率=1/((12/fosc)*(256-X))/32=fosc/12*32(256-X)
(256-X)=fosc/2400/384=6M/2400/384;256-X~=6.5104
X~=250=FAH 只能近似计算。
若fosc=11.0592MHz, 则256-X=11.0592M/2400/384=4068/384=12 X=F4H;可精确算出,对其它常用的标准波特率也是能正确算出。所以这个晶振频率是最常用的。
如果SMOD=1,则同样的X初值得出的波特率加倍。
(3)用T2:
在52型单片机中,串口方式1、3的波特率发生器选择由TCLK、RCLK位
确定是T1还是T2。若TCLK=1,则发送器波特率来自T2,否则来自T1。若RCLK=1,则接收器波特率来自T2,否则来自T1。
由T2产生的波特率与SMOD无关。T2定时的最小单元=2/fosc。T2的溢出脉冲16分频后作为串口的发送或接收脉冲。
波特率=(1/((2/fosc)(65536-X)))/16=fosc/(32(65536-X))
例:已知fosc=11.0592MHz,求波特率=2400时的X
2400=11059200/(32(65536-X)) 65536-X=144 X=65392=FF70H
计数器初值寄存器:RCAP2H=0FFH,RCAP2L=70H。