实验报告:单片机定时器与串口通信

本文详细介绍了如何使用51单片机通过定时器控制蜂鸣器产生音频信号,实现LED数码管秒表和LCD时钟功能,以及进行串口通信,旨在通过实际项目提升对相关技术的理解。
摘要由CSDN通过智能技术生成

一、驱动蜂鸣器

1.要求

利用T1的中断控制P1.7引脚输出频率为1kHz方波音频信号,驱动蜂鸣器发声。系统时钟为12MHz方波音频信号周期1ms,因此T1的定时中断时间为0.5 ms,进入中断服务程序后,对P1.7求反。

2.代码

#include<reg51.h>  			//包含头文件
sbit sound=P1^7;  			//将sound位定义为P1.7脚
#define f1(a) (65536-a)/256		//定义装入定时器高8位时间常数
#define f2(a) (65536-a)%256    		//定义装入定时器低8位时间常数
unsigned int i=500; 
unsigned int j=0; 
void main(void)
{
	 	EA=1;                  		//开总中断.
  		ET1=1;                		//允许定时器T1中断         .
   		TMOD=0x10; 			//TMOD=0001 000B,使用T1的方式1定时    	TH1=f1(i);      			//给T1高8位赋初值.
   		TL1=f2(i);      			//给T1低8位赋初值.
   		TR1=1;                 		//启动T1
   		while(1)  
{              				//循环等待
     	i=460; 
      	while(j<2000);
      	j=0;
      	i=360; 
      	while(j<2000);
      	j=0;
    }
 }
 
void T1_ISR(void) interrupt 3 using 0	//定时器T1中断函数
{
    	TR1= 0;                 	//关闭T1
   	sound=~sound; 			//P1.7输出求反
    	TH1=f1(i);   			//T1的高8位重新赋初值.
    	TL1=f2(i);   			//T1的低8位重新赋初值.
j++;				
    	TR1=1;                 	//启动定时器T1
}

3.结果

二、LED数码管秒表的制作

1.要求

用2位数码管显示计时时间,最小计时单位为“百毫秒”,计时范围0.1~9.9s。当第1次按一下计时功能键时,秒表开始计时并显示;第2次按一下计时功能键时,停止计时,将计时的时间值送到数码管显示;如果计时到9.9s,将重新开始从0计时;第3次按一下计时功能键,秒表清0。再次按一下计时功能键,则重复上述计时过程。

2.代码

#include<reg51.h>  			//头文件
unsigned char code discode1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};	
                             	//数码管显示0~9的段码表, 带小数点
unsigned char code discode2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};	
                            	//数码管显示0~9的段码表,不带小数点
unsigned char timer=0;		//timer记录中断次数
unsigned char second;        	//second储存秒
unsigned char key=0;		//key记录按键次数
 
main()				//主函数
{
	 TMOD=0x01;			//定时器T0方式1定时
	 ET0=1;                   	//允许定时器T0中断
EA=1;                    		//总中断允许
second=0;                		//设初始值
P0=discode1[second/10];   		//显示秒位0
P2=discode2[second%10];   		//显示0.1s位0
while(1)				 //循环
{	
	if((P3&0x80)==0x00)		//当按键被按下时
	{	 
		key++;			//按键次数加1
		switch(key)		//根据按键次数分三种情况
		{
			case 1:		//第一次按下为启动秒表计时
			TH0=0xee; 	//向TH0写入初值的高8位
TL0=0x00;	   	//向TL0写入初值的低8位,定时5ms
	TR0=1;         		//启动定时器T0
	break;
	case 2:        		//按下两次暂定秒表
	TR0=0;         		//关闭定时器T0
	break;
	case 3:        			//按下3次秒表清0
	key=0;         			//按键次数清
	second=0;      			//秒表清0
	P0=discode1[second/10];   	//显示秒位0   				P2=discode2[second%10];  	//显示0.1s位0
	break;
}
while((P3&0x80)==0x00);     		//如果按键时间过长在此循环
}
}
}
void int_T0() interrupt 1  using 0 		//定时器T0中断函数
{						
	TR0=0;		 	//停止计时,执行以下操作(会带来计时误差)
	TH0=0xee;	  	//向TH0写入初值的高8位
	TL0=0x00;	   	//向TL0写入初值的低8位,定时5ms
	timer++;   	   	//记录中断次数
	if (timer==20)	   	//中断20次,共计时20*5ms=100ms=0.1s
	{
		timer=0;    			//中断次数清0
		second++;   			//加0.1s
		P0=discode1[second/10]; 	//根据计时,即时显示秒位		
    P2=discode2[second%10]; 	//根据计时,即时显示0.1s位	
 }
if(second==99) 		 //当计时到9.9s时
{
	TR0=0;			//停止计时
	second=0;		//秒数清0		
	key=2;	  		//按键数置2,当再次按下按键时,					//key++,即key=3,秒表清0复原	
}                           
else				//计时不到9.9s时
{
	TR0=1;			//启动定时器继续计时
}
}

