RYMCU

Nebula Pi 开发板应用(二)—网红10秒挑战器的实现

ii11nnocent 2 年前
# 待分类

这两年比较火的网红 10 秒挑战规则为:挑战者按下开始按钮开始计时,当挑战者认为 10 秒将到时,再次按下按钮计时暂停,数码管上显示当前的计时时间。再次按下按钮,时间清零,重新开始下一次挑战。
利用 Nebula Pi 开发板的按键 KEY1 和数码管可以完成网红 10 秒挑战器的制作,程序如下:

smg.h:

#ifndef _SMG_H
#define _SMG_H

#include "reg52.h"

sbit Duan = P0^6;  //位定义数码管段选
sbit Wei  = P0^7;  //位定义数码管位选

void DigDisplay(unsigned int Time);
void delay(unsigned int i);

#endif

smg.c:

#include "smg.h"

unsigned char i;

unsigned char code smgduan[] = {0x3F,0x06,0x5B,0x4F,
	                 0x66,0x6D,0x7D,0x07,
	                 0x7F,0x6F,0x77,0x7C,
	                 0x39,0x5E,0x79,0x71,0X76};  //数码管0~F、H段码

void delay(unsigned int i)
{
 while(i--);
}

void DigDisplay(unsigned int Time)
{
	for(i=1;i<5;i++)
	  {
	   switch(i)
	   {
	    case(1):
	     P2 = 0xFE; //选中第一个数码管
	     Wei = 1;
	     Wei = 0;  //位锁存
	     P2 = smgduan[Time/1000]; //时间的十位
	     Duan = 1;
	     Duan = 0;
	     break;
	    case(2):
	     P2 = 0xFD; //选中第二个数码管
	     Wei = 1;
	     Wei = 0;  //位锁存
	     P2 = smgduan[Time/100%10] + 0x80; //时间的个位(+0x80是为了加小数点)
	     Duan = 1;
	     Duan = 0;
	     break;
	    case(3):
	     P2 = 0xFB; //选中第二个数码管
	     Wei = 1;
	     Wei = 0;  //位锁存
	     P2 = smgduan[Time/10%10]; //时间的0.1s位
	     Duan = 1;
	     Duan = 0;
	     break;
	    case(4):
	     P2 = 0xF7; //选中第二个数码管
	     Wei = 1;
	     Wei = 0;  //位锁存
	     P2 = smgduan[Time%10]; //时间的0.01s位
	     Duan = 1;
	     Duan = 0;
	     break;  
	   }
	   delay(100);
	   P2 = 0x00;
	   Duan = 1;
	   Duan = 0;   //消影   
	 }
}

KeyState.h:

#ifndef _KEYSTATE_H
#define _KEYSTATE_H

#include "reg52.h"

unsigned char ReadKeyState(void);
void Timer_Init(void);

extern unsigned char Times;						//用于按键按下次数的计算

#endif

KeyState.c:

#include "KeyState.h"

sbit Key1 = P1^0;							//位定义KEY1按键
unsigned char KeyReturn;			//保存按键的返回值
unsigned char Times = 0;								

/****宏定义按键的初始、按下和抬起状态****/
#define Key_State_Init	0
#define Key_State_Down	1
#define Key_State_Up		2

unsigned char ReadKeyState(void)
{
	static char KeyState = 0;			//按键的状态值,初始值为0
	unsigned char KeyPress;				//保存按键的电平值
	KeyPress = Key1;							//保存P1.0口电平
	
	switch( KeyState )
	{
		case Key_State_Init:				//初始状态
			if( !KeyPress )						//读取IO电平
			{
				KeyReturn = 0;					//按键返回值为0
				KeyState = Key_State_Down;	//按键的状态转为按键按下的状态
			}
			break;
		case Key_State_Down:				//初始状态按下后转为按下状态
			if( !KeyPress )						//读取IO电平确认按键是否真的被按下
			{
				KeyReturn = 1;					//按键返回值为1
				Times++;										//每按下一次按键,按键按下次数+1
				KeyState = Key_State_Up;		//按键的状态转为按键释放的状态
			}
			else
			{
				KeyState = Key_State_Init;	//如果IO电平为0,证明按键已抬起,回到初始状态
			}
		case Key_State_Up:					//按下以后转为抬起状态
//			if ( !KeyPress )					//如果按键一直按下,即没有抬起
//			{
//				Times ++;								//只要一直按下按键,Times就会10ms增加1
//				if( Times == 100 )			//Times=100时,1s定时时间到,标志位取反并且Times值清零
//				{
//					Flag	= Flag;
//					Times = 0;
//				}
//			}
			if( KeyPress )						//如果按键抬起了
			{
				KeyReturn = 2;					//按键返回值为2
				KeyState = Key_State_Init;	//读取IO电平,如果是1,证明按键已释放,回到初始状态
			}

	}
	return KeyReturn;
}

void Timer_Init(void)
{
	TMOD	= 0x11;		//定时器0、1均工作在方式1,定时器0用于时间计算,定时器用于按键值的读取
	TH0		= 0xDC;
	TL0		= 0x00;		//定时器0 10ms定时初值
	TH1		= 0xDC;
	TL1		= 0x00;		//定时器1 10ms定时初值
	ET0 	= 1;			//开定时器0中断
	ET1		= 1;			//开定时器1中断
	EA		= 1;			//开总中断
	TR1		= 1;			//打开定时器1
	//TR0		= 1;			//打开定时器0	
}

main.c:

#include "reg52.h"
#include "smg.h"
#include "KeyState.h"

unsigned int time = 0;
unsigned char KeyNumber = 0;	//按键值保存变量

void main(void)
{
	Timer_Init();
	while(1)
	{		
		if( KeyNumber == 1 )							//按下按键开启不同动作
		{
			if( Times == 1 )								//按下一次按键后,开始计时
			{
				TH0 = 0xDC;   								//重新赋初值,防止上次停止时TH0和TL0中存在遗留值
				TL0 = 0x00;  
				TR0 = 1;
			}
			if( Times == 2 )								//按下两次按键后,停止计时
			{
				TR0 = 0;
			}		
			if( Times == 3 )								//按下三次按键后,重新开始计时,并将次数清零
			{
				Times = 0;
				time = 0;
			}
		}
		DigDisplay(time);
	}
}

void Timer0() interrupt 1 using 1  
{  
     TH0 = 0xDC;   //重装初值,定时1ms初值高八位  
     TL0 = 0x00;   //定时1ms初值低八位  
		 time++; //时间加一    
     if ( time == 9999) time = 0;
}

void Timer1() interrupt 3 using 2  
{  
     TH1 = 0xDC;   //重装初值,定时1ms初值高八位  
     TL1 = 0x00;   //定时1ms初值低八位  
		 KeyNumber = ReadKeyState();		//读取按键值
}

视频:
10s.mp4

后发布评论