蓝桥杯电子赛_零基础利用按键实现不同数字的显现

目录

一、前提

按键的原理图

二、代码配置

bsp_key.c文件

疑问

main.c文件

main.c文件的详细讲解

功能实现

注意事项


一、前提

按键这一板块主要是以记忆为主,我直接给大家讲解代码去实现我要配置的功能。本次我要做的项目是板子上的按键有S4~S19,我希望任意一个按键可以显示对应的两位数,按下两个不同的按键可以一前一后各显示出两位数字,也就是生成四位数字,再按下另外一个按键实现清零的功能。

按键的原理图

这是板子上按键的原理图,如果要切换独立按键和矩阵键盘,那么我们需要将板子上J5部分的小插口的东西插到对应的位置上去,本项目是在KBD上,12是KBD矩阵键盘,23是BTN独立按键,如下图:

那么如何扫描呢?答:先锁定行,再锁定列,举个例子:假如说,我现在想要扫描S4这个按键,我们先要锁定从左往右数第一列连接对应的引脚是P44,S4对应的行是P33

二、代码配置

我们这里只用到Timer、init、seg、key,led,本文章没写的代码可以去我这个蓝桥杯第一个系列观看,里面有很详细的代码简介

bsp_key.c文件

cs 复制代码
#include "bsp_key.h"

