STC51从入门到精通(汇编)~~~ 第八讲:串行通信技术

蓝咒 提交于 2020-03-06 11:06:43

目录

8.1 80C51单片机串行通信技术的特点

8.2 串行通信基本知识

8.2.1 数据通信

8.2.2 串行通信的传输方式

8.2.3 异步通信和同步通信

8.3 串行接口的组成和特性

8.3.1 串行口的结构

8.3.2 串行口控制器及控制寄存器

8.4  串行通信接口的工作方式

8.4.1 工作方式0

8.4.2 工作方式1

8.4.3 工作方式2和工作方式3

8.5  波特率设计

8.5.1 波特率的计算方法

8.5.2 波特率的产生  

8.6 C语言程序示例


8.1 80C51单片机串行通信技术的特点

  • 80C51单片机具有一个全双工串行通信接口,即能同时进行串行发送和接收。
  • 可以作UART(通用异步接收和发送器)
  • 可以作同步位移寄存器用。
  • 可以实现点对点的单机通信、多机通信和80C51与系统机的单机或多机通信。

8.2 串行通信基本知识

8.2.1 数据通信

通信方式有两种,即并行通信串行通信:

       并行通信是指数据的各位同时进行传送(发送或接收)的通信方式。其优点是传送速度快;缺点是数据有多少位,就需要多少根传送线。

       串行通信指数据是一位一位按顺序传送的通信方式。它的突出优点是只需一对传输线(利用电话线就可作为传送线),这样就大大降低了传送成本,特别适用于远距离通信;其缺点是传送速度较低。

8.2.2 串行通信的传输方式

  • 单工(或单向)配置,只允许数据向一个方向传送
  • 半双工(或半双向)配置,允许数据向两个方向中的任一方向传送,但每次只能有一个发送,一个接收;
  • 全双工(全双向)配置,允许同时双向传送数据,因此,全双工配置是一对单向配置,它要求两端的通信设备都具有完整和独立的发送和接收能力。

8.2.3 异步通信和同步通信

1、异步通信

  • 帧格式:一个字符由四部分组成:起始位、数据位、奇偶校验位和停止位。
  • 起始位(0):占用一位,用来通知接收设备一个待接收的字符开始到达。
  • 数据位58位数据(规定低位在前,高位在后)
  • 奇偶校验位(可省略):也可用来确定一帧中的字符所代表信息的性质(地址/数据等)
  • 停止位(1):停止位用来表征字符的结束。停止位可以是1位、1.5位或2位。接收端收到停止位后,知道上一字符已传送完毕 

2、同步通信

3、波特率

1、波特率的定义每秒钟传送二进制数码的位数(亦称比特数),单位是b/s

2、假设数据传送速率是120字符/s,而每个字符格式包含10个代码(1个起始位、1个终止位、8个数据位)。这时,传送的波特率为

            (10b/字符)×120字符/s = 1200 b/s

8.3 串行接口的组成和特性

8.3.1 串行口的结构

  • 组成:两个物理上独立的串行数据缓冲寄存SBUF、发送控制器、接收控制器、输入移位寄存器和输出控制门。
  • 发送缓冲寄存器SBUF只能,不能读;
  • 接收缓冲寄存器SBUF只能,不能写。
  • 两个缓冲寄存器共用一个地址99H,可以用读/写指令区分。
  • 串行发送时,通过MOV SBUFA写指令,写入发送SBUF(99H),再由TxD一位一位地向外发送;
  • 串行接收时,RxD一位一位地接收数据,直到收到一个完整的字符数据后通知CPU,再通过MOV  ASBUF读指令,CPU从接收SBUF(99H)读出数据,送到累加器A中。

8.3.2 串行口控制器及控制寄存器

1、串行口控制寄存器SCON(98H)

SM0、SM1:串行口工作方式控制位,两位对应四种工作方式,如下表所示(fosc是晶振频率)。

8.4  串行通信接口的工作方式

8.4.1 工作方式0

      SM0 SM1=00时,串行接口选择工作方式0,为同步移位寄存器输入/输出方式常用于扩展I/O口。串行数据通过RXD输入或输出,而TXD用于输出移位时钟,作为外接部件的同步信号。发送或接收的是8位数据(低位在前,高位在后)

