蓝桥杯模块独立按键
发布日期:2021-07-01 03:12:47 浏览次数:2 分类:技术文章

本文共 7126 字,大约阅读时间需要 23 分钟。

   九层妖塔 起于垒土

在这里插入图片描述

蓝桥杯模块独立按键

独立键盘(BTN)

1、原理图

在这里插入图片描述

J523相连,即为独立键盘模式(BTN)
按键S7,S6,S5,S4用作独立按键,分别对应P30,P31,P32,P33

2、实物图

在这里插入图片描述

右 BTN 独立键盘
左 KBD 矩阵键盘

3、波形图

波形图:

在这里插入图片描述

4、Method

1、普通软件延时消抖:

 ●代码:

//独立按键--普通软件延时消抖#include
#include
#define uchar unsigned char#define uint unsigned intsbit S4 = P3^3;uchar SEG_Array[10]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数码管段码uchar yi,er,san,si,wu,liu,qi,ba;uchar LED_num; //LED流水计数标志void All_Init(void); //开发板初始化void SEG_Init(void); //数码管初始化,熄灭所有数码管void Delay1ms(); //@11.0592MHzvoid Delay10ms(); //@11.0592MHzvoid SEG_1_2(uchar yi,uchar er);//数码管1,2驱动void LED_Water(void); //按键LED流水灯驱动void main(void){
All_Init(); //开发板初始化 while(1) {
if(S4==0) {
Delay10ms(); if(S4==0) {
LED_num++; if(LED_num==10) LED_num=0; while(!S4); } } LED_Water(); SEG_1_2(LED_num,2); SEG_Init(); }}//-------------------------------延时-------------------------------//void Delay1ms() //@11.0592MHz{
unsigned char i, j; _nop_(); _nop_(); _nop_(); i = 11; j = 190; do {
while (--j); } while (--i);}void Delay10ms() //@11.0592MHz{
unsigned char i, j; i = 108; j = 145; do {
while (--j); } while (--i);}//----------------------------------初始化---------------------------------////----------------------------------开发板初始化--------------------------//void All_Init(void) {
P2&=0X1F; //关573 P0=0XFF; //预送数据 P2|=0X80; P2&=0X9F; //开LED的573 P0=0XFF; //关LED P2&=0X1F; //关573 P2&=0X1F; //关573 P0=0X00; //预送数据 P2|=0XA0; P2&=0XBF; //开蜂鸣器继电器的573 P0=0X00; //关蜂鸣器,继电器 P2&=0X1F; //关573 P2&=0X1F; //关573 P0=0X00; //预送数据 P2|=0XC0; P2&=0XDF; //开数码管位选573 P0=0X00; //位选,全部不选 P2&=0X1F; //关573 P2&=0X1F; //关573 P0=0XFF; //预送数据 P2|=0XE0; P2&=0XFF; //开数码管段选573 P0=0XFF; P2&=0X1F; //关573}//----------------------------------数码管初始化--------------------------//void SEG_Init(void) //关闭熄灭所有数码管{
P2&=0X1F; //关573 P0=0X00; //预送数据 P2|=0XC0; P2&=0XDF; //开数码管位选573 P0=0X00; //位选,全部不选 P2&=0X1F; //关573 P2&=0X1F; //关573 P0=0XFF; //预送数据 P2|=0XE0; P2&=0XFF; //开数码管段选573 P0=0XFF; P2&=0X1F; //关573}//------------------------------------动态数码管驱动-----------------------////------------------------------------动态数码管驱动------第一二个---------//void SEG_1_2(uchar yi,uchar er){
//-------第一个数码管---------// P2&=0X1F; //关573 P0=SEG_Array[yi]; //预送段选数据 P2|=0XE0; P2&=0XFF; //开数码管段选573 P0=SEG_Array[yi]; //送段选数据 P2&=0X1F; //关573 P0=0X00; //消影 P2|=0XC0; P2&=0XDF; //开数码管位选573 P0=0X01; //送位选数据 P2&=0X1F; //关573 Delay1ms(); //-------第二个数码管---------// P2&=0X1F; //关573 P0=SEG_Array[er]; //预送段选数据 P2|=0XE0; P2&=0XFF; //开数码管段选573 P0=SEG_Array[er]; //送段选数据 P2&=0X1F; //关573 P0=0X00; //消影 P2|=0XC0; P2&=0XDF; //开数码管位选573 P0=0X02; //送位选数据 P2&=0X1F; //关573 Delay1ms();}//-------------------------------按键流水灯驱动--------------//void LED_Water(void){
P2&=0X1F; //关573 P0=0XFF; //预送数据 P2|=0X80; P2&=0X9F; //开LED的573 P0=~(0X01<

 ●流程图:

在这里插入图片描述
 ●松手检查:while(!KEY)等待按键释放。等按键确认释放后再去执行相应代码。防止重入。
 ●CPU在按键按下抖动时进行10ms的软件延时消抖,在数百ms的稳定期以及松手抖动时停滞在松手检测while(!KEY)中,占用CPU资源过多;也就是在整个按键检测期间内,没有再执行其他指令。
 ●按键检测时是借助while(1)死循环进行反复检测。
 ●若是采用普通软件延时消抖10ms的软件延时和松手检测都会占用CPU资源,对其它同样借助while(1)死循环进行反复运行的模块代码产生了挤占影响,比如动态数码管。
 ●稳定期取决于是否松手,若不松手,则数码管将一直保持进入按键检测前最后一次对数码管的操作。

2、Template①:标志位软件延时消抖:

 ●代码:

