蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)

这篇具有很好参考价值的文章主要介绍了蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、按键的底层驱动代码讲解

1.按键原理图

蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)
CON3中将1,2用跳线帽短接是矩阵键盘,可用范围为S4到S19。将2,3短接则是独立按键,可用范围是S4到S7.

按键原理讲解

单取一个按键,一端接到GND,一段接到单片机的IO口上(以下称I口,输入口)。当按键按下时,I口读取电平为低电平,按键未按下单片机的I口读取为高电平。此时只需要单片机按时扫描这个I口是否为低电平,即可判断按键按是否按下。如果有四个这样的按键,就是上图中的独立按键。

如果将GND同时也换成单片机的另IO口(以下称O口,输出口),那么当我有需要读取按键时,将O口设置输出为低电平,再去读取I口的电平,即可判断按键是否按下。这样做有什么好处呢。

如果我需要有16个按键,如果用独立按键,那么我将需要16个I口取读取按键电平。如果将16个按键每行放置4个,放4列,如上图CON1,2口短接时。并却我采用O口输出口的话,采用4个O口,每个O口控制一列4个按键,采用4个I口,每个I口读取每行4个按键。这样输出对应竖排,输入对应横排。两个分量,就可以在二维平面上定位到按键的位置。如此,将本来16个IO口减少到了8个IO口,节约了单片机的资源,这就是矩阵键盘。

矩阵键盘的使用,先将一个O口置零,读取所有的I口,再依次将O口置零读取I口。那么这样去读取按键会不会有时间差。不会的,一个按键按下的过程至少需要大几十个毫秒,我只去要将O口轮换的速度变快,就可以了。

2.按键代码

(1)按键头文件

#ifndef __KEY_H
#define __KEY_H
#include "STC15F2K60S2.H"

unsigned char Key_Read();
unsigned char Key_Read_BTN();

#endif

(2)独立按键

#include "key.h"
//P30-P34为I口,读取高低电平判断按键是否按下 
unsigned char Key_Read_BTN()
{
	unsigned char key_value; //设置按键代号变量 
	
	if(P33 == 0) key_value = 4; //S4按键,用4代替 
	else if(P32 == 0) key_value = 5;
	else if(P31 == 0) key_value = 6;
	else if(P30 == 0) key_value = 7;
	else key_value = 0; 
	// 如果没有按键按下返回值为零,这个很重要。 
	return key_value;//将按键代号返回,便于接下来的处理 
}

(3)矩阵按键

#include "key.h"

unsigned char Key_Read()
{
	unsigned int key_new; 
	// I口读取变量,有16个按键,16位,两个字节,所以用int型变量 
	unsigned char key_value; //设置按键代号变量 
	
	P44 = 0; P42 = 1; P35 = 1; P34 = 1; //将一个O口置零 
	key_new = P3&0x0F; //读取全部的I口数据 
	P44 = 1; P42 = 0; P35 = 1; P34 = 1;
	key_new =(key_new<<4)|(P3&0x0F); //将上次读取的数据左移,并存储这次I口全部数据 
	P44 = 1; P42 = 1; P35 = 0; P34 = 1;
	key_new =(key_new<<4)|(P3&0x0F);	
	P44 = 1; P42 = 1; P35 = 1; P34 = 0;
	key_new =(key_new<<4)|(P3&0x0F);	
	
	//4个O口对应16个I口数据全部读取。 
	
	switch(~key_new)    //取反,按键按下是0,不按是1 
	{
		case 0x8000: key_value = 4; break;
		case 0x4000: key_value = 5; break;
		case 0x2000: key_value = 6; break;
		case 0x1000: key_value = 7; break;
		
		case 0x0800: key_value = 8; break;
		case 0x0400: key_value = 9; break;
		case 0x0200: key_value = 10; break;
		case 0x0100: key_value = 11; break;
		
		case 0x0080: key_value = 12; break;
		case 0x0040: key_value = 13; break;
		case 0x0020: key_value = 14; break;
		case 0x0010: key_value = 15; break;
		
		case 0x0008: key_value = 16; break;
		case 0x0004: key_value = 17; break;
		case 0x0002: key_value = 18; break;
		case 0x0001: key_value = 19; break;
		
		default: key_value = 0;
	}
	
	return key_value;
}