8.4.2 工作方式1

  1. 工作方式1SM0 SMl= 01,为可变波特率8位异步通信方式
  2. 发送数据由TXD端输出,接收数据由RXD端输入。
  3. 方式1以10位为一帧传输,设有1个起始位(0)8个数据位和1个停止位(1)。其帧格式起始位(0),8个数据位和1个停止位(1)。

8.4.3 工作方式2和工作方式3

SM1 SM0= 10串行接口选择工作方式2

SM1 SM0= 11串行接口选择工作方式3

方式2或方式3是一个9位的异步串行通信接口TXD为数据发送端,RXD为数据接收端。

方式2波特率固定为fosc/64或fosc/32

方式3波特率由定时器T1或T2 (80C52)的溢出率所确定

方式2和方式3以11位为1帧传输,设有1个起始位(0)8个数据位,1个附加第9位和1个停止位(1)

8.5  波特率设计

8.5.1 波特率的计算方法

1. 方式0波特率

方式0波特率 = fosc 12

若振荡器频率fosc = 12MHz,则波=fosc/12=12MHz/12=1MHz/s,即1μs移位一次。

2. 方式2波特率

方式2波特率 = (2^SMOD/64) × fosc

SMOD0时,波特率等于振荡器频率的1/64SMOD1时,波特率等于振荡器频率的1/32

3. 方式1和方式3的波特率

串行口方式1和方式3的波特率由定时器T1T2(89C52等单片机)的溢出率和SMOD所确定。

8.5.2 波特率的产生  

1. 用定时器T1产生波特率

方式1和方式3波特率 =(2^SMOD/32) ×(T1溢出率)

溢出周期 =12/振荡器频率×(256X)

溢出率为溢出周期的倒数,所以有

波特率 = 2^SMOD ×振荡器频率/[32×12×(256X)]

定时器T1在工作方式2时的初值为

X = 256 - fosc×(SMOD+1)/(384×波特率)

8.6 C语言程序示例

/*******************************************************************************
================================================================================
【平    台】STC89C51_sumjess平台
【编    写】sumjess
【E-mail  】1371129880@qq.com
【软件版本】V2.0
【最后更新】2019年06月10日
【相关信息参考下列地址】
【网    站】
           https://blog.csdn.net/qq_38351824
           http://www.51hei.com/bbs/mcu-2-1.html
---------------------------------------------------------------------------------
【dev.env.】MDK4.02及以上版本
【Target  】STC89C51
第一次修订:2019/05/09
第二次修订:2019/05/21
第三次修订:2019/06/10
【problem 】
    (1)库内补充的不全面;
    (2)库内解释部分不全面;
    (3)库内还存在一定的bug;
【direction】
      下一步的目标就是把库继续集成!
【explain 】
      为了方便使用,我也自己写了很多的库,和优化了算法和表示方式!
【warning】
      目前程序中暂无错误 !   
---------------------------------------------------------------------------------
没有完美的代码,只有不断的奉献,大家一起努力;
赠人玫瑰手留余香,欢迎大家反馈bug!
================================================================================
********************************************************************************/
#include <reg52.h>		//编译器自带的库用 < >	 编译器包含C52的定义
#include "UART_Sum.h"
//////////////////////////////////////////////////
//STC51只有一个串口 RXD---P3.0   TXD---P3.1
//////////////////////////////////////////////////
/*以下为四种波特率的计算公式:
//
//方式0的波特率 = f(osc)/12
//方式1的波特率 = 2^(SMOD)/32 x (T1溢出率)
//方式2的波特率 = 2^(SMOD)/64 x f(osc)
//方式3的波特率 = 2^(SMOD)/32 x (T1溢出率)
//
//式中f(osc)为系统晶振频率,通常为12MHz或11.0592MHz;SMOD是PCON寄存器的最高位- SMOD=0;串口方式1,2,3时,波特率正常。SMOD=1;串口方式1,2,3时,波特率加倍。
//	  T1溢出率即定时器T1溢出的频率-只要算出T1定时器
//每溢出一次所需的时间T,那么T的倒数1/T就是他的溢出率。

//只有定时器2可以减少由于时间上带来的误差,因为方式二可以自动装载 */


