实验二 独立按键控制数码管显示

仿真图有误还未修改,请自行鉴别
实验二 独立按键控制数码管显示

一、实验目的

1、掌握数码管工作原理

2、掌握独立按键的工作原理

二、实验软硬件

1、Keil uVision4或者Keil uVision5;

2、仿真软件Proteus8,烧录软件stc-isp;

3、普中51开发板;

三、学习内容

1、独立按键的输入原理和编程方法;

2、单片机控制数码管显示的原理,数码管轮流显示同时显示的实现;

3、中断和查询法控制灯的亮灭;

四、实验任务

本次实验需要在proteus上仿真,并烧录到开发板。

任务一:

编写程序,使用独立按键,实现以下功能:

1、按键K3按下,8个LED从左向右形成流水灯的效果,

2、按键K4按下,8个LED从右向左形成流水灯的效果,

任务二:

编写程序,使用中断函数实现以下功能:

1、数码管初始显示值为0。当按键K3按下,使数码管计数,记录按下的次数;

2、 当按键次数达到9时,蜂鸣器报警数码管显示值归0;

**注意:**数码管的驱动方式请查看附带PPT自行设计;

任务三:

编写程序,编写一分钟计时程序,并在数码管显示。使用开发板实现以下功能:

1、使用按键K1 K2 K3,做控制,分别为开始计时、暂停计时、计时清零;

2、开始计时(K1):每次从零开始计时

3、暂停计时(K2):按一次暂停计时,再次按下继续从停止时间计时;

4、计时清零(K3):计时清零,显示00;

任务一

编写程序,使用独立按键,实现以下功能:

1、按键K3按下,8个LED从左向右形成流水灯的效果,

2、按键K4按下,8个LED从右向左形成流水灯的效果,

实验二 独立按键控制数码管显示_第1张图片

由开发板原理图可知K3和K4分别对应单片机P3.2和P3.3单片机

在第一次任务仿真图基础上,稍作修改即可

实验二 独立按键控制数码管显示_第2张图片
用if语句判断K3和K4是否按下,哪一个按下便执行对应的代码块
代码实现如下:

