【51单片机】(手把手教你)串口通信-基础篇

通信方式


并行

适合短距离通信,并行通信控制简单、相对传输速度快(8位一起传输)。

【51单片机】(手把手教你)串口通信-基础篇_第1张图片


串行

只能一位一位的传送。

【51单片机】(手把手教你)串口通信-基础篇_第2张图片


同步(了解)

建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙。

发送方对接收方的同步可以通过外同步和自同步


异步

以字符(构成的帧)为单位进行传输。数据位从低到高传送。

格式:

【51单片机】(手把手教你)串口通信-基础篇_第3张图片

这里的空闲时间是任意的。


串行通信的制式(传输方向)


单工(仅能沿一个方向)

【51单片机】(手把手教你)串口通信-基础篇_第4张图片


半双工(可进行双向,但需分时)

【51单片机】(手把手教你)串口通信-基础篇_第5张图片


全双工

【51单片机】(手把手教你)串口通信-基础篇_第6张图片



串行通信的错误校验


奇偶校验

在发送数据时,数据位尾随的1位为奇偶校验位(1/0)。奇校验时,数据中1的个数与检验位1的个数之和应为奇数;偶校验时,数据中1的个数与校验位1的个数之和应为偶数。接收字符时,对1的个数进行校验,若字符不一致,则说明传输数据过程中出现错误。


代码和校验

发送方将所发数据块求和(或各字节异或),产生一个字节的校验字符(校验和)附加到数据块末尾。接收方接收数据时,同时对数据块(除校验字节外)求和(或各字节异或),将所得的结果与发送方的“校验和”进行比较,一致则无差。


循环冗余校验

通过某种数学预算实现有效信息与校验位之间的循环校验,常用语对磁盘信息的传输、存储区的完整性校验。



串口的基本结构

【51单片机】(手把手教你)串口通信-基础篇_第7张图片

SBUF:51单片机中的特殊寄存器,串行数据缓冲器(一个接收一个发送),两个其实是共用的一个地址99H,但是两个在物理上面是分开的。
发送使用时,就采用SBUF=XXX;  (XXX为需要传送的数据)
接收使用时,采用XXX=SBUF;
记得因为是串行的所以传输都是一位一位进行的。
T1溢出率:T1计时器的溢出频率(就是计时器每次低位计满向高位进位时间的倒数)
用处:用于计算波特率(每秒传输二进制代码的位数)

实现单片机与电脑之间的互相传送字符串通信


工具:STC-ISP


代码:

#include 
#include               //printf头文件
#define uc unsigned char 
#define uint unsigned int

uc flag,i,flag_t,s[50]="",j=0,flag_n=0;
uc code table[]="I get ";        

void init()
{
	TMOD=0x20;	  //定时器工作方式,选择了定时器1,工作方式2 八位初值自动重装的8位定时器。		 
	TH1=0xfd;	  //定时器1初值	,设置波特率为9600 晶振11.0529MHZ?
	TL1=0xfd;
	TR1=1;		  //开启定时器1

	SM0=0;
	SM1=1;		  //10位异步接收,(8位数据)波特率可变
    REN=1;		  //允许串行口接收位
	EA=1;	      //允许中断(总闸)
	ES=1;		  //允许串口中断
}
void main()
{
	init();
	while(1)
{
	  if(flag==1)
	{	  if(flag_n!=0)		   //使第二个及以后I get xx 换行,不与You transfer在一行(单纯为了格式好看)
			{TI=1;
			printf("\n");
			while(!TI);
			TI=0;
			}
		for(i=0;i<6;i++)
		{
			SBUF=table[i];
			while(!TI);
			TI=0;
		}
			for(i=0;s[i]!='#'&&i<50;i++)
		{
			SBUF=s[i];
			while(!TI);
			TI=0;
		}
		flag=0;
	}
	if(flag_t==1)						   //发送完毕之后,在电脑端输出。
	{
		TI=1;							   //printf之前必须将T1置为1才行。
		printf ("\nYou transfer %s",s);
		while(!TI);
		TI=0;
		flag_t=0;
	}	
}
}