3.结果

三、LCD时钟

1.实现

将T0定时时间定为50ms,采用中断方式进行溢出次数累计,满20次,则秒计数变量second加1;若秒计满60,则分计数变量minute加1,同时将秒计数变量second清0;若分钟计满60,则小时计数变量hour加1;若小时计数变量满24,则将小时计数变量hour清0。

2.代码

#include"reg51.h"
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
unsigned char s[]={"0123456789"};
unsigned char s1[]={"clock:"};
unsigned char num=0,sec=0,min=25,hour=12;
unsigned char temp0=0,temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;
 
void delay(unsigned int m)
{
	unsigned int i=0,j=0;
	for(i=0;i<m;i++)
	{
		for(j=0;j<120;j++);
	}
}
 
 
void writecom(unsigned char com)
{
	RS=0;
	RW=0;
	E=0	;
	P2=com; 
	delay(5);
	E=1;
	E=0;
}
 
void writedat(unsigned char dat)
{
	RS=1;
	RW=0;
	E=0	;
	P2=dat; 
	delay(5);
	E=1;
	E=0;
}
 
void initlcd()
{
	writecom(0x38);
	writecom(0x0c);
	writecom(0x06);
	writecom(0x01);
}
 
void inittime()
{
	TMOD=0x01;//???0
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	EA=1;
	ET0=1;
	TR0=1;
}
 
void display()
{		
	unsigned int i=0;
	temp0=sec%10;
	temp1=sec/10;
	temp2=min%10;
	temp3=min/10;
	temp4=hour%10;
	temp5=hour/10;
 
	writecom(0x80+0x46); 
	delay(5);
	writedat(s[temp5]);
	delay(5);
	writedat(s[temp4]);
	delay(5);
	writedat(':');
	delay(5);
	writedat(s[temp3]);
	delay(5);
	writedat(s[temp2]);
	delay(5);
	writedat(':');
	delay(5);
	writedat(s[temp1]);
	delay(5);
	writedat(s[temp0]);
	delay(5);
 
 
	writecom(0x80);
	delay(5);
	while(s1[i]!='\0')
	{
		writedat(s1[i]);
		i++;
	}
	
}
 
void main()
{
	initlcd();
	inittime();
	while(1)
	{
		display();
	}
}
 
void inittime_isr() interrupt 1
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	num++;
	if(num==20)
	{
		sec++;
		num=0;
	}
	if(sec==60)
	{
		min++;
		sec=0;
	}
	if(min==60)
	{
		hour++;
		min=0;
	}
	if(hour==24)
	{
		hour=0;
	}
}

四、串口通信

1.要求

甲、乙两单片机进行 方式3(或方式2)串行通信。甲机把控制8个流水灯点亮的数据发送给乙机并点亮其P1口的8个LED。方式3比方式1多了1个可编程位TB8,该位一般作奇偶校验位。乙机接收到的8位二进制数据有可能出错,需进行奇偶校验,其方法是将乙机的RB8和PSW的奇偶校验位P进行比较,如果相同,接收数据;否则拒绝接收。

2.代码

甲机

#include <reg51.h>
  sbit T_P=PSW^0;		
  unsigned char Tab[8]= {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; 
 
void Send(unsigned char dat)	
  {		
  TB8=T_P; 			
  SBUF=dat;
  while(TI==0); 		
  TI=0; 		
  }
 void delay (void) 	
  {	
  	unsigned char m,n;
  	for(m=0;m<250;m++)
  	for(n=0;n<250;n++);
  } 
 
	 void main(void) 				
 {	
  	unsigned char i;
  	TMOD=0x20;				
  	SCON=0xc0;			
  	PCON=0x00;  				  
	TH1=0xfd;				
  TL1=0xfd;
  TR1=1;				
  while(1)
  {	
  	for(i=0;i<8;i++)
     	{
  		Send(Tab[i]);
       	delay( );	
      }
  }
  }


乙机

#include <reg51.h>
  sbit R_P=PSW^0;		
  
    unsigned char Receive(void)	
  {	
  unsigned char dat;
  while(RI==0); 		
  RI=0;			
  ACC=SBUF;			
  if(RB8==R_P) 		
  {	
  	dat=ACC;	
  	return dat;		
  }
  }
	
	  void main(void) 		
  {	
  	TMOD=0x20;	
  	SCON=0xd0;	
  	PCON=0x00;  	
  	TH1=0xfd;		
  	TL1=0xfd;
  	TR1=1;	
    REN=1;		
  while(1)
  {	
  P1= Receive( );		
  }
  }

3.结果

五、总结

通过此次实验学习51单片机驱动蜂鸣器、实现一个LCD显示时钟、LED数码管秒表的制作、串口通信等内容,通过实验案例,加深了我对相关知识的理解。

本博客仅为学习实验报告,多有不足。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值