单片机定时器和串口通信

提示:以下是本篇文章正文内容,下面案例可供参考

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

1.原理说明

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

先计算T1初值,系统时钟为12MHz,则机器周期为1µs。1kHz音频信号周期为1ms,要定时计数的脉冲数为a。则T1初值:                  

TH1=(65 536 −a) /256;              

TL1=(65 536 −a) %256.

2.protues仿真设计

通过在protues上面运用元器件仿真。

仿真图如下:

3.代码实现 

通过学习PPT上的代码指导的到实现。

代码如下:

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

4.仿真得到结果 

得到效果如下:蜂鸣发声器发出声音:

 

二、LED数码管秒表的制作

1.原理说明

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

用2位数码管显示计时时间,最小计时单位为“百毫秒”,计时范围0.1~9.9s。当第1次按一下计时功能键时,秒表开始计时并显示;第2次按一下计时功能键时,停止计时,将计时的时间值送到数码管显示;如果计时到9.9s,将重新开始从0计时;第3次按一下计时功能键,秒表清0。再次按一下计时功能键,则重复上述计时过程.本秒表应用定时器模式,计时范围0.1~9.9s。此外还涉及如何编写控制LED数码管显示的程序。

2.protues仿真设计

通过在protues上面运用元器件仿真。

仿真图如下:

3.代码实现

通过学习PPT上的代码指导的到实现。

代码如下:

#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;			//向THO写入初值的高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;							//向THO写入初值的高8位
	TL0=0x00;							//向TLO写入初值的低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;			//启动定时器继续计时
	}
}
 

4.仿真得到结果 

得到效果如下:

按一下,数码计时器开始计数:

按第二下数码计时器停止计数:

按三下计时器归零:

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

1.原理说明

最小计时单位是秒,如何获得1s的定时?

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

2.protues仿真设计

通过在protues上面运用元器件仿真。

仿真图如下:

3.代码实现

通过学习PPT上的代码指导的到实现。

代码如下:

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

4.仿真得到结果

得到效果如下:

四、甲乙两个单片机串口通信

1.原理说明

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

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

我们使用了一个虚拟终端来观察甲机串口发出的数据。

2.protues仿真设计

通过在protues上面运用元器件仿真。

仿真图如下:

3.代码实现

通过学习PPT上的代码指导的到实现。

1号机代码如下:

#include <REGX52.H>
sbit T_P=PSW^0;
unsigned char code 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(unsigned char xms)		
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}
 
void main()
{
	unsigned char i;
	TMOD=0x20;
	SCON=0xc0;
	PCON&=0x7f;
	TH1=0xfd;
	TL1=0xfd;
	TR1=1;
	while(1)
	{
		for(i=0;i<8;i++)
		{
			Send(Tab[i]);
			Delay(200);
		}
	}
}

2号代码如下:

#include <reg51.h>

sbit P_flag = PSW ^ 0;

unsigned char Receive(void); // ?????????????

void main(void)
{
    TMOD = 0x20;
    SCON = 0xd0;
    PCON = 0x00;
    TH1 = 0xfd;
    TL1 = 0xfd;
    TR1 = 1;
    REN = 1;
    while (1)
    {
        P1 = Receive();
    }
}

unsigned char Receive(void)
{
    unsigned char dat;
    while (RI == 0)
        ;
    RI = 0;
    ACC = SBUF;
    if (RB8 == P_flag)
    {
        dat = ACC;
        return dat;
    }
		else{
			return 0;
}
		}

 

4.仿真得到结果

得到效果如下:

开始仿真后,8盏LED灯一个接一个逐渐闪烁

如下图:

总结

1.本次实验难点在于按照PPT里面的代码进行编写,可能会出现错误情况,而我们则要将错误更正回来。

2.需要找到一些特定的元器件来完成自己的设计。

3.学习了解本次的串行通信的数据口和串行通信方面的计时器设计。

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值