蓝桥杯单片机基础学习项目(LED,数码管,蜂鸣器,继电器,按键控制)

一、前言

在前四篇笔记里,我们学习了单片机最基础的四个部分,分别是LED,数码管,蜂鸣器,继电器,按键控制。在单片机的学习,理论只是很小一部分内容,实操是占很大一部分的,在蓝桥比赛里,这四个部分是最容易得分的,所以,在本文我们进行这四个部分的联合,对四个部分进行调控配置,像比赛一样,完成指定要求。

二,基础项目

1、题目要求

(1)使用矩阵键盘输入(J5键帽短接1 2)如图功能要求

当按下S7按键时,数码管输入数字“0”;按下S11按键时,数码管输入数字“1”.....输入数字要求从右往左输入。

功能要求

(2)当按键S4按下时,数码管所有输入的内容全部清零。

(3)当按键S8按下时,数码管所有输入的内容减一位。比如:数码管输入了“87654”,按下一次S8按键后,数码管显示“8765”,按下两次S8按键后,数码管显示“876”。

(4)当按键S13按下时,蜂鸣器响起,再次按下,蜂鸣器关闭。

(5)当按键S17按下时,继电器合并,再次按下,继电器断开。

(6)当按键S12按下时,LED灯的L1,3,5,7点亮,再次按下,LED灯的L2,4,6,8点亮

再次按下,LED灯全部熄灭。

(7)当按键S16按下时,LED灯的L2,4,6,8点亮,再次按下,LED灯的L1,3,5,7点亮

再次按下,LED灯全部熄灭。

要求:按键之间互不影响,去抖,长按短按不影响功能显示;数码管不出现频闪,过亮,过暗;上电时,关闭所有LED灯,数码管,蜂鸣器,继电器。

2、题目分析

这道题目包含了单片机前四个基础模块,把四个模块整合起来,进而形成项目功能。

总体上难度不大,都是笔者通过蓝桥历年题目抽取出来的,本题最关键的地方是理清按键逻辑,知道哪一个按键负责什么内容,再通过打开锁存器不同的通道,实现不同功能。这里我们出现了,状态值这个定义,状态值是用于记录不同状态实现不同功能的赋值,状态值在单片机的工作逻辑里是非常重要的一部分,通过状态值去记录在这个时间段需要CPU完成的内容。

三、代码实现

1、头文件及按键引脚定义

#include <STC15F2K60S2.H>
//==============按键引脚定义==============
sbit K1 = P4^4;
sbit K2 = P4^2;
sbit K3 = P3^5;
sbit K4 = P3^4;
sbit K5 = P3^3;
sbit K6 = P3^2;
sbit K7 = P3^1;
sbit K8 = P3^0;

2、数组定义

//======数码管显示数字及键盘输入数组=======
//共阳数码管显示码段
code unsigned char Seg_Table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char Key_Pass[8] = {0};			//键盘输入数字

3、状态定义

//==================状态定义===============
unsigned char Keynum = 0;					//键盘输入次数状态
unsigned char BUZZ_flag;					//蜂鸣器状态
unsigned char RELAY_flag;					//继电器状态
unsigned char LED_1357;						//LED1357灯状态
unsigned char LED_2468;						//LED2468灯状态

4、其他函数

//============数码管延时函数===============
void Nixie_Delay(unsigned int i)
{
	while(i--);
}

//============按键去抖延时函数=============
void Delay20ms()	//@11.0592MHz
{
	unsigned char data i, j;
	i = 216;
	j = 37;
	do
	{
		while (--j);
	} while (--i);
}

//============锁存器通道选择================
void hc573(unsigned char n,dat)
{
	P0 = dat;
	switch(n)
	{
		case 0:
			P2 = (P2 & 0x1f) | 0x00;		//关闭所有锁存器通道
			break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;		//锁存器通道选择LED
			break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;		//锁存器通道选择蜂鸣器,继电器
			break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;		//锁存器通道选择数码管位选
			break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;		//锁存器通道选择数码管段选
			break;
	}
	P2 = (P2 & 0x1f) | 0x00;				//关闭所有锁存器通道
}