void ser() interrupt 4
{
		if(RI)		 //接收数据,手动将RI清0
	{	    
		RI=0;
		
		if(flag==0&&j!=0)//1.循环赋值为'\0'(字符串结尾标志符),j=0,为了第二次传递字符串是又是从头输出
		{			 //2.flag为0和j不为0时,保证是第二次及以后,传输字符串(控制输出格式)
			flag_n++;			 
			for(j=0;s[j]!='#'&&j<50;j++)
				  s[j]='\0';
				  j=0;
		}
		s[j]=SBUF;
		flag=1;
		if(s[j]=='#'||j==49)	 //以'#'作为传送字符串的结尾符,我定义的字符数组最长为50所以49也应该结束。
			flag_t=1;
		else
		 	j++;
	}

	if(TI)     //发送数据
	{
	}	 
}



运行截图:

【51单片机】(手把手教你)串口通信-基础篇_第8张图片


代码解读:基本上就是几个模块:计时器、中断以及串口通信

中断

寄存器介绍

IE(interrupt enable):(可位寻址)设定各个中断源的打开和关闭【51单片机】(手把手教你)串口通信-基础篇_第9张图片
IP(interrupt prior)中断优先级寄存器:(可位寻址)用来设定各个中断源属于两级中断中的哪一级【51单片机】(手把手教你)串口通信-基础篇_第10张图片

中断源:


【51单片机】(手把手教你)串口通信-基础篇_第11张图片

中断响应条件:

1.中断源有中断请求
2.此中断源的中断允许位为1
3.CPU开中断(EA=1)

代码书写:

1.先开总中断EA
2
.然后再开特定的中断去控制
3.如果有特殊需要优先级问题再设置IP
4.中断函数书写
格式
void 函数名() interrupt 中断号(上面图示的序号)
//中断函数返回值一定是void  
//函数名随便写
//中断号用来判断是哪个中断源


计时器

寄存器介绍

TCON 支持位寻址 :控制寄存器,控制T1、T0的启动和停止及设置溢出标志

【51单片机】(手把手教你)串口通信-基础篇_第12张图片


TMOD,不支持位寻址:定时/计数器的工作方式寄存器,确定工作方式和功能

【51单片机】(手把手教你)串口通信-基础篇_第13张图片


【51单片机】(手把手教你)串口通信-基础篇_第14张图片


计时器代码书写步骤:

1.EA=1;

2.ETX=1;                            //开启计时器X中断

3.配置工作方式  TMOD=0x..; //根据自己需求按照上表来配     

3.配置计时器初值

//THX=(65535-N)/256;
//TLX=(65535-N)%256;    
//N由你要计时的时长决定。计时器计一个数花费一个时钟周期来计算。

4.TRX=1;                           //开启计时器X


串口通信

寄存器介绍

PCON电源管理寄存器 :(不可位寻址)

用来管理单片机的电源部分,包括上电复位检测、掉电模式

、空闲模式等


【51单片机】(手把手教你)串口通信-基础篇_第15张图片

【51单片机】(手把手教你)串口通信-基础篇_第16张图片


SCON:(可位寻址)用以设定串行口的工作方式、接收/发送控制以及设置状态标志




【51单片机】(手把手教你)串口通信-基础篇_第17张图片


波特率计算

【51单片机】(手把手教你)串口通信-基础篇_第18张图片


SMOD就是PCON中的第一位,默认为0
fosc为晶振频率,所以自己设定不同波特率时,也要考虑晶振不同的问题。


代码书写

1.上面都书写完毕之后
2.还需要ES=1
3.传输数据时,SBUF=XX
   接收数据时,XX=SBUF
4.中断函数书写 
一定要将RI清0,但是TI的清0在主函数中进行
//因为TI在中断中进行,(1)没有if(TI)的判断,那么就会和RI的处理混淆(2)如果有TI判断
//那么有可能永远进行不了传输数据,因为最开始TI是为0的,无法进入TI条件,就无传
//输数据(SBUF=XX)。而且在传输数据的时候会又一次进入中断,就是还没处理中
//断就又进入了另外一个中断,导致通信出现异常。


相信有了这些模块的讲解之后加上代码的注释应该都懂了~
如果有任何问题和不懂的都可以提出~

你可能感兴趣的:(--51单片机)