实验三按键控制.docx

上传人:b****7 文档编号:15392415 上传时间:2023-07-04 格式:DOCX 页数:19 大小:260.89KB
下载 相关 举报
实验三按键控制.docx_第1页
第1页 / 共19页
实验三按键控制.docx_第2页
第2页 / 共19页
实验三按键控制.docx_第3页
第3页 / 共19页
实验三按键控制.docx_第4页
第4页 / 共19页
实验三按键控制.docx_第5页
第5页 / 共19页
实验三按键控制.docx_第6页
第6页 / 共19页
实验三按键控制.docx_第7页
第7页 / 共19页
实验三按键控制.docx_第8页
第8页 / 共19页
实验三按键控制.docx_第9页
第9页 / 共19页
实验三按键控制.docx_第10页
第10页 / 共19页
实验三按键控制.docx_第11页
第11页 / 共19页
实验三按键控制.docx_第12页
第12页 / 共19页
实验三按键控制.docx_第13页
第13页 / 共19页
实验三按键控制.docx_第14页
第14页 / 共19页
实验三按键控制.docx_第15页
第15页 / 共19页
实验三按键控制.docx_第16页
第16页 / 共19页
实验三按键控制.docx_第17页
第17页 / 共19页
实验三按键控制.docx_第18页
第18页 / 共19页
实验三按键控制.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

实验三按键控制.docx

《实验三按键控制.docx》由会员分享,可在线阅读,更多相关《实验三按键控制.docx(19页珍藏版)》请在冰点文库上搜索。

实验三按键控制.docx

实验三按键控制

实验三基于ARM92440linux系统的按键控制

一、实验内容

(1)学习按键驱动原理,了解ARM实验箱上如何控制键盘的输入

(2)设计程序在ARM实验箱上能够正确读出被按的键位。

(3)优化按键的部分源程序,能准确写出按照自己的要求设计的按键输入代码,掌握通过CPU的I/O扩展键盘的方法。

(4)将写出的代码载入到ARM实验箱上,验证所写的按键程序是否正确。

二、实验目的

(1)熟悉Linux操作系统。

(2)熟悉嵌入式系统Ubuntu的开发环境和流程,熟练掌握常用的指令。

(3)掌握按键程序的设计思路,并根据提供的源代码将其简化,编程实现键盘的驱动,通过按键可以在超级终端上显示相应的键值。

三、实验设备及工具

硬件:

ARM9S3C2440实验箱、PC(CPU:

Inteli3,内存:

4GB以上)、交叉网线、串口线

软件:

VMWare10.0.2、ubuntu14.04.1、SecureCRT

四、实验原理

矩阵键盘又称为行列式键盘,它是用4条I/O线做为行线,4条I/O线作为列线组成的键盘。

在行线和列线的每一个交叉点上,设置一个按键。

这样键盘中按键的个数是4*4个(如图1),这种行列式键盘结构能够有效的提高嵌入式系统MCU的I/O的利用率(如果采用直连式的键盘,16个按键需要16个I/O口,此举节省了8个I/O口)。

S3C2440上key4×4的硬件电路引脚如图:

图1:

S3C2440上key4×4的硬件电路引脚

根据图1找到相应的输入输出接口,通过ARM的rPDATC(低四位)和EINT4567四个中断口扩展4×4的键盘,编程实现键盘的驱动,通过按键可以在超级终端上显示相应的键值。

在初始化阶段,所有的行(输出端口)被强行设置为低电平。

在没有任何键按下时,所有的列(输入端口)将读到高电平。

任何键的闭合将造成其中的一列变为低电平,因此只需再确定是哪一行即可定位被按键的位置。

在所有的行中,保持一行为低,其余为高,循环所有行,此时能使列仍然输出低的行即为按键的行号。

实验板行扫描线分别连接与PX270的KP_MKOUT0、KP_MKOUT1、KP_MKOUT2、KP_MKOUT6端口相连,列扫描线分别与PX270的KP_MKIN0、KP_MKIN1、KP_MKIN2、KP_MKIN5端口相连。

图2

PX270支持最大8根行扫描线,8根列扫描线总计64个按键的矩阵键盘,通过对键盘控制寄存器KPC的操作,我们可以自由的定制键盘的扫描工作方式,行扫描线,列扫描线的个数。

现在对矩阵键盘驱动中要使用的KPC寄存器主要控制位进行简要的说明(如图3)。

图3

BIT11:

MIE:

矩阵键盘中断使能1:

矩阵键盘中断0:

矩阵键盘不中断

BIT12:

ME:

矩阵键盘工作模式使能1:

矩阵键盘工作0:

矩阵键盘不工作

BIT13~BIT20:

MS0~MS7:

行扫描线使能1:

对应的行扫描线工作0:

对应的行扫描线不工作

BIT23~BIT25:

MKCN:

行扫描线个数统计000:

0个111:

7个

BIT26~BIT28:

MKRN:

列扫描线个数统计000:

0个111:

7个

BIT29:

ASACT:

激活矩阵扫描自动扫描过程1:

激活0:

不激活

BIT30:

AS:

矩阵扫描工作模式选择1:

自动扫描0:

手动扫描

设置好KPC之后,就可以调用PX270的键盘扫描功能模块进行键值的扫描。

现在就实验板实际连接的电路对扫描的键值加以说明。

实验板的16键矩阵键盘的行扫描线是KP_MKOUT0、KP_MKOUT1、KP_MKOUT2、KP_MKOUT6,列扫描线是KP_MKIN0、KP_MKIN1、KP_MKIN2、KP_MKIN5,其对应PX270内置的列扫描线位于第0、1、2、6列,对应的行扫描线为0、1、2、5行。

以按下16键矩阵键盘的第4行,第4列的按键为例,根据前面对矩阵键盘工作原理的分析可以知道,其对应的键值应该是PX270第6列,第5行所对应的键值。

故实验板上16键矩阵键盘的键值如下表所示:

第〇列

第一列

第二列

第六列

第〇行

0x00(0,0)

0x01(0,1)

0x02(0,2)

0x06(0,6)

第一行

0x10(1,0)

0x11(1,1)

0x12(1,2)

0x16(1,6)

第二行

0x20(2,0)

0x21(2,1)

0x22(2,2)

0x26(2,6)

第五行

0x50(5,0)

0x51(5,1)

0x52(5,2)

0x56(5,6)

表1

键盘控制过程就是让微处理器按有规律的时间间隔查看键盘矩阵,以确定是否有键被按下。

一旦处理器判定有一个键按下,键盘扫描软件将过滤掉抖动并且判定哪个键被按下。

每个键被分配一个称为扫描码的唯一标识符。

应用程序利用该扫描码,根据按下的键来判定应该采取什么行动。

某一时刻按下多个键(意外地或者故意地)的情况被称为转滚。

能够正确识别一个新键被按下(即使n-1个键已经被按下)的任何算法被称为具有n键转滚的能力。

本章提出的矩阵键盘系统设计,在这种系统中用户输入可能发生相继按键。

这些系统通常不需要具有像终端或者计算机系统上的键盘的全部特征那样的键盘。

五、实验步骤

1.先对老师给的程序进行编译,先把源代码拷贝在虚拟机并共享目录VM_share下,然后用cd命令逐层进入源代码所在目录,如图所示,在led文件夹下,有bsp.c、main.c、以及他们的头文件,除此之外还有makefile文件和以前编译生成的可执行文件等等。

①修改main.c里的头文件

把第一行的改为:

②从错误中发现makefile环境变量和我们之前配置的不一样,所以我们还要修改makefile文件

重新配置CROSS_COMPILE,把第二行注释掉改为如下行:

完成后并保存。

2.输入cd命令进入所在key4×4路径之后,首先执行makeclean命令清除以前make产生的文件,运行效果如下:

产生的两个.o文件、make、led的可执行文件都被清除了。

3.使用make命令进行编译

4.编译成功后,把生成的key_4x4文件用U盘拷贝到串口终端上使用./命令执行。

5.修改按键程序:

在key_4x4平行的目录中新建yoyokey文件夹,将新建的.c文件放在该文件夹中,之后编写需要的.h文件,这是前者需要的头文件,同样把.h文件放在yoyokey文件夹中最后把上面的makefile文件直接拷贝到这个文件夹里

6.修改完成后,执行cd命令进入led_test文件夹使用make命令进行编译

7.编译成功之后,把生成的key4x4文件拷贝到U盘在串口终端上使用./命令执行,当按键按下时运行效果如下:

六、实验小结

通过本次课的学习,让我更熟悉了Linux操作系统的使用,熟悉了嵌入式系统Ubuntu的开发环境和流程以及常用的指令。

掌握了键盘驱动的原理和ARM9S3C2440开发板的通用I/O接口以及他们的工作原理,加深了对基于linux的ARM开发的基本流程的学习。

 

附录

#include

#include

#include

#include

#include

#include

#include

unsignedint*PIOB_BaseVirt;/*端口PORTB虚拟基地址0x56000040*/

unsignedint*PIOE_BaseVirt;/*端口PORTE虚拟基地址0x56000040*/

