IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 蓝桥杯开发板学习——移位运算符法矩阵键盘&矩阵键盘长短按 -> 正文阅读

[嵌入式]蓝桥杯开发板学习——移位运算符法矩阵键盘&矩阵键盘长短按

矩阵键盘是蓝桥杯开发板的一个重要模块,矩阵键盘的扫描思想在以后的单片机学习中也是一个重要的思想,除了通过条件判断的方式实现矩阵键盘,我们还可以通过移位运算符更方便的实现矩阵键盘;

一、移位运算符实现矩阵键盘

二、加入长短按功能

一、移位运算符实现矩阵键盘

我么可以对一行或列进行扫描后,将数据左移四位(<<4)后腾出空间,将下一行或列写入,每次将扫描数据加入后都左移四位,这样我们就可以通过一个16位的变量存储一轮扫描获得的每一行或列的信息,代码实现如下:

unsigned char Key_Scan(void)
{
	unsigned int Key_New;
	unsigned char Key_Value;
	P3 |= 0x0F;
	P44 = 0; P42 = 1; P35 = 1; P34 = 1;  // 第一列
	Key_New = P3 & 0X0F;
	P44 = 1; P42 = 0; P35 = 1; P34 = 1;  // 第二列
	Key_New = (Key_New << 4) | (P3 & 0X0F); 
	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); 
	switch(~Key_New)
	{
		case 0x8000: Key_Value = 1; break;
		case 0x4000: Key_Value = 2; break;
		case 0x2000: Key_Value = 3; break;
		case 0x1000: Key_Value = 4; break;		
		case 0x0800: Key_Value = 5; break;
		case 0x0400: Key_Value = 6; break;
		case 0x0200: Key_Value = 7; break;
		case 0x0100: Key_Value = 8; break;		
		case 0x0080: Key_Value = 9; break;
		case 0x0040: Key_Value = 10; break;
		case 0x0020: Key_Value = 11; break;
		case 0x0010: Key_Value = 12; break;			
		case 0x0008: Key_Value = 13; break;
		case 0x0004: Key_Value = 14; break;
		case 0x0002: Key_Value = 15; break;
		case 0x0001: Key_Value = 16; break;			
		default : Key_Value = 0;
	}
	return Key_Value;
}

将以上函数放入循环中即可实现移位运算符法实现矩阵键盘。

二、加入长短按功能

加入了长短按功能可以使矩阵键盘的功能更加丰富,这里我们采用Delay延时+Count计数的方式获得按键按下的时间,再设定一个阈值来判断长按或是短按,代码实现如下:

//长短按判断函数
unsigned char LongOrShort()
{
	unsigned int TimeCount = 0;
	unsigned int EnterFlag = 0;
	while(Key_Scan() != 0)//使用Key_Scan()函数的返回值作为按键按下的判断标志,其他判断标志亦可
	{
		TimeCount++;
		EnterFlag = 1;//释放信号量,防止直接进入按键按下时间判断(即下面的if和else if)
		Delay(1);//理想情况下计数值每增加一花费1毫秒,但实际略大于1毫秒
                    //想减少误差可增加delay时间,减少判断时Count的阈值(懒得改了)
	}
	if(TimeCount<500 & EnterFlag == 1)
	{
		TimeCount = 0;//清除循环次数计数
		EnterFlag = 0;//清除信号量
		return 0;
	}
	else if(TimeCount>500 & EnterFlag == 1)
	{
		TimeCount = 0;
		EnterFlag = 0;
		return 1;
	}
	return IFLong_OutPut;//若未进入按下时间判断,返回上次值
}

全部函数如下:

#include <STC15F2K60S2.H>
code unsigned char smg_DM[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char Key_OutPut,IFLong_OutPut;
void Delay(unsigned int xms)		//@11.0592MHz
{
		while(xms--)
		{
		unsigned char i, j;
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}

void smg_bit(unsigned char com,unsigned char num)//数码管显示函数
{
	P2 = (P2 & 0x1f) | 0xC0;
	P0 = 1 << (com - 1);
	P2 = (P2 & 0x1f) | 0xE0;
	P0 = smg_DM[num];
	Delay(2);
	P0 = 0xff;
}

unsigned char Key_Scan(void)
{
	unsigned int Key_New;
	unsigned char Key_Value;
	P3 |= 0x0F;
	P44 = 0; P42 = 1; P35 = 1; P34 = 1;  // 第一列
	Key_New = P3 & 0X0F;
	P44 = 1; P42 = 0; P35 = 1; P34 = 1;  // 第二列
	Key_New = (Key_New << 4) | (P3 & 0X0F); 
	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); 
	switch(~Key_New)
	{
		case 0x8000: Key_Value = 1; break;
		case 0x4000: Key_Value = 2; break;
		case 0x2000: Key_Value = 3; break;
		case 0x1000: Key_Value = 4; break;		
		case 0x0800: Key_Value = 5; break;
		case 0x0400: Key_Value = 6; break;
		case 0x0200: Key_Value = 7; break;
		case 0x0100: Key_Value = 8; break;		
		case 0x0080: Key_Value = 9; break;
		case 0x0040: Key_Value = 10; break;
		case 0x0020: Key_Value = 11; break;
		case 0x0010: Key_Value = 12; break;			
		case 0x0008: Key_Value = 13; break;
		case 0x0004: Key_Value = 14; break;
		case 0x0002: Key_Value = 15; break;
		case 0x0001: Key_Value = 16; break;			
		default : Key_Value = 0;
	}
	return Key_Value;
}
	
unsigned char LongOrShort()
{
	unsigned int TimeCount = 0;
	unsigned int EnterFlag = 0;
	while(Key_Scan() != 0)
	{
		TimeCount++;
		EnterFlag = 1;
		Delay(1);
	}
	if(TimeCount<500 & EnterFlag == 1)
	{
		TimeCount = 0;
		EnterFlag = 0;
		return 0;
	}
	else if(TimeCount>500 & EnterFlag == 1)
	{
		TimeCount = 0;
		EnterFlag = 0;
		return 1;
	}
	return IFLong_OutPut;
}

void main()
{
	while(1)
	{
		if(Key_Scan()) Key_OutPut = Key_Scan();
		IFLong_OutPut = LongOrShort();
		if(IFLong_OutPut){P2 = (P2 & 0x1f) | 0x80;P0 = 0;}//长按点亮所有LED,反之关闭所有
		else {P2 = (P2 & 0x1f) | 0x80;P0 = 0xFF;}
		smg_bit(1,Key_OutPut/10);//显示按键编号
		smg_bit(2,Key_OutPut%10);
	}
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-06 15:25:34  更:2021-12-06 15:27:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 12:18:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码