//   在在具体操作串行口之前,需要对单片机的一些与串口有关的特殊寄存器做初始化设置,主要是设置产生波特率的定时器1、串行口控制和中断控制,具体步骤如下:
//   一、确定T1的工作方式(编程TMOD寄存器);
//   二、计算T1的初值,装载TH1,TL1;
//   三、启动T1(编程TCON中的TR1位);
//   四、确定串行口工作方式(编程SCON寄存器);
//   五、串行口工作在中断方式时,要进行中断设置(编程IE,IP寄存器)。

//		                              常用波特率初值表									
//									
//波特率	晶振      	 初值		 误差(%)	晶振	      初值		     误差(12MHz晶振)(%)	
//(bps) (MHz) (SMOD=0)	(SMOD=1)			(MHz)(SMOD=0)	(SMOD=1)	(SMOD=0)	(SMOD=1)
//300     11.0592	0xA0	  0X40	     0	      12	 0X98	  0X30	      0.16	      0.16
//600 	  11.0592	0XD0	  0XA0	     0	      12	 0XCC	  0X98	      0.16	      0.16
//1200	  11.0592	0XE8	  0XD0	     0	      12	 0XE6	  0XCC	      0.16	      0.16
//1800	  11.0592	0XF0	  0XE0	     0	      12	 0XEF	  0XDD	      2.12	      -0.79
//2400	  11.0592	0XF4	  0XE8	     0	      12	 0XF3	  0XE6	      0.16	      0.16
//3600	  11.0592	0XF8  	  0XF0	     0	      12	 0XF7	  0XEF	      -3.55	      2.12
//4800	  11.0592	0XFA	  0XF4	     0	      12	 0XF9	  0XF3	      -6.99	      0.16
//7200	  11.0592	0XFC 	  0XF8	     0	      12	 0XFC	  0XF7	      8.51	      -3.55
//9600	  11.0592	0XFD	  0XFA     	 0	      12	 0XFD	  0XF9	      8.51	      -6.99
//14400	  11.0592	0XFE	  0XFC	     0	      12	 0XFE	  0XFC	      8.51	      8.51
//19200	  11.0592	 ——	      0XFD	     0	      12	  ——	  0XFD	      ——	      8.51
//28800	  11.0592	0XFF	  0XFE	     0	      12	 0XFF	  0XFE	      8.51	      8.51

/*
  方式0时,串行口为同步移位寄存器的输入/输出方式,主要用于扩展并行输入或输出口。
  !!!注意!!!串行口工作模式0并不是一个同步串口通信方式,他主要用途是与外面的同步移位寄存器相连。 具体见本篇程序下文件夹的word
  数据由RXD(P3.0)引脚输入或输出,同步移位脉冲由TXD(P3.1)引脚输出。发送和接收均为8位数据,低位在先,高位在后。	
  方式0的波特率 = f(osc)/12					   
*/
void Init_UART_0(void)          //使用方式1  ---  1次中断为5ms,200次为1s
{		
	SCON=0;						//设置T1定时器工作方式2					
	EA=1;						//开总中断
	ES=1;						//开串口中断
	TI=0;
	}
#if 0
/////////////////配合主函数定时使用示例////////////////
////////////////////////输出波形///////////////////////
void main()
{   
    Init_UART_0();
	while(1)
	{
			SBUF=0xaa;	   //发送接收到的数据
			delay(1);
	}
}
void serial() interrupt 4
{
  TI=0;
}
#endif
/*
  方式1的波特率 = 2^(SMOD)/32 x (T1溢出率)
  方式1是10位数据的异步通信口,其中1位起始位,8位数据位,1位停止位。
  TXD(P3.1)为数据发送引脚,RXD(P3.0)为数据接收引脚。
  其传输波特率是可变的,对于51单片机,波特率由定时器1的溢出率决定。
  通常我们在做单片机与单片机串口通信、单片机与计算机串口通信、计算机与计算机串口通信时,基本都选择方式1,因此这种方式大家务必要完全掌握。						   
*/
void Init_UART_1(void)          //使用方式1  ---  1次中断为5ms,200次为1s
{		
	TMOD=0x20;					//设置T1定时器工作方式2
	TH1=0xfd;		        	//T1定时器装初值
	TL1=0xfd;					//T1定时器装初值
	TR1=1;						//启动T1定时器
	REN=1;						//允许串口接收
	SM0=0;						//设定串口工作方式1
	SM1=1;						//设定串口工作方式1
	EA=1;						//开总中断
	ES=1;						//开串口中断
	}
