一、前言
在前四篇笔记里,我们学习了单片机最基础的四个部分,分别是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();
}
}