unsignedint*PIOF_BaseVirt;/*端口PORTF虚拟基地址0x56000050*/

unsignedint*PIOG_BaseVirt;/*端口PORTG虚拟基地址0x56000060*/

unsignedint*PIOJ_BaseVirt;/*端口PORTJ虚拟基地址0x560000d0*/

unsignedint*ADC_BaseVirt;/*端口ADC控制器的虚拟基地址0x560000d0*/

#defineS3C2440_GPXCON_OFFSET0x0

#defineS3C2440_GPXDAT_OFFSET0x4

#defineS3C2440_GPXUP_OFFSET0x8

#defineS3C2440_PIO_PJ7S3C2440_BASE_PIOJ,((unsignedint)1<<7)//PinControlledbyPC7

#defineS3C2440_PIO_PJ5S3C2440_BASE_PIOJ,((unsignedint)1<<5)//PinControlledbyPC5

#defineS3C2440_BASE_PIOJ((unsignedint)PIOJ_BaseVirt)

#defineS3C2440_PIO_PJ0S3C2440_BASE_PIOJ,((unsignedint)1<<0)//PinControlledbyPC0

#defineS3C2440_PIO_PJ10S3C2440_BASE_PIOJ,((unsignedint)1<<10)//PinControlledbyPC10

#defineS3C2440_PIO_PJ8S3C2440_BASE_PIOJ,((unsignedint)1<<8)//PinControlledbyPC8

#defineS3C2440_PIO_PJ12S3C2440_BASE_PIOJ,((unsignedint)1<<12)//PinControlledbyPC12

#defineS3C2440_PIO_PJ1S3C2440_BASE_PIOJ,((unsignedint)1<<1)//PinControlledbyPC1

#defineS3C2440_PIO_PJ2S3C2440_BASE_PIOJ,((unsignedint)1<<2)//PinControlledbyPC2

#defineS3C2440_PIO_PJ4S3C2440_BASE_PIOJ,((unsignedint)1<<4)//PinControlledbyPC4

#defineS3C2440_PIO_PJ11S3C2440_BASE_PIOJ,((unsignedint)1<<11)//PinControlledbyPC11

#defineKEYA_R_1S3C2440_PIO_PJ0//这4个一直保持输入

#defineKEYA_R_2S3C2440_PIO_PJ10

#defineKEYA_R_3S3C2440_PIO_PJ8

#defineKEYA_R_4S3C2440_PIO_PJ12//当给它高时,这个PB29一直是2.45V,拉不高

#defineKEYA_D_1S3C2440_PIO_PJ4

#defineKEYA_D_2S3C2440_PIO_PJ1

#defineKEYA_D_3S3C2440_PIO_PJ2

#defineKEYA_D_4S3C2440_PIO_PJ11

/*

*

*函数描述延迟us

*参数延时时间,单位us

*返回无

*

*/

voiduudelay(unsignedintus)

{

unsignedinti,j;

for(i=0;i

for(j=0;j<170;j++);

}

/*

*

*函数描述延迟ms

*参数延时时间,单位ms

*返回无

*

*/

voidmmdelay(unsignedintms)

{

unsignedinti,j;

for(i=0;i

for(j=0;j<30000;j++);

}

intopen_port_device(void)//别名AT91RM9200_PORTABCD_init(void)

{

unsignedchar*gpioports;

intfdMem=-1;

fdMem=open("/dev/mem",O_RDWR);

if(fdMem<0)

{

printf("Can'topenmemdeviceentry.Errornumber:

%d\n",fdMem);

return-1;

}

gpioports=mmap(0,getpagesize(),PROT_READ|PROT_WRITE,MAP_SHARED,fdMem,

0x56000000);

if(gpioports==MAP_FAILED)

{

printf("\nMapfailed!

\n");

return-1;

}

PIOB_BaseVirt=(unsignedint*)(gpioports+0x10);

PIOE_BaseVirt=(unsignedint*)(gpioports+0x40);

PIOF_BaseVirt=(unsignedint*)(gpioports+0x50);

PIOG_BaseVirt=(unsignedint*)(gpioports+0x60);

PIOJ_BaseVirt=(unsignedint*)(gpioports+0xD0);

//printf("*ADC_BaseVirt:

0x%x\r\n",(*(volatileunsignedint*)(ADC_BaseVirt)));

return0;

}

/*

*

*函数描述读端口的某一个PIN的数值===>如PA.0(端口A的引脚1)

*参数unsignedintpio_port_base_addr,端口PIO基地址

*unsignedintport_bit端口的某位

*返回读取的数据(0or1)

*

*/

intport_read(unsignedintpio_port_base_addr,

unsignedintport_bit)

{

unsignedintval/*,i*/;

//对应的那两位配置为00,INPUT

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXCON_OFFSET))&=~(0x0001<<((int)log2((double)port_bit)*2));

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXCON_OFFSET))&=~(0x0001<<((int)log2((double)port_bit)*2+1));

//对应的那1位UP配置为0,enable

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXUP_OFFSET))&=~port_bit;

