单片机与 PC 机串口通信实验

实验原理
51 单片机的串行口是一个可编程的全双工的通信接口,具有 UART(通用异步收发器)的全部功能,能同时进行数据的发送和接收,也可以作为同步移位寄存器使用。51 单片机的串行口主要有两个独立的串行数据缓冲寄存器 SBUF(一个发送缓冲寄存器,一个接收缓冲寄存器)和发送控制器、接收控制器、输入移位寄存器及若干控制们电路组成。串行口方式 1 是最常用的通信方式,传输的数据共 10 位,1 位起始位,8 位数据位,最低位在前,高位在后,1 位停止位,帧与帧之间可以有空闲,也可以无空闲。
发送方式:当数据被写入 SBUF 寄存器后,单片机自动开始从起始位发送数据,发送到停止位的开始时,有内部硬件将 TI 置 1,向 CPU 申请中断,接下来可在中断程序中做相应处理,也可以选择不进入中断。
接收方式:用软件置 REN 为 1 时,接收器以选择波特率的 16 倍速率采样 RXD 引脚电平,检测到 RXD 引脚输入电平发生负跳变时则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入一位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位,当 RI=0;且 SM2=0(或接收到的停止位为 1)时,将接收到的 9 位数据的前 8 位数据装入接收 SBUF,第 9 位(停止位)进入 RB9,并置 RI=1,向 CPU 请求中断。
在具体操作串行口之前,需要对单片机的一些与串口有关的特殊功能寄存器进行初始化设置,主要设置产生波特率的定时器 1,、串行口控制和中断控制,具体步骤如下:
○1 确定 T1 的工作方式(编程 TMOD 寄存器);
○2 计算 TI 的初值,装载 TH1,TL1;
○3 确定串行口工作方式(编程 SCON 寄存器);
○4 串行口工作在中断方式,要进行中断设置,(编程 IE,IP 寄存器);

相关寄存器的选择说明

单片机与 PC 机串口通信实验_第1张图片
单片机与 PC 机串口通信实验_第2张图片
单片机与 PC 机串口通信实验_第3张图片

实验代码如下

#include 
#define uchar unsigned char
#define uint unsigned int
uchar num,a;//定义变量
/*
****************************************************************************
** 函数名称 : main(void)
** 函数功能 : 主函数
*****************************************************************************/
void main()
{
	TMOD=0x20; //用来定时器设置
	TH1=0xfd; //设置初值 9600=(2 的 SMOD 次方/32)*(TI 溢出率)=(1/32)
//*11059200/(256-X)*12
	TL1=0xfd;
	TR1=1; //开启定时器 1
	SM0=0; //设置串行口工作方式
	SM1=1;
	REN=1; //允许串行接收位
	EA=1; //开启总中断
	ES=1; //开启串口中断
while(1)
{
	if(num==1) //判断是否有串口数据的传送
	{
		ES=0; //关闭串口中断
		num=0;
		SBUF=a; //发送数据 a 到 SBUF,即将单片机的数据发送到计算机
		while(!TI); //发送数据后,TI 自动置 1
		TI=0; //TI 置 0,才能进行下次发送
		ES=1; //打开中断
	}
}
}
void ser() interrupt 4
{
	RI=0; //接收到数据后,将 RI 置 0
	a=SBUF; //接收数据
	num=1; //标志位
}

为了方便以后复习,写得详细一点,以下是引用.

串口的6个特征如下。
(1)、物理上的连线至少3根,分别是Tx数据发送线,Rx数据接收线,GND共用地线。
(2)、0与1的约定。RS232电平,约定﹣5V至﹣25V之间的电压信号为1,﹢5V至﹢25V之间的电压信号为0 。TTL电平,约定5V的电压信号为1,0V电压信号为0 。CMOS电平,约定3.3V的电压信号为1,0V电压信号为0 。其中,CMOS电平一般用于ARM芯片中。
(3)、发送秩序。低位先发。
(4)、波特率。收发双方共同约定的一个数据位(0或1)在数据传输线上维持的时间。也可理解为每秒可以传输的位数。常用的波特率有300bit/s, 600bit/s, 2400bit/s, 4800bit/s, 9600bit/s。
(5)、通信的起始信号。发送方在没有发送数据时,应该将Tx置1 。 当需发送时,先将Tx置0,并且保持1位的时间。接受方不断地侦测Rx,如果发现Rx常时间变高后,突然被拉低(置为0),则视为发送方将要发送数据,迅速启动自己的定时器,从而保证了收发双方定时器同步定时。
(6)、停止信号。发送方发送完最后一个有效位时,必须再将Tx保持1位的时间,即为停止位。

注意:

读取SBUF数据或接受SBUF数据都是采用ASCII码,数据类型unsigned char,二进制数据

实验

从串口中输入0-999,数码管显示0-999.

#include 
#define uchar unsigned char 
#define uint unsigned int 
sbit wela1 = P1^0; //第一位
sbit wela2 = P1^1; //第二位
sbit wela3 = P1^2; //第三位	   
unsigned int  a; 
uchar num,ge,shi,bai;

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
 0x07,0x7f,0x6f};//不带小数点的共阴数码管段值0-9。
uchar code tablewe[]={0x04,0x02,0x01};

uchar table1[2];
uchar k=0;
void delay(uchar x)//延时
{
	uchar i,j; 
	for(j=x;j>0;j--)
	{
		for(i=113;i>0;i--){}
	}
}
void main(void)
{          
	TMOD=0x20;  	   //用定时器设置串口波特率    9600  
 	TH1=0xfd; 	 	   //赋初值  9600=(2 的 SMOD 次方/32)*(TI 的溢出率)=(1/32)*11059200/(256-X)*12 x=253 
 	TL1=0xfd; 	 	   //赋初值 
 	TR1=1;  	 	   //开启定时器 1 
 	SM0=0;  	 	   //模式选择  	
	SM1=1; 
 	REN=1;             //串口初始化 
 	EA=1;              //开启总中断 
 	ES=1; 	 	 	   //开启串口中断 
	P1=0x00;
	while(1)
	{
 	 	if(num==1)     //判断是否有串口数据的传送 
 	 	{ 
			num=0;
			if (table1[1]==0x00){
				bai=table1[1];
				shi=(table1[0]>>4)&0xf;
				ge=table1[0]&0xf;
				//if((table1[0]>>4)&0xf==0x00)出错
			}else{
				bai=(table1[0]>>4)&0xf;
				shi= table1[0]&0xf;
				ge=table1[1];
			}
 	 	}
		if (bai!=0x00){
			P1=0x04;
			P0=table[bai];
			delay(5);		
		}
		if (shi!=0x00){
			P1=0x02;
			P0=table[shi];
			delay(5);	
		}
		P1=0x01;
		P0=table[ge];
		delay(5);
	}  
}
void ser() interrupt 4 	 	 //串口中断号 4 
{ 
	table1[0]=0;
	table1[1]=0;//清零
	if(RI)
	{
		for(k=0;k<2;k++)
		{
			
			while(!RI); //查询接收标志
			RI=0;
			table1[k]=SBUF;//一次读8位
			delay(10);
			if (RI==0)	break;	//表示只发一位 
		}
	
	}	 
    num=1;//表示有接收
} 

你可能感兴趣的:(个人)