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

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

一、实验目的

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从右向左形成流水灯的效果,

在这里插入图片描述

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

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

在这里插入图片描述
用if语句判断K3和K4是否按下,哪一个按下便执行对应的代码块
代码实现如下:

#include <stdio.h>
#include <reg52.h>
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开发板原理图

在这里插入图片描述

74HC573数码管控制驱动电路

在这里插入图片描述

74LS138八选一选择器原理图

可作Proteus仿真图如下:

在这里插入图片描述

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

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

#include <stdio.h>
#include <intrins.h>
#include <reg52.h>
#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;

在这里插入图片描述

#include <stdio.h>
#include <reg52.h>
#include <intrins.h>
#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;
		}
	}					
}

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

  • 18
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是一个简单的Arduino四位数按键数码管计数器的代码示例: ``` #include <SevSeg.h> SevSeg sevseg; // 创建SevSeg对象 int counter = 0; // 计数器初始值为0 void setup() { byte numDigits = 4; // 数码管位数为4 byte digitPins[] = {2, 3, 4, 5}; // 数码管连接到Arduino的引脚 byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; // 数码管段连接到Arduino的引脚 bool resistorsOnSegments = false; // 数码管段是否需要电阻 bool updateWithDelays = false; // 是否使用延迟更新数码管 byte hardwareConfig = COMMON_CATHODE; // 数码管类型为共阴极 bool leadingZeros = false; // 是否显示前导零 bool disableDecPoint = true; // 是否禁用小数点 sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint); sevseg.setBrightness(90); // 数码管亮度为90 } void loop() { if (digitalRead(14) == HIGH) { // 当第一个按键按下 delay(50); // 延迟去抖动 if (digitalRead(14) == HIGH) { // 再次确认按键是否按下 counter++; // 计数器加1 if (counter > 9999) { // 如果计数器超出范围 counter = 0; // 重置计数器为0 } } } sevseg.setNumber(counter, 0); // 显示计数器数值 sevseg.refreshDisplay(); // 更新显示 } ``` 在上述代码中,我们使用了SevSeg库来控制数码管的显示。其中,数字位连接到Arduino的引脚2、3、4和5,数码管段连接到Arduino的引脚6、7、8、9、10、11、12和13。第一个按键连接到Arduino的引脚14。 在setup函数中,我们初始化了SevSeg对象并设置了数码管的一些参数,如亮度、位数、类型等。 在loop函数中,我们通过读取第一个按键的状态来控制计数器的增加,如果计数器超过了9999,则重置为0。然后通过setNumber函数将计数器的值显示在数码管上,并通过refreshDisplay函数更新显示。 这是一个简单的四位数按键数码管计数器的示例代码,你可以根据需要进行修改和完善。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值