#if 0
//////////////如果不使用可不写中断服务函数/////////////
/////////////////配合主函数定时使用示例////////////////
//////////////////收到什么发什么///////////////////////
uchar b=0,flag=0;
void main()
{   
    Init_UART_1();
	while(1)
	{
		if(flag==1)
		{
			ES=0;	   //发送数据时,关串口中断
			flag=0;	   //清除标志位
			SBUF=b;	   //发送接收到的数据
			while(!TI);//直到发送完毕,发送结束TI为1
			TI=0;	   //置0,准备下一次发送
			ES=1;	   //开启串口中断
		}
	}
}
void serial() interrupt 4
{
	b=SBUF;				//赋值,读取接收到的数据
	flag=1;				//写入标志位
	RI=0;				//置0等待下次中断
}

#endif

/*
方式2,3都为11位数据的异步通信口。
TXD(P3.1)为数据发送引脚,RXD(P3.0)为数据接收引脚。
这两种方式下,起始位1位,数据9位(含1位附加的第9位,发送时为SCON中的TBS,接收时为RBS),停止位1位,一帧数据为11位。
方式2的波特率固定为晶振频率的1/64或1/32,方式3的波特率由定时器Tl的溢出率决定。
方式2和方式3的差别仅在于波特率的选取方式不同,在两种方式下,接收到的停止位与SBUF,RBS及RI都无关。
方式2的波特率 = 2^(SMOD)/64 x f(osc)
*/
void Init_UART_2(void)          //使用方式2  --- 具体情况时,需修改
{	
       SCON = 0x50;   //REN=1允许串行接受状态,串口工作模式2  (1010 0000)   SM0 SM1 SM2 REN   
       TMOD|= 0x20;   //定时器工作方式2                      
       PCON|= 0x80;   //波特率提高一倍                                                   
       TH1 = 0xF4;    //波特率2400、数据位8、停止位1。效验位无 (12M)
       TL1 = 0xF4;	  //因为 PCON|= 0x80; 波特率提高一倍为4800
       TR1 = 1;       //开启定时器1                                                     
       ES  = 0;       //开串口中断                 
       EA  = 0;       // 开总中断
	}
#if	 0
void main()
{   
    Init_UART_2();
	while(1)
	{
			SBUF=0x01;	   //发送接收到的数据
			delay(1);
	}
}
void serial() interrupt 4
{
  TI=0;
}
#endif
/*
方式2,3都为11位数据的异步通信口。
TXD(P3.1)为数据发送引脚,RXD(P3.0)为数据接收引脚。
这两种方式下,起始位1位,数据9位(含1位附加的第9位,发送时为SCON中的TBS,接收时为RBS),停止位1位,一帧数据为11位。
方式2的波特率固定为晶振频率的1/64或1/32,方式3的波特率由定时器Tl的溢出率决定。
方式2和方式3的差别仅在于波特率的选取方式不同,在两种方式下,接收到的停止位与SBUF,RBS及RI都无关。
方式2的波特率 = 2^(SMOD)/64 x f(osc)
*/
void Init_UART_3(void)          //使用方式3  ---  具体情况时,需修改
{	
    TMOD = 0x20;      // 定时器1  方式 2
	SM0=1;			  // 设定串口工作方式3
	SM1=1;			  // 设定串口工作方式3
    TH1   = 0XFD;     // 定时器1初值
    TL1   = 0XFD;     // 定时器1初值
	EA=1;			  // 开总中断
    ES    = 1;        // 串口中断
    TR1   = 1;        // 开启定时器1	
	TI=0;			  //置0,准备下一次发送
	}
#if 0
void main()
{   
    Init_UART_3();
	while(1)
	{
			SBUF=0xaa;	   //发送接收到的数据
			delay(1);
	}
}
void serial() interrupt 4
{
  TI=0;
}
#endif

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!