//函数名:按键码值读取函数
//入口参数:无
//返回值:按键的码值
//函数功能:返回按键码
unsigned char Key_Read(void)
{
	unsigned int Key_NEW;
	unsigned char Key_Value;//返回值
	P44 = 0;P42 = 1;P35 = 1;P34 = 1;//第一列扫描
	Key_NEW = P3 & 0X0F; //P3 = 0000 1000---P37~P30,高位无效,只看P33~P30
	
	P44 = 1;P42 =0;P35 = 1;P34 = 1;//第二列扫描
	Key_NEW = (Key_NEW << 4) | (P3 & 0X0F); //将原来的数值挪到次4位,本次数值放到最低4位,占用了8位
	
	P44 = 1;P42 =1;P35 = 0;P34 = 1;//第三列扫描
	Key_NEW = (Key_NEW << 4) | (P3 & 0X0F); //将原来的数值挪到次次4位,本次数值放到最低4位,占用了12位

	P44 = 1;P42 =1;P35 = 1;P34 = 0;//第三列扫描
	Key_NEW = (Key_NEW << 4) | (P3 & 0X0F); //将原来的数值挪到次次次4位,本次数值放到最低4位,占用了16位

	
	switch(~Key_NEW)//Key_Value的数值对应按键的编号
	{
	  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;
	
}

疑问

在中switch中,为什么进行Key_New的取反?

答:一般来说,按键配置的时候,我们配置的是上拉输入,在没按按键的时候,对应的是高电平,按下去,是低电平,那么我们通过取反,就是按下去成为高电平1,利用哪个地方是1,进行选择对应的case

main.c文件

cs 复制代码
#include "bsp_init.h"
#include "bsp_seg.h"
#include "Timer0.h"
#include "bsp_key.h"
#include "bsp_key.h"
#include "STDIO.H"

/* 函数声明 */
void	Key_Proc(void);//按键处理
void	Seg_Proc(void);//显示处理

/* 全局变量 */

unsigned char seg_buf[8];//放置字符串转换后的段码到数组
unsigned char seg_string[10];//放置字符串
unsigned char pos = 0;//中断显示专用

unsigned char Key_Value;//读取按键的数值存储变量
unsigned char Key_Down,Key_Old;

unsigned char num_buffer[2] = {0, 0}; // 存储2个按键编号
unsigned char num_count = 0; // 当前存储的数字个数

unsigned char Seg_Show_Num;//准备显示出来的数值
void main()
{
 Cls_Peripheral();
 Timer0Init();		//1毫秒@12.000MHz
 EA = 1;
 while(1)
 {
	Key_Proc();//按键处理
	Seg_Proc();//显示处理
 }

}


/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 
{
   Seg_Disp( seg_buf, pos );
   if(++pos ==8) pos = 0;
}
/* Key_Proc */
void	Key_Proc(void)//按键处理,底层数据变更
{
	Key_Value = Key_Read();//读取按键按下的编号
	Key_Down = Key_Value & (Key_Old ^ Key_Value);//^异或(0000^0101)= 0101 0101 & 0101 = //0101 如果按键发生了下降沿的变化,输出结果和本次按键数值相同
												//^异或(0101^0101)= 0000 0101 & 0000 = //0000 如果按键发生了下降沿的变化,输出结果和本次按键数值相同
	Key_Old = Key_Value;

	if(Key_Down)//如果捕捉到下降沿跳变
	{
			if (num_count < 2) // 如果存储的按键个数小于2
        {
            num_buffer[num_count++] = Key_Down; // 存储按键编号
        }
        else // 如果已经存储了两个按键编号
        {
            // 清零操作
            num_count = 0; // 清空按键个数     
        }

	}	
}

/* Seg_Proc */
void	Seg_Proc(void)//显示处理,显示信息生成
{
		if (num_count == 1) // 如果只存储了一个按键编号
    {
        // 显示第一个按键编号的两位数字
        sprintf(seg_string, "    %02d", (unsigned int)num_buffer[0]);
    }
    else if (num_count == 2) // 如果存储了两个按键编号
    {
        // 显示两个按键编号的四位数字
        sprintf(seg_string, "    %02d%02d", (unsigned int)num_buffer[0], (unsigned int)num_buffer[1]);
    }
    else // 如果没有存储任何按键编号
    {
        // 显示全0
        sprintf(seg_string, "    0000");
    }
		
 Seg_Tran( seg_string,seg_buf);

}

main.c文件的详细讲解

假如说,我现在按下去了S4,那么检测到了S4处有下降沿,并且将这个数值给一个变量Key_Val,然后这个变量就给到了Seg_Show_Num,此刻还是一个二进制数,无法显示到数码管上,然后将这个Seg_Show_Num通过sprintf转化成字符串,字符串在Seg_Disp函数下,将段码转化成能看懂的数字,最后利用定时器中断每1ms进行刷新数码管上的东西

  1. 显示逻辑调整 : 在Seg_Proc函数中:

    • 如果num_count为0,显示全0。

    • 如果num_count == 2,显示两个按键编号的四位数字(如0405)。

    • 如果num_count == 1,只显示第一个按键编号的两位数字(如04)。

  2. 按键逻辑调整

    Key_Proc函数中:

    • 如果num_count == 2,按下任意按键清零。

    • 如果num_count < 2,存储按键编号。

  3. 数码管显示位数调整

    数码管的动态扫描范围为8位,显示内容通过sprintf格式化为8位数码管的显示格式。

功能实现
  • 按下第一个按键

    • 显示该按键对应的两位数字(如04)。
  • 按下第二个按键

    • 显示两个按键对应的四位数字(如0405)。
  • 按下任意第三个按键

    • 清零显示内容,显示0000
注意事项

确保按键编号S4S19与实际硬件的按键编号一致。

如果按键编号不是从419的连续数字,需要根据实际硬件调整按键编号的判断逻辑。

显示内容前面有4个空格,确保显示内容在8位数码管的中间位置。如果需要调整显示位置,可以修改sprintf中的空格数量。

相关推荐
O。o.尊都假都1 小时前
STM32之SPI——外部FLASH和RFID
stm32·单片机·嵌入式硬件
Hy行者勇哥2 小时前
从零起步搭建基于华为云构建碳排放设备管理系统的产品设计
大数据·人工智能·嵌入式硬件·物联网·华为云
MaoXian_n2 小时前
[IRQ] 01.QEMU ARM 异常 & 中断
linux·驱动开发·嵌入式硬件
gongyuan0734 小时前
思澈LCD-kit测试过程记录
单片机
apolloyhl5 小时前
深入理解 I2C 总线:STM32 外设通信的关键纽带
stm32·单片机·嵌入式硬件
真的想上岸啊5 小时前
学习STC51单片机18(芯片为STC89C52RCRC)
单片机·嵌入式硬件·学习
Camellia03116 小时前
嵌入式学习--江协stm32day1
stm32·嵌入式硬件·学习
清月电子13 小时前
KT6368A通过蓝牙芯片获取手机时间详细说明,对应串口指令举例
单片机·嵌入式硬件·物联网·智能手机·音视频
且撷相思红豆枝14 小时前
一种比较精简的协议
c语言·网络·嵌入式硬件·esp32
_Poseidon15 小时前
2025蓝桥杯WP
蓝桥杯·wp·2025