#include 
#include 
typedef unsigned int u16;	 
typedef unsigned char u8;
#define LED P2
/*定义按键控制位*/
sbit K3 = P3^2;
sbit K4 = P3^3;
/*延时函数*/
void delay(unsigned int ms)
{
	u16 i,j;
	for(i=0;i<ms;++i)
		for(j=0;j<110;++j);
}
/*主函数*/
void main()
{
 	u16 i;
    /*左移和右移LED亮灭状态数组*/
	char led_L[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
	char led_R[] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
	while (1)
	{
		if(K3 == 0)
		{
			for(i=0;i<8;i+=1)
			{
				LED = led_L[i];
				delay(500);
			}	
		}
		if(K4 == 0)
		{
			for(i=0;i<8;i+=1)
			{
				LED = led_R[i];
				delay(500);
			}
		}
	}   
}

任务二

编写程序,使用中断函数实现以下功能:

1、数码管初始显示值为0。当按键K3按下,使数码管计数,记录按下的次数;

2、 当按键次数达到9时,蜂鸣器报警数码管显示值归0;

**注意:**数码管的驱动方式请查看附带PPT自行设计;

根据HC6800-ES V2.0开发板原理图

实验二 独立按键控制数码管显示_第3张图片

74HC573数码管控制驱动电路

实验二 独立按键控制数码管显示_第4张图片

74LS138八选一选择器原理图

可作Proteus仿真图如下:

实验二 独立按键控制数码管显示_第5张图片

数码管显示各部分代码实现详见:从零开始玩转C51之02. 数码管-CSDN博客

中断详解暂时还没写,可移步其他博文。

#include 
#include 
#include 
#define SEG P0
/*定义位选控制位*/
sbit A2=P2^4;
sbit A1=P2^3;
sbit A0=P2^2;

sbit K3 = P3^2;
sbit BEEP = P1^5;
typedef unsigned int u16;	 
typedef unsigned char u8;
/*存储段选数据*/
u8 code SEG_DATA[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//共阴0 1 2 3 4 5 6 7 8 9
											0x77,0x7c,0x39,0x5e,0x79,0x71};//A B C D E F
/*定义计数变量*/
static u16 cnt=0;
											
/*延时函数*/
void delay(unsigned int ms)
{
	u16 i,j;
	for(i=0;i<ms;++i)
		for(j=0;j<110;++j);
}
/*设置外部中断0*/
void Int0Init()
{
	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。	
	EA=1;//打开总中断	
}
/*主函数*/
void main()
{
	u16 i,j;
	while (1)
	{
		Int0Init();
		while(1){
			SEG = SEG_DATA[cnt%10];//用取余函数,实现0~9周期显示
			if(cnt%10 ==9)
			{
				do{
					BEEP = ~BEEP;
					delay(1);
				}while(K3);
				if(K3 == 0)
				BEEP = 0;
			}
		}
	}   
}
/*外部中断0的中断函数*/
void Int0()	interrupt 0		
{
	if(K3==0)
	{
		delay(100);//延时消抖,可调节delay时间调整好消抖效果
		if(K3==0)
		{
			cnt++;
		}	
	}
}

任务三

编写程序,编写一分钟计时程序,并在数码管显示。使用开发板实现以下功能:

1、使用按键K1 K2 K3,做控制,分别为开始计时、暂停计时、计时清零;

2、开始计时(K1):每次从零开始计时

3、暂停计时(K2):按一次暂停计时,再次按下继续从停止时间计时;

4、计时清零(K3):计时清零,显示00;

实验二 独立按键控制数码管显示_第6张图片

#include 
#include 
#include 
#define SEG P0
/*定义位选控制位*/
sbit A2=P2^4;
sbit A1=P2^3;
sbit A0=P2^2;
/*定义按键控制位*/
sbit K1 = P3^1;
sbit K2 = P3^0;
sbit K3 = P3^2;
typedef unsigned int u16;	 
typedef unsigned char u8;
/*存储段选数据*/
u8 code SEG_DATA[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//共阴0 1 2 3 4 5 6 7 8 9
											0x77,0x7c,0x39,0x5e,0x79,0x71};//A B C D E F
/*定义计时变量*/
u8 gmsec=0;//毫秒级定义
u8 gsec=0;//秒定义
											
/*延时函数*/
void delay(unsigned int ms)
{
	u16 i,j;
	for(i=0;i<ms;++i)
		for(j=0;j<110;++j);
}
void delay10ms(void)   //用于数码管位选扫描显示
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}
/*定时器0初始化*/
void time0_init(void)
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1
	TH0=0XDC;	//给定时器赋初值,定时10ms
	TL0=0X00;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=0;//关闭定时器		
}
void time0_start(void)
{
	TR0=1;//打开定时器	
}
void time0_stop(void)
{
	TR0=0;//关闭定时器
	TH0=0X00;
	TL0=0X00;	
}
/*简易按键扫描*/
void key_scan()
{
	
	if(K1 == 0)//从零开始计时
	{
		time0_start();
		gsec = 0;
	}
	if(K2 == 0)
	{
		delay(1);//按键消抖
		if(K2 == 0)
		{
			TR0=!TR0;//利用取反运算实现暂停和计时
		}
	}
	if(K3 == 0)
	{
		time0_stop();//计时清零,显示00
		gsec = 0;
	}
}
/*动态显示实现两位数显示*/
void display_smg()
{
	u16 i;
	for(i=0;i<2;i++)
		{
		   switch(i)
			{
				case(0):
					A2=0;A1=0;A0=0;
					SEG = SEG_DATA[gsec%10];//显示个位
					break;
				case(1):
					A2=0;A1=0;A0=1;
					SEG = SEG_DATA[gsec/10];//显示十位
					break;
			}
		   delay10ms();
		}
}
/*主函数*/
void main()
{
	time0_init();
	while(1){
		key_scan();
		display_smg();
	}
}
/*定时器0中断函数*/
void time0() interrupt 1 //定时器0中断函数
{
	TH0=0XDC;	//给定时器赋初值,定时10ms
	TL0=0X00;
	gmsec++;//10ms加1次
	if(gmsec==100)//定时1秒
	{
		gmsec=0;
		gsec++;//对秒计数
		if(gsec == 61)
		{	
			gsec = 0;
		}
	}					
}

虽然代码不是很优雅,但好在能实现功能,等有时间再来优化吧。

你可能感兴趣的:(单片机实验,51单片机,proteus,c语言,经验分享,笔记,嵌入式硬件,单片机)