CC2530+74HC164矩阵键盘的设计
最近个大网盘都发出通知,用户的数据将会被清楚,其中就有金山快盘,上大学的时候用的金山,很多重要的资料在其中都保存了一份。现在将其全部下载了下来,然后发现了我的毕业论文,看了一遍,就有了这系类文章。今天将矩阵键盘的设计和编程。
背景
我的毕业设计是基于ZigBee网络的一个hub系统,协调器节点作为中枢,控制器和被控制器都连接在这个中枢上。控制器上使用矩阵键盘那就很平常了。
CC2530的端口数比较小,这也是单片机开发中遇到的常见问题,I/O资源有限,那么我们这边的矩阵键盘也是,在这里我们为了减少I/O端口的使用,我们使用了移位寄存器来减少端口的使用。我们使用的是74HC164。下面对其进行简单的介绍。
74HC164移位寄存器
74HC164是一种由边沿触发的8位移位寄存器器件,其以串行方式一位一位的接受数据输入,然后以并行方式输出一个8位的结果数据。通过两个数据输入端(DSA或DSB)中的一个进行数据的串行输入或者将两个输入端连在一起共同输入。
每次时钟信号(CP)由低变高时,即发生边沿触发,寄存器中的数据都要右移一个比特,这时Q0的电位即为此次的数据输入的结果,是0还是1,也就是数据输入端DSA和DSB的逻辑与。
当主复位(MR)接低电平是,将会使其他端口失效,重置寄存器,输出端口置低电平。
引脚为下图所示:
各引脚说明:
键盘模块设计
矩阵键盘是一种通用的,在工控行业应用广,使用成熟的布局类似于矩阵的按键组。
当实际应用需要很多按钮时,为了尽量减少占用的I/O端口数,通常需要使用一个矩阵键盘。矩阵键盘中每个行线和列线在相交处不直接连通,而是用一个按键作为连接两者的点。这样,如果一个需要包含16个按键的键盘,排成一个4x4的矩阵,就只需要8个端口,比一个I/O连接一个按键减了少一倍的端口数使用,这对于I/O较紧张的系统来说是很重要的,而且当线数越多时,两者之间的区别就越突出,比如再多加一条行线就可以多包含4个按键,而直接使用端口线则只能构成9个按键的键盘。由此可见,在需要的键数较多的情况下,采用矩阵法是在合适不过的。
相比较而言,矩阵式结构肯定比直接相连结构在设计布局上要复杂的多,对于按键按下操作的识别也要复杂。在对矩阵式键盘处理按下事件时一般采用行列扫描法和反转法。本设计使用的是反转法。
一般的反转法的接法是行线和列线接I/O口,其中一列为低,一列为高。比如一个器件有两排端口分别为P0和P1,现在P0接行线,P1接列线,如果P0初始状态为高,那么P1则为低。当所有的按键都是处于未按下的状态,则P0继续保持高电平的状态,P1也保持的原来低电平的状态。如果其中有一个按键被按下,因为按键连接着行列线,P0为高电平状态,P1为低电平状态,所以P0中会有一个I/O端口的电位会被拉低,此时我们就可以知道按下的按键位于哪一行。在检测到P0口有I/O端口电位被拉低后,记录下此时P0口的状态,在C51编程中,一般使用一个8bit数保存。记录下P0状态后,立刻有规律的改变P1的各位的电位,改变的规则为从一个方向开始,依次拉高一个I/O的电位,其他位保持低电平,检查P0的状态是否恢复到原来的高电平,如果为高电平则记录下P1口的状态,此时记录下的P0口和P1口的状态的两个数据,就可以唯一的代表一个按键。
在本课题中,由于CC2530的I/O端口数量少,为了尽量地减少I/O端口的使用,以便以后能够对系统进行拓展,我们使用了8位串入、并出移位寄存器74HC164来减少I/O的使用。我们的主键盘设计为2x8的矩阵,另外还有两个独立的按键(左右按键,现阶段只使用了左按键),一共18个按键,使用中断来通知CPU发生了按键事件,其中主键盘共用一个中断,两个独立的按键各自使用一个中断,不使用轮询,这样有效的提高了按键的稳定性,在复杂系统中提高了按键的响应度。本来主键盘的列线需要8位I/O口,但是现在我们使用74HC164,则列线只需要使用一个I/O口,行线数量不变,现在就只需要3个I/O口就可以完成,这大大降低了I/O的使用数量,为以后扩展提供了I/O空间。
键盘布局如下:
因为使用了中断,所以当按钮按下时,两行按键中会有一行电平被拉低,使用一个与门来得出按键按下的信号,也就是当有按键按下时,与门输入为低电平,触发中断。
键盘驱动程序设计
键盘的第一行与P1_4(P1端口的第5个引脚)相连,第二行与P1_5(P1端口的第6个引脚)相连,单独的左按键与P1_7(P1端口的第8个引脚)相连,74HC164的数据输入端与P1_2(P1端口的第2个引脚)相连,74HC164的时钟线与P1_3(P1端口的第4个引脚)相连,与门的输出端,也就是中断信号线与P1_6相连。
在键盘驱动初始化过程中需要对使用到的端口进行对应的设置。行线所接的端口和中断信号接口都是输入口,74HC164的数据和时钟都是输出口,中断的端口还需要进行相应的功能设置。
P1DIR为P1口的方向寄存器,可位寻址,当某一位设置为0时,此I/O口用于输入,为1时,则用于输出。所以将P1DIR的4~7设置为0,2和3设置为1。P1IEN为P1口的中断使能寄存器,为1开中断,为0关中断,6和7分别用于主键盘和左键盘中断。
D0~D3位被用来对端口的中断触发方式进行设置,取值为0时设置上升沿触发,取值为1时设置下降沿触发。P1_6和P1_7使用下降沿触发。P1SEL为P1功能选择寄存器,0代表普通的I/O口,1代表功能口,中断为功能口,所以P1_6和P1_7为功能口。因为P1使用到中断,所以需要P1口中断使用。P1IFG为端口1的终端状态标志寄存器,当端口的某个I/O口有中断请求时,P1IFG寄存器中相应的位将被置1。例如如果P1_6有中断,那么P1IFG的第六位就会置1,在初始化时,可以将它清空。在P1口的中断函数中,需要先判断P1IFG的第六位和第七位是否为1,如果第六位为1,那就是主键盘有按键按下,否则为左按键。
在程序中,使用了两个变量,一个用来标示是否有键按下,另一个用来记录了按下的按键值。当有按键按下时,中断函数起作用,会改变着两个值,那么当操作系统查询按键标识时,发现它标示有按键发生,然后查询按键值,这样就可以根据按键值进行相关的功能设计。那怎样得出是那个按键按下呢?我们根据硬件和设计的算法得出了一个按键的编码表。
主键盘算法描述如下:
1.获得行线当前的状态Th;
2.将{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}这八个数据依次发送给74HC164直到行线恢复到原来的状态,记录下此时的发送的数据Tl;
3.将Th和Tl进行或操作,得出的即为此按钮的编码。
对于左按键,使用独立的处理函数,给它的编码值为0xff。当有按键按下时,我们根据算法计算出编码,然后使用查表法,就能够确定按下的是那个按键。
code
void send_key(uint8 key_value)
{int i = 0;for (;i < 8;++i){CLCK = 0;S_IN = ((key_value & 0x80) >> 7);CLCK = 1;key_value <<= 1; }delay_ms(1);get_row();
}void get_row()
{//00XX0000//0x30uint8 t = P2;uint8 t2 = P1_5;uint8 t3 = P1_4;row |= t2;row <<= 1;row |= t3;row <<= 6;
}void get_column()
{int j = 0;uint8 temp = 0x00;get_row();if (row != 0xc0) {delay_ms(4);get_row();if (row != 0xc0) {temp = row;} else {return;}} else {return;}for (;j < scan_size;++j){send_key(scan[j]);if (temp != row){is_click = 1;row = 0xc0;result_key = temp | (j + 1);CLEARZERO();break;}}
}//供中断调用
void do_button()
{get_column();
}uint8 click()
{uint8 re = is_click;if (is_click == 1){is_click = 0;}return re;
}
uint8 key()
{return result_key;
}char parse_key(uint8 key_value)
{char re;int i = 0;for (;i<16;i++){if (button_code[i] == key_value){if (i < 10){re = '0' + i;}else{switch(i){case 10:re = '=';break;case 11:re = '+';break;case 12:re = '-';break;case 13:re = '*';break;case 14:re = '/';break;case 15:re = 'C';break;}}break;}}return re;
}void button_init()
{//高电平为输出方式//000011xxP1DIR &= 0x0f;P1DIR |= 0x0c;P1IEN |= 0xc0;//7 6中断是能PICTL |= 0x04;//P1下降沿触发P1INP &= 0x0f;//上拉P1SEL |= 0xc0;//6 7功能口P1SEL &= 0xc0;//0-5 I/O口IEN2 |= 0x10;P1IFG = 0;CLEARZERO();
}void do_left_soft_button()
{is_click = 1;result_key = 0xff;
}#pragma vector = P1INT_VECTOR //外部中断函数
__interrupt void P1_INT(void){IEN2 &= 0xef;;if (P1IFG > 0){if (P1IFG & 0x40) {do_button();} else {//左软键do_left_soft_button();}}IEN2 |= 0x10;P1IFG = 0;
}
其中有很多CC2530初始化中断和端口的代码。主要是send_key
函数,使用在移位过程中,器件特性导致了一定的延时,当时调试的时候,反转的时候一直没用,然后想到74HC164可能在输入和并出有一点的间隔,然后加了延时就OK了。在读行的时候也加了延时,而且读两遍,不然可以就读不出来。
CC2530+74HC164矩阵键盘的设计相关推荐
- 矩阵键盘硬件设计及软件流程
很多情况下我们芯片的IO口不够用,但是有需要很多按键的话,矩阵键盘是一个很好的选择,通过矩阵键盘的设计我们可以用很少的IO来实现多个按键的功能.下面我们来介绍一下矩阵键盘的相关设计,不多说直接上图 上 ...
- 矩阵键盘简易计算机设计报告,矩阵键盘显设计报告..doc
摘要 在日常生活中,我们经常要用到键盘来实现对电子装置的控制.小到手表手机,中到电视电脑,大到各种复杂仪器,都需要通过各种按键来实现各种操作.本次课程设计以按键控制显示为主题,以MSP430G2553 ...
- c语言数码管加法程序怎么写,拜托大神写数码管与矩阵键盘结合设计简易计算器C语言的程序...
我和你用的是一样的,给你一个我买板子送的矩阵程序 //4*4键盘检测程序,按下键后相应的代码显示在数码管上 #include sbit beep=P2^3; sbit dula=P2^6; sbit ...
- 单片机实验说明<四>矩阵键盘与LCD基本使用
实验四 矩阵键盘识别设计 设计要求: 对4×4矩阵式键盘电路的键值进行编码,编程实现在LCD液晶显示器上显示每个按键的"0-F"序号 电路设计: 软件代码: #include &q ...
- 4x4矩阵键盘(STM32F103C8)
一.前言 使用STM32F103C8T6最小系统,实现4x4矩阵键盘的键值上报,通过串口调试助手打印相关的键值,使用的是逐行逐列扫描法,通过库函数实现. 二.概述 ( 一)矩阵键盘简述 矩阵键盘是单片 ...
- 单片机(二):3个IO扩展n*8个IO,基于74hc595与74hc165的8x8矩阵键盘
3个IO通过一片74hc595扩展8个输出IO,3个IO通过一片74hc1655扩展8个输入IO,最终成为8X8的矩阵键盘.对于普通的矩阵键盘,再加入防止鬼键.消抖和按下与松开识别. 一.74hc59 ...
- 进阶项目(11) 矩阵键盘程序设计讲解
写在前面的话 在使用按键的时候,如果按键不多的话,我们可以直接让按键与FPGA相连接,但是如果按键比较多的时候,如果还继续使用直接让按键与FPGA相连接的话,会大量增加FPGA端口的消耗,为了减少FP ...
- Arduino智能闹钟设计(8x8矩阵键盘+LCD显示)
Arduino智能闹钟设计(8x8矩阵键盘+LCD显示+蜂鸣器歌曲) 作者:STCode(公众号同名) 1.效果描述: 本设计基于Arduino Nano控制器,主要功能为定时闹钟和环境温湿度显示,使 ...
- 单片机实验——十六路抢答器 ,抢答器是一种应用十分广泛的设备,在各种竞赛、抢答场合中,它能迅速、客观地分辨出最先获得发言权的选手。本设计采用矩阵键盘节省输入的I/O口,带有奇偶校验的双单片通信。
1.实验内容与要求 抢答器是一种应用十分广泛的设备,在各种竞赛.抢答场合中,它能迅速.客观地分辨出最先获得发言权的选手.本设计采用矩阵键盘节省输入的I/O口,带有奇偶校验的双单片通信,确保发送的正确接 ...
- 矩阵键盘简易计算机设计报告,矩阵键盘设计实验报告.doc
南 京 林 业 大 学 实验报告 基于AT89C51 单片机4x4矩阵键盘接口电路设计 课 程 机电一体化设计基础 院 系 机械电子工程学院 班 级 学 号 姓 名 指导老师 杨雨图 201 南京林业 ...
最新文章
- ExecuteNonQuery() 返回值
- CTF-RSA-tool 安装全过程
- 在R.java中新建自定义的新类
- 用Xamarin 实现园友的 :Android浮动小球与开机自启动
- OpenCV安全栅栏摄像头security barrier camera的实例(附完整代码)
- JavaSE 学习参考:变量(1)
- java通过poi读取excel中的日期类型数据或自定义类型日期
- Django的各种初识
- java classifier_Java 朴素贝叶斯分类器、SVM(5行代码)实现乳腺癌分类
- 大型K8s沙龙来啦,火速报名——Kubernetes Cloud Native Meetup
- MyBatis框架学习笔记02:利用MyBatis实现CRUD操作
- mysql中使用case when语句
- Maven技巧和窍门:高级Reactor选项
- 图片字符串base64的判断
- bootstrap java web_JavaWEB开发05_Bootstrap
- centos7 如何安装部署k8s_如何在CentOS 7上正确安装Chromium
- Nginx的入门详解
- Exploring Visual Relationship for Image Captioning
- Jenkins安装插件报错解决方法
- wd 文件服务器客服电话,wd 云服务器