//===============系统初始化=================
void System_Init()
{
	hc573(4,0xff);
	hc573(5,0x00);
}

5、数码管函数

//=============数码管位选段选===============
void Nixie_pos_num(unsigned char pos,num)
{
	hc573(6,0x01 << (pos-1));				//指定数码管显示位置				
	hc573(7,Seg_Table[num]);				//指定数码管显示内容
	Nixie_Delay(500);
	hc573(7,0xff);							//数码管消隐
}

//=============数码管显示函数===============
void Nixie_Show()
{
	switch(Keynum)							//按键按下次数不同,数码管显示数字不同
	{
		case 1:
			Nixie_pos_num(8,Key_Pass[0]);
			break;
		case 2:
			Nixie_pos_num(7,Key_Pass[0]);
			Nixie_pos_num(8,Key_Pass[1]);
			break;
		case 3:
			Nixie_pos_num(6,Key_Pass[0]);
			Nixie_pos_num(7,Key_Pass[1]);
			Nixie_pos_num(8,Key_Pass[2]);
			break;
		case 4:
			Nixie_pos_num(5,Key_Pass[0]);
			Nixie_pos_num(6,Key_Pass[1]);
			Nixie_pos_num(7,Key_Pass[2]);
			Nixie_pos_num(8,Key_Pass[3]);
			break;
		case 5:
			Nixie_pos_num(4,Key_Pass[0]);
			Nixie_pos_num(5,Key_Pass[1]);
			Nixie_pos_num(6,Key_Pass[2]);
			Nixie_pos_num(7,Key_Pass[3]);
			Nixie_pos_num(8,Key_Pass[4]);
			break;
		case 6:
			Nixie_pos_num(3,Key_Pass[0]);
			Nixie_pos_num(4,Key_Pass[1]);
			Nixie_pos_num(5,Key_Pass[2]);
			Nixie_pos_num(6,Key_Pass[3]);
			Nixie_pos_num(7,Key_Pass[4]);
			Nixie_pos_num(8,Key_Pass[5]);
			break;
		case 7:
			Nixie_pos_num(2,Key_Pass[0]);
			Nixie_pos_num(3,Key_Pass[1]);
			Nixie_pos_num(4,Key_Pass[2]);
			Nixie_pos_num(5,Key_Pass[3]);
			Nixie_pos_num(6,Key_Pass[4]);
			Nixie_pos_num(7,Key_Pass[5]);
			Nixie_pos_num(8,Key_Pass[6]);
			break;
		case 8:
			Nixie_pos_num(1,Key_Pass[0]);
			Nixie_pos_num(2,Key_Pass[1]);
			Nixie_pos_num(3,Key_Pass[2]);
			Nixie_pos_num(4,Key_Pass[3]);
			Nixie_pos_num(5,Key_Pass[4]);
			Nixie_pos_num(6,Key_Pass[5]);
			Nixie_pos_num(7,Key_Pass[6]);
			Nixie_pos_num(8,Key_Pass[7]);
			break;
	}
}

6、按键控制函数

