51单片机——实验6:串行口

一、实验任务

1.用中断方式串口循环发送学号到PC并用串口助手显示;

2.串口接收PC发送数据(0-F)并发回PC,同时用单个数码管显示接收到的数据。

二、实验目的及原理

1.实验目的:掌握串行口接收、发送数据的原理及编程方法,掌握定时器产生波特率的原理,掌握串行中断服务程序。

2.实验原理:串行通信通过将数据存储在SBUF,再进一步进行发送与接收。发送、接收的速率由波特率控制,其值由定时器产生。当发送、接收完后发送、接收标志位会置1,传输停止,执行串行中断程序,将发送、接收标志位置0,方便下次传输。

三、实验中使用的仪器与材料

Keil、PZ-ISP、普中科技51单片机、串行口、定时器

四、实验方案、步骤及原始记录(数据、图表、计算等)

1.任务一:用中断方式串口循环发送学号到PC并用串口助手显示

(1)用keil编写程序,输出.hex文件

/*-----------------------------------------------
功能:	连接串口到电脑,下载该程序,打开电源
        打开串口调试助手,将波特率设置为9600,无奇偶校验
        晶振12MHz,发送和接收使用的格式相同,如都使用
        字符型格式,设置正确后接受框可以显示出:
		The UART test, 请在发送区输入信息
------------------------------------------------*/
 
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义                        
 
/*------------------------------------------------
                   函数声明
------------------------------------------------*/
void SendStr(unsigned char *s);
 
/*------------------------------------------------
                    串口初始化
------------------------------------------------*/
void InitUART  (void)
{
 
    SCON  = 0x50;	 // SCON:设定工作方式1, 8-bit, 打开REN(允许串行接收位) 
    TMOD = 0x20;  // TMOD:设定定时器中断方式2, 8-bit 自动重装初值
    
	  //定时器T1产生波特率
		TH1=0xfa; //存放备用初值,自动重装给TL1
	  TL1=0xfa;	//定时器初值-----11.0592MHZ晶振+4800波特率-->对应应装初值
	
	  EA = 1; //打开总中断
    ET1=0; // 关闭定时器中断,因为其优先级比串行高,且实际不需要它
	
	  TR1=1; // TR1:启动定时器                       
    // ES = 1;  //这里暂不打开串行发送中断的原因是,一般在发送数据是不会
                //对数据进行处理的,不需要中断
}                            
/*------------------------------------------------
                    主函数
------------------------------------------------*/
void main (void)	
{
    int i,j;
    InitUART();
    while(1) //循环发送
    {
			SendStr("2022210491 ");
      for(i=0;i<200;i++) //延时
	      for(j=0;j<300;j++);
    }
 
    ES = 1;                  //打开串口中断
    while (1)                       
    {}
}
/*------------------------------------------------
                    发送一个字节
------------------------------------------------*/
void SendByte(unsigned char dat)
{
    SBUF = dat; //将数据写入发送缓冲器SBUF
    while(!TI); //TI=1,数据发完,触发中断
    TI = 0; //恢复其值,为下一次发送做准备
}
/*------------------------------------------------
                    发送一个字符串
------------------------------------------------*/
void SendStr(unsigned char *s)
{
	  //循环将字符串里的数字一个个发出来
    while(*s!='\0')// \0 表示字符串结束标志,通过检测是否字符串末尾
    {
      SendByte(*s);
      s++;
    }
}
/*------------------------------------------------
                     串口中断程序
------------------------------------------------*/
void UART_SER (void) interrupt 4 //串行中断服务程序
{
    unsigned char Temp;          //定义临时变量 
   
    if(RI)                        //判断是接收中断产生
     {
	     RI=0;                      //标志位清零
	     Temp=SBUF;                 //读入缓冲区的值
	     P1=Temp;                   //把值输出到P1口,用于观察
       SBUF=Temp;                 //把接收到的值再发回电脑端
	   }
    if(TI)                        //如果是发送标志位,清零
     TI=0;
}

(2)将输出的hex文件烧录到开发板上

2.任务二:串口接收PC发送数据(0-F)并发回PC,同时用单个数码管显示接收到的数据

(1)用keil编写程序,输出.hex文件

#include<reg52.h> 
#define uchar unsigned char // 定义无符号字符类型
uchar Char; // 定义字符变量Char
uchar flag; // 定义标志位变量flag

// UART初始化函数
void UART_Init()
{
	SCON=0x50; // 设置串口工作方式1 ,8-bit, 打开REN(允许串行接收位)
	//PCON=0; // 设置波特率
	TMOD=0x20; // 设置定时器工作方式2, 8-bit 自动重装初值
	TL1=0xfa; // 设置定时器初值-----11.0592MHZ晶振+4800波特率-->对应应装初值
	TH1=0xfa;//存放备用初值,自动重装给TL1
	ET1=0; // 关闭定时器中断
	ES=1; // 开启串口中断
	EA=1; // 开启总中断
	TR1=1; // 启动定时器
}

// UART发送一个字节函数
void UART_sendbyte(uchar Byte)
{
	SBUF=Byte; // 将数据写入串口缓冲区
	while(TI==0); // 等待发送完成
	TI=0; // 清除发送标志位
}

// 主函数
void main()
{
	uchar Code[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,
	                0x7c,0x39,0x5e,0x79,0x71}; // 定义数码管显示编码数组
	uchar i=0; // 定义计数器变量i
	UART_Init(); // 调用UART初始化函数
	P2=0xe3; // 选择数码管以输出值
	while(1) // 无限循环
	{
		if('0'<=Char&&Char<='9'&&flag==1) // 如果接收到的数字在0-9之间且标志位为1
		{
			i=Char-'0'; // 计算数字对应的编码索引
			UART_sendbyte(Char); // 发送接收到的数字
			P0=Code[i]; // 控制数码管显示对应的编码
			flag=0; // 清空标志位
		}
		if('a'<=Char&&Char<='f'&&flag==1) // 如果接收到的小写字母在a-f之间且标志位为1
		{
			i=Char-'a'+10; // 计算字母对应的编码索引
			UART_sendbyte(Char); // 发送接收到的字母
			P0=Code[i]; // 控制数码管显示对应的编码
			flag=0; // 清空标志位
		}
	}
}

// UART接收中断服务函数
void UART_R() interrupt 4
{
	if(RI==1) // 如果接收到数据
	{
		Char=SBUF; // 读取接收到的数据到Char变量
		RI=0; // 清除接收标志位
		flag=1; // 设置标志位为1,表示接收到数据
	}
}

(2)将输出的hex文件烧录到开发板上

五、实验结果及分析、实验过程中遇到问题及处理过程说明

1.任务一结果

2.任务二结果

3.遇到的问题及解决方法

在任务一时打开了定时中断,接收不到信息,分析原因后是因为定时器的中断优先级比串行高,且无需定时器中断,这里仅用定时器来产生波特率。

六、实验总结及心得体会

通过理论与实践相结合,我进一步理解了串行口的结构、工作方式,还有串行口进行数据的发送与接收的原理及编程逻辑。在使用多个中断时注意中断优先级。

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值