【51单片机】单片机定时器与串口通信

目录

一、定时器/计数器的结构

二、利用中断发出1Khz的方波信号,驱动蜂鸣器鸣叫。

三、LED数码管秒表的制作。

四、使用定时器实现一个LCD显示时钟。

五、两个单片机的串口通信

六、单片机与笔记本电脑串口通信


一、定时器/计数器的结构

        AT89S51定时器/计数器结构见图 7-1,定时器/计数器T0由特殊功能寄存器TH0、TL0构成,T1由特殊功能寄存器TH1、TL1构成。

图1   定时器/计数器结构框图 

        T0、T1都有定时器和计数器两种工作模式,两种模式实质都是对脉冲信号进行计数,只不过计数信号来源不同。计数器模式是对加在T0(P3.4)和T1(P3.5)两个引脚上的外部脉冲进行计数(见图7-1);定时器模式是对系统时钟信号经12分频后的内部脉冲信号(机器周期)计数。由于系统时钟频率是定值,可根据计数值计算出定时时间。两个定时器/计数器属于增1计数器,即每计一个脉冲,计数器增1。T0、T1具有4种工作方式(方式0、1、2和3)。图 7-1特殊功能寄存器TMOD用于选择定时器/计数器T0、T1的工作模式和工作方式。特殊功能寄存器TCON用于控制T0、T1的启动和停止计数,同时包含了T0、T1状态。计数器起始计数从初值开始。单片机复位时计数器初值为0,也可给计数器装入1个新的初值。 

二、利用中断发出1Khz的方波信号,驱动蜂鸣器鸣叫。

电路图:

代码:

#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(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
}

Proteus仿真:

三、LED数码管秒表的制作。

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

电路图:

代码:

#include<reg51.h>  			
unsigned char code discode1[]=                                  			{0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};	                            
unsigned char code discode2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};	
unsigned char timer=0;		
unsigned char second;        	
unsigned char key=0;		
 
