单片机定时器与串口通信

目录

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

二、LED数码管秒表的制作

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

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

五、单片机串口与笔记本电脑串口模块相连

参考文献


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

Keil源码如图所示:

#include<reg51.h>
sbit sound=P2^5;
#define f1(a) (65536-a)/256
#define f2(a) (65536-a)%256
unsigned int i=500;
unsigned int j=0;
void t1(void) interrupt 3 using 0
{
	TR1=0;
	sound=~sound;
	TH1=f1(i);
	TL1=f2(i);
	j++;
	TR1=1;
}	

void main(void)
{
	EA=1;
	ET1=1;
	TMOD=0X10;
	TH1=f1(i);
	TL1=f2(i);
	TR1=1;
	while(1)
	{
		i=460;
		while(j<2000);
		j=0;
		i=360;
		while(j<2000);
		j=0;
	}	
}

Proteus仿真图如图所示:

Priteus仿真演示如图所示:

二、LED数码管秒表的制作

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

Keil源码如图所示:

#include<reg51.h>
typedef unsigned int uint;	 //定义无符号整形和字符型
typedef unsigned char uchar;

uchar led[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};	//共阳数码管 0 - 9
uchar led1[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; 	//共阳数码管 0 - 9 加小数点
uchar second; //秒数
uchar key; //按键次数
uint t; //用来计数,每500,代表0.1s

sbit keyif = P3^7;	//按键接口
void delay(){ //延时函数,用于消除抖动
	uchar i,j;
	for(i=0;i<255;i++){
		for(j=0;j<100;j++);
	}
}

void init(void) //初始化
{
	TMOD = 0x02;  //0000 0010 使用方式二
	second = 0; //秒数初始化为0
	EA = 1;	 //总中断,定时器0中断允许
	ET0 = 1;  //允许定时器0中断
	key = 0; //按键次数初始化为0
	t = 0; //计数初始化为0
}

void main(){
	init();
	P0 = led1[second/10];
	P2 = led[second%10];
	while(1){
		if(keyif == 0){
			delay();//消除抖动	 
			if(keyif == 0){		  
				key++;
			switch(key){
				   case 1: //按一次,计时器开始
				   		TH0 =  0x38;
						TL0 = 0x38; //200us,也就是0.2ms
						TR0 = 1;			   		
				   		break;
				   case 2:	//按两次,暂停定时器
				   		t = 0; 
				   		TR0 = 0;
				   		break;
				   case 3: //按三次,停止计时,数据清零
				   		key = 0;
						second = 0;
						P0 = led1[0];
						P2 = led[0];
				   		break;
					}
				while(keyif == 0);  //若一直按下,使其停留
				
			}
		}

	}

}

void timer() interrupt 1
{
	TR0 = 0; //停止计时
	t++;
	if(t == 500){
		second++;
		P0 = led1[second/10];
		P2 = led[second%10];
		t = 0;
	}
	if(second == 99){ //当计数到9.9秒,重新开始计时
		second = 0;
		key = 1; //相当于重新开始计时
	}
	TR0 = 1; //继续启动计时器		
	

}

原理图如图所示:

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

Keil源码如图所示:

#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(h);
	write_sfm(m);
	write_sfm(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仿真演示如图所示:

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

甲机发送Keil源码如图所示:

//甲机发送程序
#include <reg51.h>
sbit p=PSW^0;		//P位为PSW寄存器的第0位,即奇偶校验位
unsigned char Tab[8]= {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};	//控制流水灯显示数据数组,为全局变量

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++) ;
}

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发送一次数据
		}
	}
}

乙机接收Keil源码如图所示:

//乙机接收程序
#include <reg51.h>
sbit p=PSW^0;	//P位为PSW寄存器的第0位,即奇偶校验位

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;			//将接收的数据返回
	}
}

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口显示
	}
}

Proteus仿真原理如图所示:

Proteus仿真演示如图所示:

五、单片机串口与笔记本电脑串口模块相连

Keil源码如图所示:

#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uint p=0;					//默认设置状态0
void delay_2s()				//延时函数
{
	int i,j; 
	for(i=0;i<21800;i++)
     {
        for(j=10;j>0;j--);
       }
}
void uart_sendbyte(uchar byte)//发送字符
{
	SBUF=byte;
	while(TI==0);
	TI=0;
}
void helloc51()
{
			uart_sendbyte('h');
			uart_sendbyte('e');
			uart_sendbyte('l');
			uart_sendbyte('l');
			uart_sendbyte('o');
			uart_sendbyte('c');
			uart_sendbyte('5');
			uart_sendbyte('1');
			uart_sendbyte(' ');
}
void uart_init(uchar baud)//uart初始化
{
	TMOD|=0X20;
	SCON=0X50; 
	PCON=0X80; 
	TH1=baud; 
	TL1=baud;
	ES=1;
	EA=1;
	TR1=1;
}
void uart() interrupt 4
{
	if(RI==1)//读取串口发送的信息
{
	uchar rec_data;
	rec_data=SBUF;
	RI=0;
	if(rec_data==0)//发送0,设置为模式0
	{
		p=0;
	}
	else if(rec_data==1)//发送1,设置为模式1
	{
		p=1;
	}
	
}
}
void main()
{
	uart_init(0XFA);
	while(1)
{
	if(p==0)//状态0,不做操作
	{
	while(p==0)
	{
		
	}
	}
	else if(p==1)//状态1,循环输出hello c51并且延时2s
	{
		while(p==1)
		{
			helloc51();
			delay_2s();
		}
	}
}
}

演示如图所示:

参考文献

单片机定时器与串口通信-CSDN博客

51单片机LED数码管秒表制作_一、led 秒表 用 2 位数码管显示计时时间,最小计时单位为“百毫秒”,计时范围 0.1-CSDN博客

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值