(4)main.c中按键函数(三行消抖的理解)

void Key_Proc()
{
	if(key_slow_down) return;
	key_slow_down = 1;
	//降速处理每10毫秒进入一次按键处理
	
	key_value = Key_Read_BTN();//进入底层驱动读取键值
	key_down = key_value&(key_value^key_old);//下降沿
	key_up = (~key_value)&(key_value^key_old);//上升沿
	key_old = key_value;
	//三行代码按键消抖,文章中讲解
	switch(key_down)//对按键的下降沿进行扫描处理
	{
		case 4:    
			if(display>>4 == 0x1)
				display = 0x20;
			else if(display>>4 == 0x2)
				display = 0x31;
			else if(display>>4 == 0x3)
				display = 0x41;
			else if(display>>4 == 0x4)
				display = 0x11;
			break;	//S4按下时的处理,13届蓝桥杯国赛部分参考
		default: break;
	}
}
key_value = Key_Read_BTN();
key_down = key_value&(key_value^key_old);
key_old = key_value;

这三行代码是蓝桥杯官方提供的按键消抖代码,简洁精炼,值得我们去学习。
学习代码之前先看一幅图
蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)
A是上升沿,B是下降沿,A-B为高电平,B-A为低电平。

key_value = Key_Read_BTN();
//这一行就是去读取高低电平状态,高电平即使未按下,低电平是按下。这一行只能说明是一种状态,如果是最基本的按下触发,状态值是不可以使用,因为一次按键按下至少维持几十毫秒,再这几十个毫秒里程序会不只一次获取状态值,那么我们通过按键所执行的任务就会多次执行。
所以仅仅读取电平状态是不可行的,如何做到按键一次按下,只执行一次。我们想到去读取跳变沿A或B,官方给出的是读取下降沿(即B);为此引入第二行代码,再讲解第二行代码前,先说一下第三行代码

key_old = key_value;
//为了运用代码得到跳变沿,即我们需要获取上一次的电平状态与这一次的电平状态经过逻辑运算得到。这第三行代码就是为了得到上一次的电平状态

key_down = key_value&(key_value^key_old);
//第二行代码既要获得下降沿又要获得按键键值,即那个按键发送下降沿。
key_value^key_old 将上次的电平状态与当前的电平状态取按位异或,可以检测出跳变沿,没有跳变沿为0,又跳变沿为当前跳变沿的键值。当然仅仅一个按位异或是不够的,并不能区分出上升沿和下降沿。所以要在按位与key_value(得到下降沿)或者按位与(~key_value)(得到上升沿)。
//为什么上升沿检测比下降沿检测多一个取反
key_down = key_value&(key_value^key_old);//下降沿
key_up = (~key_value)&(key_value^key_old);//上升沿
首先下降沿检测前一次状态是抬起,键值是0,而瞬时状态为按下,键值为x,(key_value^key_old)为x。x与上x,任然为x,得到键值。
而检测上升沿,前一次状态是按下,键值是下,而瞬时状态为抬起,键值为0。(key_value^key_old)为x。应为瞬时键值为0,所以通过取反来获得键值。

总结,前半段决定上升沿还是下降沿,后半段检测跳变沿。

二、按键考点解析与代码展示

1.按键控制界面,工作模式的切换

(1)多个模式相同等级

蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)

	unsigned char state_flag;
	switch(key_down)
	{
		case 12: 
			if(++state_flag == 3) state_flag = 0; 
			//用state_flag代表界面,并且加到3清零。
			//显示模块通过state_flag的值显示
			break;
		default: break;
	}

(2)多模式不同级

蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)
简介表示
1.数据界面
(1)时间
(2)温度
(3)亮暗状态
2.参数界面
(1)时间参数
(2)温度参数
(3)指示灯参数

	unsigned char display = 0x11;
	//采用16进制数据,高位代表高模式,低位代表低模式
	switch(key_down)
	{		
		case 4: //高模式模式切换
			if(display>>4 == 1) 
				display = 0x21;
			else
				display = 0x11;
			break;
		case 5://低模式模式切换
			if(display == 0x11)
				display = 0x12;
			else if(display == 0x12)
				display = 0x13;
			else if(display == 0x13)
				display = 0x11;
			else if(display == 0x21)
				display = 0x22;
			else if(display == 0x22)
				display = 0x23;
			else if(display == 0x23)
				display = 0x21;
			break;
	}

总结:用一个对应变量决定模式状态。按键部分是对变量的处理。

2.按键长按。

(1)长按按键从A界面跳转到B界面,松开后恢复A界面

蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)

	if( key_old == 4)//S4按下
	{
		if(state_flag != 1 && state_flag != 2)//非设置状态
		{
			led_class_disp = 1; //长按状态设置
		}
	}
	else led_class_disp = 0;

注意点在于,长按显示不需要去读取跳边沿,而是直接读取电平状态。

(2)按键长按,按键抬起超过规定时间生效

蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)
蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)
下降沿开始计数,上升沿停止计数。判断计数时间。

	
	//按键程序
	key_value =Key_Read_BTN();
	key_down = key_value & ( key_value ^ key_old);//下降沿
	key_up = (key_value^0xff) & ( key_value ^ key_old);//上升沿
	key_old = key_value;
	
	if(key_down == 7)
	{
		ms_statrt = ms;//定时器中断ms每1毫秒加1,检测S7下降沿,将ms赋值到ms_statrt。
	}
	if(key_up == 7)
	{
			if((ms - ms_statrt) >= 1000)  led_flag ^= 1 ;//抬起时检测(ms - ms_statrt)是否超过规定时间
			else f_value = freq;
	}
	

为什么if(key_down)和if(key_up)同级:
答:按键只检测跳变沿并不是检测高低电平,跳变沿是瞬时性的所以在跳变沿里检测另一个跳变沿是不合理的。

(3)按键长按,时间到后生效(无须按键抬起)

蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)
注意点:下降沿仅开始计数,对时间进行判断。对短按识别上升沿识别。对长按进行一次进入判断(一次判断,赋值卡死而不是取反)。

下降沿,开始计数,(是否进行一次判断)
短时间上升沿扫描,
长时间,电平扫描加一次判断。文章来源地址https://www.toymoban.com/news/detail-419128.html

	if(key_down == 7)
	{
		key_time = ms; // 计数开始
		key_long = 1;//长按一次判断,即长按达到时间后只进行一次操作
	}
	
	if(ms-key_time<1000)//时间未到,短按操作
	{
		if(key_up == 7)
		{
			if(display == 0x41)
				freq_compare = freq_compare-0.5;
			else if(display == 0x42)
				temp_compare = temp_compare-10;
			else if(display == 0x43)
				dist_compare = dist_compare-0.1;
			else if(display == 0x11)
				display = 0x12;
			else if(display == 0x12)
				display = 0x11;
		}
	}
	else // 长按操作
	{
		if(key_value == 7&&key_long == 1) // 判断此时按键电平状态和一次操作
		{
			key_long = 0;
			if(display==0x20)
				relay_count = 0;
		}
	}

蓝桥杯的资料,个人应该有一些,需要什么资料可以私信我哈。