//独立按键--标志位软件延时消抖sbit S4 = P3^3;sbit S5 = P3^2;sbit S6 = P3^1;sbit S7 = P3^0; void keyscan_4(void); //独立按键扫描//-------------------------------------独立按键扫描---------------------//void keyscan_4(void){
static bit S4_down,S5_down,S6_down,S7_down; //S4-S7独立按键按下标志位 if(S4==0 && S4_down==0) //S4 {
Delay10ms(); if(S4==0) {
S4_down=1; } } if(S4==1 && S4_down==1) {
Delay10ms(); if(S4==1) {
S4_down=0; SEG_num1++; if(SEG_num1==10) SEG_num1=0; } } if(S5==0 && S5_down==0) //S5 {
Delay10ms(); if(S5==0) {
S5_down=1; } } if(S5==1 && S5_down==1) {
Delay10ms(); if(S5==1) {
S5_down=0; SEG_num2++; if(SEG_num2==10) SEG_num2=0; } } if(S6==0 && S6_down==0) //S6 {
Delay10ms(); if(S6==0) {
S6_down=1; } } if(S6==1 && S6_down==1) {
Delay10ms(); if(S6==1) {
S6_down=0; SEG_num3++; if(SEG_num3==10) SEG_num3=0; } } if(S7==0 && S7_down==0) //S7 {
Delay10ms(); if(S7==0) {
S7_down=1; } } if(S7==1 && S7_down==1) {
Delay10ms(); if(S7==1) {
S7_down=0; SEG_num4++; if(SEG_num4==10) SEG_num4=0; } }}

 ●波形图:

在这里插入图片描述
 ●通过引入按下标志位,省去了while(!KEY)的松手检测,将按下时稳定期的数百ms释放出来,只占用了按下和松手时的共20ms的消抖时间。
 ●若采用10ms消抖,按下和松手时刻,数码管仍然会有轻微闪动。是亮灭之间的闪动。
 ●SEG_Init();即灭掉所有数码管(在此其实只灭掉了最后一个数码管,其他数码管本来就是关闭的)。若不加此句,前七位是亮灭之间的闪动,最后一位是亮与更亮之间的闪动,格外刺眼。
 加上SEG_Init();并不是如大科所说将消抖的10ms均分给各个数码管,只是将10ms从最后一个数码管的时间里拿去。

3、Template②:标志位定时器延时消抖:

①定时器配置:

 ●定时器1模式0(16位自动重装载模式)
 ●下列定时器配置代码是将STC-ISP生成后的,删除最后一行开定时器;在第一行增加关定时器。
 ●只要TR1 = 1定时器就在不停计数,无论溢出标志位是否清除,无论若是中断查询是否响应。所以先关定时器,重新写入初值,再清除标志位。
 ●目前已经实现的方法中,效果最好的方法。没有丝毫的闪动。

void Timer1Init(void)		//10毫秒@12.000MHz{
TR1=0; //关定时器1 AUXR &= 0xBF; //定时器时钟12T模式 TMOD &= 0x0F; //设置定时器模式 TL1 = 0xF0; //设置定时初值 TH1 = 0xD8; //设置定时初值 TF1 = 0; //清除TF1标志 //TR1 = 1; //定时器1开始计时}

②主函数:

 ●进入死循环前,需要先配置定时器,装初值。(进入第一个定时器延时前没有初值的装填)

void main(void){
All_Init(); //开发板初始化 Timer1Init();//定时器1配置,独立按键消抖 while(1) {
keyscan_4(); //独立按键扫描 SEG_1_2(SEG_num1,SEG_num1); SEG_3_4(SEG_num2,SEG_num2); SEG_5_6(SEG_num3,SEG_num3); SEG_7_8(SEG_num4,SEG_num4); SEG_Init(); }}

③按键扫描

 ●使用定时器进行延时消抖。
 ●定时器使用查询法,若采用中断法可能会影响其他模块的显示或者通信。
 ●使用标志位代替松手检测。
 ●增加代码,就可以很方便的进行长按和短按的检测。(或者用状态机检测长按和短按)。

//-------------------------------------独立按键扫描---------------------//void keyscan_4(void){
static uchar S4_down,S5_down,S6_down,S7_down; //S4-S7独立按键按下标志位 if(S4==0 && S4_down==0) //S4 {
TR1 = 1; //定时器1开始计时 if(S4==0 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S4_down=1; } } if(S4==1 && S4_down==1) {
TR1 = 1; //定时器1开始计时 if(S4==1 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S4_down=0; SEG_num1++; if(SEG_num1==10) SEG_num1=0; } } if(S5==0 && S5_down==0) //S5 {
TR1 = 1; //定时器1开始计时 if(S5==0 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S5_down=1; } } if(S5==1 && S5_down==1) {
TR1 = 1; //定时器1开始计时 if(S5==1 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S5_down=0; SEG_num2++; if(SEG_num2==10) SEG_num2=0; } } if(S6==0 && S6_down==0) //S6 {
TR1 = 1; //定时器1开始计时 if(S6==0 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S6_down=1; } } if(S6==1 && S6_down==1) {
TR1 = 1; //定时器1开始计时 if(S6==1 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S6_down=0; SEG_num3++; if(SEG_num3==10) SEG_num3=0; } } if(S7==0 && S7_down==0) //S7 {
TR1 = 1; //定时器1开始计时 if(S7==0 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S7_down=1; } } if(S7==1 && S7_down==1) {
TR1 = 1; //定时器1开始计时 if(S7==1 && TF1==1) {
Timer1Init(); //关定时器;重装初值;清除TF1标志 S7_down=0; SEG_num4++; if(SEG_num4==10) SEG_num4=0; } }}

4、Template:状态机:

5、三行代码:

转载地址:https://methadone-no1.blog.csdn.net/article/details/108119449 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:蓝桥杯模块显示部分Part3:蜂鸣器&继电器
下一篇:蓝桥杯模块显示部分Part2:数码管

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年05月02日 02时16分21秒