//=============按键控制函数===============
void Scan_Key()
{
	K1 = K2 = K3 = K4 = K5 = K6 = K7 = 1;K8 = 0;
	if(K1 == 0 || K2 == 0 || K3 == 0 || K4 == 0)
	{
		Delay20ms();
		if(K1 == 0)							//按键s7按下,数码管显示0
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 0;
				Keynum++;
			}
			while(K1 == 0)
			{
				Nixie_Show();
			}
		}
		if(K2 == 0)							//按键s11按下,数码管显示1
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 1;
				Keynum++;
			}
			while(K2 == 0)
			{
				Nixie_Show();
			}
		}
		if(K3 == 0)							//按键s15按下,数码管显示2
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 2;
				Keynum++;
			}
			while(K3 == 0)
			{
				Nixie_Show();
			}
		}
		if(K4 == 0)							//按键s19按下,数码管显示3
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 3;
				Keynum++;
			}
			while(K4 == 0)
			{
				Nixie_Show();
			}
		}
	}
	
	K1 = K2 = K3 = K4 = K5 = K6 = K8 = 1;K7 = 0;
	if(K1 == 0 || K2 == 0 || K3 == 0 || K4 == 0)
	{
		Delay20ms();
		if(K1 == 0)							//按键s6按下,数码管显示4
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 4;
				Keynum++;
			}
			while(K1 == 0)
			{
				Nixie_Show();
			}
		}
		if(K2 == 0)							//按键s10按下,数码管显示5
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 5;
				Keynum++;
			}
			while(K2 == 0)
			{
				Nixie_Show();
			}
		}
		if(K3 == 0)							//按键s14按下,数码管显示6
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 6;
				Keynum++;
			}
			while(K3 == 0)
			{
				Nixie_Show();
			}
		}
		if(K4 == 0)							//按键s18按下,数码管显示7
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 7;
				Keynum++;
			}
			while(K4 == 0)
			{
				Nixie_Show();
			}
		}
	}
	
	K1 = K2 = K3 = K4 = K5 = K7 = K8 = 1;K6 = 0;
	if(K1 == 0 || K2 == 0 || K3 == 0 || K4 == 0)
	{
		Delay20ms();
		if(K1 == 0)							//按键s5按下,数码管显示8
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 8;
				Keynum++;
			}
			while(K1 == 0)
			{
				Nixie_Show();
			}
		}
		if(K2 == 0)							//按键s9按下,数码管显示9
		{
			if(Keynum < 8)
			{
				Key_Pass[Keynum] = 9;
				Keynum++;
			}
			while(K2 == 0)
			{
				Nixie_Show();
			}
		}
		if(K3 == 0)							//按键s13按下,蜂鸣器开/关
		{
			BUZZ_flag = (BUZZ_flag + 1) % 2;
			if(BUZZ_flag == 1)
			{
				hc573(5,0x40);
			}
			else
			{
				hc573(5,0x00);
			}
			while(K3 == 0)
			{
				Nixie_Show();
			}
		}
		if(K4 == 0)							//按键s17按下,继电器开/关
		{
			RELAY_flag = (RELAY_flag + 1) % 2;
			if(RELAY_flag == 1)
			{
				hc573(5,0x10);
			}
			else
			{
				hc573(5,0x00);
			}
			while(K4 == 0)
			{
				Nixie_Show();
			}
		}
	}
	
	K1 = K2 = K3 = K4 = K6 = K7 = K8 = 1;K5 = 0;
	if(K1 == 0 || K2 == 0 || K3 == 0 || K4 == 0)
	{
		Delay20ms();
		if(K1 == 0)							//按键s4按下,数码管清零
		{
			Key_Pass[0]=Key_Pass[1]=Key_Pass[2]=Key_Pass[3]=Key_Pass[4]=Key_Pass[5]=Key_Pass[6]=Key_Pass[7]=Key_Pass[8]=0;
			Keynum = 0;
			while(K1 == 0)
			{
				Nixie_Show();
			}
		}
		if(K2 == 0)							//按键s8按下,数码管删除一位数字
		{
			if(Keynum > 0)
			{
				Key_Pass[Keynum] = Key_Pass[Keynum-1];
				Keynum--;
			}
			while(K2 == 0)
			{
				Nixie_Show();
			}
		}
		if(K3 == 0)							//按键s12按下,LED灯转换
		{
			LED_1357 = (LED_1357 + 1) % 3;
			if(LED_1357 == 1)
			{
				hc573(4,0xaa);
			}
			else if(LED_1357 == 2)
			{
				hc573(4,0x55);
			}
			else
			{
				hc573(4,0xff);
			}
			while(K3 == 0)
			{
				Nixie_Show();
			}
		}
		if(K4 == 0)							//按键s16按下,LED灯转换
		{
			LED_2468 = (LED_2468 + 1) % 3;
			if(LED_2468 == 1)
			{
				hc573(4,0x55);
			}
			else if(LED_2468 == 2)
			{
				hc573(4,0xaa);
			}
			else
			{
				hc573(4,0xff);
			}
			while(K4 == 0)
			{
				Nixie_Show();
			}
		}
	}
}

7、main函数

void main()
{
	System_Init();
	while(1)
	{
		Scan_Key();
		Nixie_Show();
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值