到了这里,关于蓝桥杯单片机类按键代码讲解和考点探究(三行代码消抖讲解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机——独立按键实验,小白讲解,相互学习

    按键介绍:         按键是一种电子开关,使用时轻轻按开关按钮就可式开关接通,当松手时,开关断开。开发板上使用的按键及内部简易图如下图:         按键管脚两端距离长的表示默认是导通状态,距离短的默认是断开状态,如果按键按下,初始导通状态变为断

    2024年02月04日
    浏览(55)
  • 51单片机——矩阵按键实验,小白讲解,相互学习

    矩阵按键介绍:         独立按键与单片机连接时,每一个按键都需要单片机的一个I/O 口,若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O 口资源.单片机系统中I/O 口资源往往比较宝贵,当用到多个按键时为了减少I/O 口引脚,引入了矩阵按键。       

    2024年02月12日
    浏览(49)
  • 关于蓝桥杯单片机 官方例程 矩阵按键 消抖原理 ‘s 解释

    关于蓝桥杯单片机官方例程矩阵按键消抖原理解释 芯片:IAP15F2K60S 蓝桥杯原书41页官方例程 最开始我以为这款开发板有硬件消抖,对于下面这部分代码一直当作固定格式写,最近回看,发现其中另有“玄机”。 这里默认大家看过并且会了 = = 之前的按键扫描例程了 众所周知

    2023年04月08日
    浏览(37)
  • 单片机按键开关代码

    在单片机的应用程序中,按键开关的使用频率非常高。按键开关可以通过检测用户的操作,实现程序的控制和交互。本文将介绍单片机按键开关的基本原理和如何在程序中实现按键开关的控制。 按键开关的原理基于接通和断开电路之间的变化。当按键按下时,连接到单片机的

    2024年02月02日
    浏览(43)
  • 单片机之独立按键(多种按键代码编写)

    单片机之独立按键原理:按键右端接GND,左边接到单片机的IO口,同时接了一个上拉电阻,当按键未按下时,P2.0为高电平(学过模电的人都应该知道为什么吧)当按键按下时,相当于P2.0口与GND相连为 低电平。

    2024年02月03日
    浏览(60)
  • 蓝桥杯单片机学习日记3-矩阵键盘的使用,线反转法,三步消抖,按键长按与短按

    此片文章用于记录蓝桥杯单片机的学习 篮球杯单片机上的矩阵按键原理图如下:   使用矩阵键盘时,要将跳线帽J5跳至KBD模式。   值得注意的是,若开发板上的单片机使用的为STC15,那么以上原理图适用。如果单片机为IAP15,则在上述原理图中,要将P36换成P42,P37换成P44。  

    2023年04月10日
    浏览(49)
  • 蓝桥杯单片机模块代码综合(考前快速复习)

    今天做的是蓝桥杯所有模块的综合,只展示模块的核心代码,所以只能作为复习资料,而不是学习资料。这次给原理图全在官方给的资料里,考试记不起来可以在文件夹里找到! (一)LED   核心代码示例: 原理图:   回忆一下,译码器选择Y4使得其为低电平,J13中WR与地连

    2024年02月03日
    浏览(37)
  • 【蓝桥杯单片机】2023官方底层驱动代码【补充点】

    第14届蓝桥杯单片机设计,官方提供了新的底层驱动代码版本, 虽然依旧是onewire、iic、ds1302这三个源文件, 但是并没有给出头文件,且在此三个源文件中缺少了一些必要的管脚定义 下面是本人在往年真题中替换新的底层代码时总结出来的一些需要注意的地方 【关键点】引用

    2023年04月08日
    浏览(114)
  • 【蓝桥杯单片机】第十二届省赛(含题目和解答代码)

    main.c  iic.c iic.h onewire.c onewire.h      

    2024年02月04日
    浏览(72)
  • 蓝桥杯十四届单片机国赛试题及代码

        今年十四届单片机国赛试题在程序题设计方面难度有所下降,但选择题没有了以往可以在手册中可以找到的单片机类选择题,选择题难度较高,因此想获得一个不错的成绩,需要在选择题方面有所加强 此次国赛采用了温度传感器DS18B20模块,LED模块,按键模块,Pcf8591DAC模

    2024年02月13日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包