val=(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXDAT_OFFSET))&port_bit;

//printf("CON:

0x%x,DAT:

0x%x,port:

%f\r\n",(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXCON_OFFSET)),

//(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXDAT_OFFSET)),log2((double)port_bit));

return(val?

1:

0);

}

/*

*

*函数描述读端口的某一个PIN的数值===>如PA.0(端口A的引脚1)

*参数unsignedintpio_port_base_addrPIO基地址

*unsignedintport_bit,某位

*intvalue值:

0,1

*返回0成功

*-1失败

*

*/

intport_write(unsignedintpio_port_base_addr,//PIO基地址

unsignedintport_bit,//某位

intvalue)//值:

0,1

{

//对应的那两位配置为01,OUTPUT

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXCON_OFFSET))|=(0x0001<<((int)log2((double)port_bit)*2));

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXCON_OFFSET))&=~(0x0001<<((int)log2((double)port_bit)*2+1));

//对应的那1位UP配置为0,enable

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXUP_OFFSET))&=~port_bit;

if(value)

{

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXDAT_OFFSET))|=port_bit;

}

else

{

/*ClearOutput*/

(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXDAT_OFFSET))&=~port_bit;

}

//printf("CON:

0x%x,DAT:

0x%x,port:

%f\r\n",(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXCON_OFFSET)),

//(*(volatileunsignedint*)(pio_port_base_addr+S3C2440_GPXDAT_OFFSET)),log2((double)port_bit));

return0;

}

//返回同时按下的键个数,buf中将放入同时按下的所有键的ASCII码

//始终保持KEYA_R_1,KEYA_R_2,KEYA_R_3,KEYA_R_4为input功能

//注意:

调用此函数的时间间隔不能太短,机械按键需要一定的延时“去抖”

unsignedcharScanKey(char*buf)

{//ESC=27,ENTER=13

charkeyArr[4][4]={{'0','1','2','3'},

{'4','5','6','7'},

{'8','9','A','B'},

{'C','D','E','F'}};

volatileunsignedcharhScan,vScan,vTemp,bNumPressed=0,i,j;

/*

*同一个端口从从写到读,需要注意一点,一般读端口时,如果端口引脚悬空,读到的是1

*因为在读状态上拉电阻起作用(reset后缺省打开)

*但是端口从写到读切换要注意,且换到读后,第一个读,是上次write的状态,第二次读才是正常值

*/

port_write(S3C2440_PIO_PJ7,0);//245方向切换

port_write(S3C2440_PIO_PJ5,1);//245方向切换,245做输入

port_write(KEYA_R_1,0);

port_write(KEYA_R_2,0);

port_write(KEYA_R_3,0);

port_write(KEYA_R_4,0);

mmdelay

(1);

vScan=port_read(KEYA_D_1)<<4;//放到高4位

vScan|=port_read(KEYA_D_2)<<5;

vScan|=port_read(KEYA_D_3)<<6;

vScan|=port_read(KEYA_D_4)<<7;

vScan=(~vScan);

vScan=vScan>>4;

mmdelay

(1);

port_write(S3C2440_PIO_PJ7,1);//245方向切换,245做输入

port_read(KEYA_R_1);port_read(KEYA_R_1);//状态切换的空读

port_read(KEYA_R_2);port_read(KEYA_R_2);

port_read(KEYA_R_3);port_read(KEYA_R_3);

port_read(KEYA_R_4);port_read(KEYA_R_4);

mmdelay

(1);

//

port_write(S3C2440_PIO_PJ5,0);//245方向切换,245做输入

port_write(S3C2440_PIO_PJ7,1);

port_write(KEYA_D_1,0);

port_write(KEYA_D_2,0);

port_write(KEYA_D_3,0);

port_write(KEYA_D_4,0);

mmdelay

(1);

//

//

hScan=port_read(KEYA_R_1)<<4;//放到高4位

hScan|=port_read(KEYA_R_2)<<5;

hScan|=port_read(KEYA_R_3)<<6;

hScan|=port_read(KEYA_R_4)<<7;

hScan=(~hScan);

hScan=hScan>>4;

//printf("hScan:

0x%x-------v

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2