main()				
{
	 TMOD=0x01;			
	 ET0=1;                   
EA=1;                    		
second=0;                	
P0=discode1[second/10];   	
P2=discode2[second%10];   		
while(1)				
{	
	if((P3&0x80)==0x00)		
	{	 
		key++;			
		switch(key)		
		{
			case 1:		
			TH0=0xee; 	
TL0=0x00;	   
	TR0=1;         	
	break;
	case 2:        	
	TR0=0;         		
	break;
	case 3:        			
	key=0;         			
	second=0;      			
	P0=discode1[second/10];   
	break;
}
while((P3&0x80)==0x00);     	
}
}
void int_T0() interrupt 1  using 0 		
{						
	TR0=0;		 	
	TH0=0xee;	  	
	TL0=0x00;	   	
	timer++;   	   
	if (timer==20)	  
	{
		timer=0;    			
		second++;   			
		P0=discode1[second/10]; 	
        P2=discode2[second%10]; 	
 }
if(second==99) 		
{
	TR0=0;			
	second=0;			
	key=2;	  		
}                           
else				
{
	TR0=1;			
}
}
 

四、使用定时器实现一个LCD显示时钟。

电路设计:

代码:

#include<reg51.h>
#include<lcd1602.h>
#define uchar unsigned char
#define uint unsigned int
uchar int_time;				//定义中断次数计数变量
uchar second;				//秒计数变量
uchar minute;				//分钟计数变量
uchar hour;				//小时计数变量
uchar code date[]="  H.I.T. CHINA  ";	//LCD第1行显示的内容
uchar code time[]=" TIME  23:59:55 ";	//LCD第2行显示的内容
uchar second=55,minute=59,hour=23;
 
void clock_init()
{
	uchar i,j;
	for(i=0;i<16;i++)
	{
		write_data(date[i]);
	}
write_com(0x80+0x40);
for(j=0;j<16;j++)
	{
		write_data(time[j]);
	}
}
 
void clock_write( uint s, uint m, uint h)
{
	write_sfm(0x47,h);
	write_sfm(0x4a,m);
	write_sfm(0x4d,s);
}
 
void main()
{
	init1602();		//LCD初始化
	clock_init();		//时钟初始化
TMOD=0x01;			 //设置定时器T0为方式1定时
EA=1;            			// 总中断开 
ET0=1; 				// 允许T0中断 
TH0=(65536-46483)/256;	//给T0装初值
TL0=(65536-46483)%256;
TR0=1;
int_time=0;			//中断次数、秒、分、时单元清0
second=55;
minute=59;
hour=23;
while(1)
{
	clock_write(second ,minute, hour);
}
}
void  T0_interserve(void)  interrupt 1  using 1 	//T0中断服务子程序
{	
	int_time++;				//中断次数加1
 	if(int_time==20) 			//若中断次数计满20次
 	{ 
		int_time=0; 			//中断次数变量清0
 		second++;			//秒计数变量加 1
 	}
 	if(second==60)			//若计满60s
 	{ 
	second=0; 				//秒计数变量清0
 	minute ++;				//分计数变量加 1
 	}
if(minute==60)			//若计满60分
{ 	
	minute=0;		//分计数变量清0
	hour ++;		//小时计数变量加1
}
if(hour==24)
{ 	
	hour=0;			//小时计数计满24,将小时计数变量清0
}
TH0=(65536-46083)/256;		//定时器T0重新赋值
TL0=(65536-46083)%256;
}

 Proteus仿真:

五、两个单片机的串口通信

(甲乙两个单片机串口通信)在实物实验时,如果不能找到两个普中单片机,用笔记本电脑的串口助手程序代替其中一个单片机,实现课件上描述的主要功能。

电路设计:

甲代码:

#include <reg51.h>
  sbit P=PSW^0;		//P位为PSW寄存器的第0位,即奇偶校验位
  unsigned char Tab[8]= {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf,  
                  0xbf, 0x7f};   //控制流水灯显示数据数组,为全局变量
 
 void main(void) 				//主函数
 {	
  	unsigned char i;
  	TMOD=0x20;				//设置定时器T1为方式2
  	SCON=0xc0;				//设置串口为方式3
  	PCON=0x00;  				//SMOD=0   
TH1=0xfd;				//给T1赋初值,波特率设置为9600
  TL1=0xfd;
  TR1=1;				//启动定时器T1
  while(1)
  {	
  	for(i=0;i<8;i++)
     	{
  		Send(Tab[i]);
       	delay( );		//大约200ms发送一次数据
      }
  }
  }
  
void Send(unsigned char dat)		// 发送1字节数据的函数
  {		
  TB8=P; 				// 将偶校验位作为第9位数据发送
  SBUF=dat;
  while(TI==0); 			//检测TI,TI=0,未发送完
  ;					// 空操作
  TI=0; 				// 1字节发送完,TI清0
  }
void delay (void) 		// 延时约200ms的函数
  {	
  	unsigned char m,n;
  	for(m=0;m<250;m++)
  	for(n=0;n<250;n++);
  } 

 乙代码:

#include <reg51.h>
  sbit P=PSW^0;		// P位为PSW 寄存器的第0位,即奇偶校验位
  
  void main(void) 		//主函数
  {	
  	TMOD=0x20;		//设置定时器T1为方式2
  	SCON=0xd0;		//设置串口为方式3,允许接收REN=1
  	PCON=0x00;  		// SMOD=0  
  	TH1=0xfd;		//给定时器T1赋初值,波特率为9600
  	TL1=0xfd;
  	TR1=1;			//接通定时器T1
  	REN=1; 			//允许接收
while(1)
  {	
  P1= Receive( );			//将接收到的数据送P1口显示
  }
  }
  
    unsigned char Receive(void)		//接收1字节数据的函数
  {	
  unsigned char dat;
  while(RI==0); 		//检测RI,RI=0,未接收完,则循环等待
  ;
  RI=0;			//已接收一帧数据,将RI清0
  ACC=SBUF;			//将接收缓冲器的数据存于ACC
  if(RB8==P) 			//只有偶校验成功才能往下执行,接收数据
  {	
  	dat=ACC;		//将接收缓冲器的数据存于dat
  	return dat;		//将接收的数据返回
  }
  }    

  Proteus仿真:

六、单片机与笔记本电脑串口通信

将单片机串口与笔记本电脑串口模块相连,单片机每隔2秒发送“Hello C51”,笔记本电脑用串口助手软件接收。 如果串口助手发送字符“0" 给单片机,则单片机停止发送; 如果单片机收到“1”,则继续每隔2秒发送“Hello C51”。

代码:

#include <REGX52.H>
#include "stdio.h"
unsigned char ch;
unsigned char Flag=1;
void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
 
	while(xms--)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}
 
void UartInit(void)		
{
	PCON &= 0x7F;		
	SCON = 0x50;		
	TMOD &= 0x0F;		
	TMOD |= 0x20;		
	TL1 = 0xFD;		
	TH1 = 0xFD;		
	ET1 = 0;		
	TR1 = 1;		
	EA=1;
	ES=1;
}
void UartSend()
{
		TI=1;
		puts("Hello C51");
		while(!TI);
		TI=0;
		Delay(2000);
}
 
void main()
{
	UartInit();
	while(1)
	{
		if(Flag==1)UartSend();
	}	
}
 
 
void UART_Routine()	interrupt 4 
{
	if(RI==1)
	{
		RI=0;
		ch=SBUF;
		if(ch=='1')Flag=1;
		if(ch=='0')Flag=0;
	}
}

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
51单片机串口通信与定时器有一定的关系。定时器可以提供精确的时序控制,而在串口通信中,定时器常常被用来生成波特率时钟,即串口通信的时钟信号。通过定时器的计数和溢出,可以实现精确的波特率设定,从而使得串口通信能够按照预定的速率进行数据传输。此外,定时器还可以用来检测接收数据的间隔时间,或者用来生成特定的时序信号,以实现串口通信的各种功能。所以可以说,定时器在51单片机串口通信中扮演着重要的角色。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [51--定时器/计数器,串口,中断的巧妙关系](https://blog.csdn.net/weixin_64473106/article/details/126725789)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [AutoLeaders控制组——51单片机学习笔记(定时器、串口通信)](https://blog.csdn.net/draw_future_TL/article/details/127914528)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值