目录
一、硬件部分:
1、原理图:
二、独立按键:
1、功能一参考代码:
(1)宏定义:
(2)主函数:(感觉现在迷上位操作了,不会的可以自已定义IO口)
1、功能一参考代码(模块化):
2、功能二参考代码:
(1)宏定义:(同上)
(2)主函数:(如果跟着我之前几篇文章一起优化过自己代码的人,应该看得懂我这次写的代码,如果看不懂建议回去巩固一下)
(3)主函数:(优化版但可能比较难懂)
3、功能一参考代码: (直观化)
4、优化代码:(最好学过定时器后再来学习以下代码)
(1)宏定义:
(2)主函数:
(1)J5:当1和2相接,电路就变成一个4*4的矩阵键盘电路;当2和3相接时,电路变成
了一个S4-S7的独立按键
(2)对于独立按键的分析:
独立按键,按键检测_佛科院深夜学习的博客-CSDN博客https://blog.csdn.net/weixin_63568691/article/details/128374461
实现功能:
(1)按下S7-S4分别点亮L1-L4,同时要求松手熄灭和消抖
(2)S7、S6为选择键,S5和S4为开关键:
(A)当按下S7,指示灯L1亮(无松手检测),同时表明当前选择L3、L4,分别由S5和S4控制(有松手检测)
(B)当按下S6,指示灯L2亮(无松手检测),同时表明当前选择L5、L6,分别由S5和S4控制(有松手检测)
(C)同时要求未进行选择之前,开关键不起作用
#ifndef _PUBLIC_H
#define _PUBLIC_H
#include
#define u8 unsigned char
#define u16 unsigned int
void Delay_1ms(u16 num);
void Close_All(void);
void Delay_10us(u16 num);
#endif
#include "Public.h"
// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
unsigned int i;
while(num--)
for(i=0; i<628; i++);
}
/*
输入变量:无
输出变量:无
功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
//关闭蜂鸣器和继电器
P0 = 0x00;
P2 = (P2 & 0x1f) | 0xA0;
P2 &= 0x1f;
//关闭LED灯
P0 = 0xff;
P2 = (P2 & 0x1F) | 0x80;
P2 &= 0x1f;
}
void Delay_10us(u16 num)
{
u16 i;
while(num--)
for(i=0; i<3; i++);
}
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
// 主函数
void main(void)
{
u8 i;
Close_All();
while(1)
{
for(i=0;i<4;i++)
{
if(!(P3 & (0x01<
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
u8 Key_check();
// 主函数
void main(void)
{
u8 temp;
Close_All();
while(1)
{
if(temp=Key_check())
{
LED_ON(~(0x01<<(7-temp)));
while(!(P3 & 0x01<<(7-temp)));
LED_ON(0xff);
}
}
}
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}
/*
输入变量:无
输出变量:7-4代表第几个按键被按下;0代表没有按键按下
功能:检测哪个独立按键被按下
注意:只有消抖,没有松手检测
*/
u8 Key_check()
{
u8 i;
for(i=0;i<4;i++)
{
if(!(P3 & (0x01<
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
u8 Key_check();
// 主函数
void main(void)
{
u8 temp,last_led;
Close_All();
while(1)
{
if(temp=Key_check())
{
//按下S7
if(temp==7)
{
//L1亮,并且保存好L1亮的信息
LED_ON(~(last_led=0x01<<(7-temp)));
//松手后再进行其他操作,但不关灯
while(!(P3 & 0x01<<(7-temp)));
while(1)
{
//再对S5、S4进行判断
temp=Key_check();
if(temp==5||temp==4)
{
//L1和其中之一的灯一起亮
LED_ON(~((0x01<<(7-temp))|last_led));
while(!(P3 & 0x01<<(7-temp)));
//保持为L1亮的状态
LED_ON(~last_led);
}
if(temp==7)
{
//关闭所有灯
LED_ON(0xff);
while(!(P3 & 0x01<<(7-temp)));
break;
}
}
}
//按下S6
if(temp==6)
{
//L2亮
LED_ON(~(last_led=0x01<<(7-temp)));
//松手后再进行其他操作,但不关灯
while(!(P3 & 0x01<<(7-temp)));
while(1)
{
//再对S5、S4进行判断
temp=Key_check();
if(temp==5||temp==4)
{
//如果是按下S6,表明选择L5、L6
LED_ON(~((0x01<<(7-temp+2))|last_led));
while(!(P3 & 0x01<<(7-temp)));
LED_ON(~last_led);
}
if(temp==6)
{
LED_ON(0xff);
while(!(P3 & 0x01<<(7-temp)));
break;
}
}
}
}
}
}
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}
/*
输入变量:无
输出变量:7-4代表第几个按键被按下;0代表没有按键按下
功能:检测哪个独立按键被按下
注意:只有消抖,没有松手检测
*/
u8 Key_check()
{
u8 i;
for(i=0;i<4;i++)
{
if(!(P3 & (0x01<
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
u8 Key_check();
// 主函数
void main(void)
{
u8 temp,last_led,c_sign;
Close_All();
while(1)
{
if(temp=Key_check())
{
if(temp==7||temp==6)
{
//按下S7,控制L3、L4
if(temp==7)
c_sign=0;
//按下S6,控制L5、L6
if(temp==6)
c_sign=2;
//L1/L2亮,并且保存好L1/L2亮的信息
LED_ON(~(last_led=0x01<<(7-temp)));
//松手后再进行其他操作,但不关灯
while(!(P3 & 0x01<<(7-temp)));
while(1)
{
//再对S5、S4进行判断
temp=Key_check();
if(temp==5||temp==4)
{
//L1和其中之一的灯一起亮
LED_ON(~((0x01<<(7-temp+c_sign))|last_led));
while(!(P3 & 0x01<<(7-temp)));
//保持为L1亮的状态
LED_ON(~last_led);
}
//检测到控制键按下且标志位对应
if((temp==7&&c_sign==0)||(temp==6&&c_sign==2))
{
//关闭所有灯
LED_ON(0xff);
while(!(P3 & 0x01<<(7-temp)));
break;
}
}
}
}
}
}
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}
/*
输入变量:无
输出变量:7-4代表第几个按键被按下;0代表没有按键按下
功能:检测哪个独立按键被按下
注意:只有消抖,没有松手检测
*/
u8 Key_check()
{
u8 i;
for(i=0;i<4;i++)
{
if(!(P3 & (0x01<
由于不太清楚是模块化思想编程好,还是减少模块和位运算尽量直观化的方法好,我决定都尝试一下
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
// 主函数
void main(void)
{
u8 i;
Close_All();
while(1)
{
if(!S7)
{
Delay_1ms(20);
if(!S7)
{
LED_ON(~(0x01<
4、功能二参考代码: (直观化)
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
u8 Key_check();
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
// 主函数
void main(void)
{
Close_All();
while(1)
{
if(!S7)
{
Delay_1ms(20);
if(!S7)
{
LED_ON(~(0x01<<0));
while(!S7);
while(1)
{
if(!S5)
{
Delay_1ms(20);
if(!S5)
{
LED_ON(~((0x01<<2)|(0x01<<0)));
while(!S5);
LED_ON(~(0x01<<0));
}
}
if(!S4)
{
Delay_1ms(20);
if(!S4)
{
LED_ON(~((0x01<<3)|(0x01<<0)));
while(!S4);
LED_ON(~(0x01<<0));
}
}
if(!S7)
{
Delay_1ms(20);
if(!S7)
{
while(!S7);
LED_ON(0xff);
break;
}
}
}
}
}
if(!S6)
{
Delay_1ms(20);
if(!S6)
{
LED_ON(~(0x01<<1));
while(!S6);
while(1)
{
if(!S5)
{
Delay_1ms(20);
if(!S5)
{
LED_ON(~((0x01<<4)|(0x01<<1)));
while(!S5);
LED_ON(~(0x01<<1));
}
}
if(!S4)
{
Delay_1ms(20);
if(!S4)
{
LED_ON(~((0x01<<5)|(0x01<<1)));
while(!S4);
LED_ON(~(0x01<<1));
}
}
if(!S6)
{
Delay_1ms(20);
if(!S6)
{
while(!S6);
LED_ON(0xff);
break;
}
}
}
}
}
}
}
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}
写完的个人感受:
(1)优点:直观化的可读性强,在局部阅读属于一看就明白,如果是一小部分写错,几乎是一下子就能看出错误;缺点:代码整体冗杂,如果是整体有错误,全局阅读性很差,特别是存在过多大括号的情况下‘;重复性强,如果存在一处错误,基本上需要改多处;可移植性差,基本不存在一码多用的情况
(2)优点:模块化的可移植性强,有时候写着写着发现都是用已经写好的函数;整体可读性强,基本上都是不同的模块组成,可以分开一部分一部分看;修改简单,由于程序大量使用同一函数,基本上只需要改某个的函数就行;缺点:局部可读性极差,极其考虑逻辑思维能力;函数与主函数联系起来较为麻烦;
(3)总结:建议还是以模块化思维编程会更有逻辑性,但是不要过度追求模块化,实在想不明白的地方直接用最笨的方法也行,在平时可以进行优化训练,但在比赛场上就不要硬求优化,能写出来就行
更新:学习其他代码后而且经过一个实际工程代码的编写,深感之前代码的鲁棒性太差了,也通过定时器和位操作优化了消抖和松手检测
蓝桥杯模块学习8——定时器中断(深夜学习——单片机)_佛科院深夜学习的博客-CSDN博客https://blog.csdn.net/weixin_63568691/article/details/128508355
#ifndef _PUBLIC_H
#define _PUBLIC_H
#include "STC15F2K60S2.H"
#define u8 unsigned char
#define u16 unsigned int
void Delay_1ms(u16 num);
void Close_All(void);
void Delay_10us(u16 num);
#endif
#include "Public.h"
// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
unsigned int i;
while(num--)
for(i=0; i<628; i++);
}
/*
输入变量:无
输出变量:无
功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
//关闭蜂鸣器和继电器
P0 = 0x00;
P2 = (P2 & 0x1f) | 0xA0;
P2 &= 0x1f;
//关闭LED灯
P0 = 0xff;
P2 = (P2 & 0x1F) | 0x80;
P2 &= 0x1f;
}
void Delay_10us(u16 num)
{
u16 i;
while(num--)
for(i=0; i<3; i++);
}
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "Public.h"
u8 key_old,key_1ms = 1;
void LED_ON(u8 L_X);
void Key_Proc();
void Timer_0_Init(u16 time);
// 主函数
void main(void)
{
Close_All();
Timer_0_Init(1000);//1ms
while(1)
{
Key_Proc();
}
}
/*****************LED*******************/
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}
/*****************按键*******************/
/*
输入变量:无
输出变量:7-4代表第几个按键被按下;0代表没有按键按下
功能:检测哪个独立按键被按下
注意:只有消抖,没有松手检测
*/
u8 Key_read()
{
u8 i;
for(i=0;i<4;i++)
{
if(!(P3 & (0x01<