实验六键盘驱动实践Word下载.docx
《实验六键盘驱动实践Word下载.docx》由会员分享,可在线阅读,更多相关《实验六键盘驱动实践Word下载.docx(28页珍藏版)》请在冰豆网上搜索。
Ø
初始化
在进行中断处理和启动键盘扫描程序以前,首先要进行一些初始化工作,包括中断的初始化,IO端口的初始化,还有缓冲区初始化以及等待队列的初始化。
初始化完了之后,如果没有键按下,任务就会在等待队列上睡眠。
按键缓冲区
本实例中开辟了大小为16的缓冲区用来缓存键值。
中断处理
当有键按下的时候,产生中断,进入中断服务程序。
在中断服务程序中只做两件事情,第一件是配置KB_INT1引脚为输入,第二件就是唤醒在等待队列上睡眠的任务。
该任务被唤醒以后会调用相应的键盘扫描程序来取得键值。
键盘扫描
在键盘扫描程序中需要判断具体的按键位置。
扫描的原理在上一小节已经详细讲解过了,下图是键盘驱动中的按键扫描流程图。
图键盘扫描程序流程图
3实验任务
(1)编写4*4键盘的设备驱动程序,驱动程序中手动定义设备名称及主设备号为214,实现与键盘设备相应的端口配置,中断的申请,以及读写设备的接口函数等。
(2)将驱动编译成模块,并实现模块的加载及卸载。
(3)编写驱动的测试程序,在程序中实现打开4*4键盘设备和上一章中实现的数码管设备。
主循环中不断读取键盘设备,然后将读取的值在数码管上显示。
4实验步骤
(1)实验准备
如果在学生机上操作,请先恢复交叉编译器、根文件系统,方法参见实验四。
把e:
/linuxshar/备份/下的u-boot目录拷贝到e:
\linuxshare目录
把ftp:
//192.168.4.210/u-boot烧写目录下载到e:
/linuxshare目录下
恢复arm-linux内核到虚拟机中(学生自己的电脑如果做过实验四可跳过这一步):
//192.168.4.210/lcd_demo目录下载到e:
/linuxshare目录下,然后将它解压到linux系统中
tar-xjvf/mnt/hgfs/share/lcd_demo/linux_kernel.tar.bz2-C/#解压内核必须文件
tar-xjvf/mnt/hgfs/share/lcd_demo/rootfs.tar.bz2-C/#解压根文件系统
tar-xjvf/mnt/hgfs/share/u-boot/arm-linux-gcc.tar.bz2-C/#解压交叉编译器
exportPATH=/arm2410/crosstool/gcc-4.1.1-glibc-2.3.2/arm-linux/bin/:
$PATH#每开一个新的终端都要执行一次
arm-linux-gcc-v#检查交叉编译器是否正常
(2)配置NFS服务器
把虚拟机网卡类型设置为bridged(桥接模式),设置网卡IP地址为指定IP192.168.5.XX最后一位IP与XP主机最后一位相同,然后做下面的操作
关闭linux下的防火墙,主菜单下->
系统设置->
安全级别
修改linux机器的IP地址
ifdowneth0#关闭网卡
ifconfigeth0hwetherXXXXXXXXXXXX#设置12位16进制物理地址,物理地址请设置成各人不一样,最后两位请设置成与ip地址相同,以保证每台机器不一样
ifupeth0//重新启动网卡
ifconfigeth0192.168.5.XX#后面两位请设置成XP的IP最后两位
在虚拟机的linux中主菜单“系统设置->
服务器设置->
NFS服务器配置中添加NFS共享
设置用户访问权限
设置好后用showmount-e查看自己的共享设置情况
showmount-e#查看自己的设置情况
showmount-eIP#查看指定IP的共享设置情况,同学们之间相互查看
mountip:
/共享目录名本地目录名#请把红字部分设置成实际的IP和目录名
例如:
绿色字样是输入命令后显示出来的内容
Showmount-e192.168.5.7
Exportlistfor192.168.5.7:
/arm2410/rootfs*
lsaaa
mount192.168.5.7:
/arm2410/rootfs/aaa
df
文件系统1K-块已用可用已用%挂载点
/dev/sda2158917888374412671011256%/
/dev/sda110108994268644410%/boot
none12763201276320%/dev/shm
.host:
/61440560204962884094427234%/mnt/hgfs
192.168.5.7:
/arm2410/rootfs/
158917889050076603444860%/root/aaa
(2)编写按键中断驱动程序kb.c文件
以下操作都在nfs文件系统目录(/arm2410/rootfs)下进行,因此先执行cd/arm2410/rootfs命令。
解压事先下载的kb.tar.bz2:
tar-xjvf/mnt/hgfs/share/lcd_demo/kb.tar.bz2-C/arm2410/rootfs/usr
进入kb下的驱动程序目录,查看设备驱动文件:
cd/arm2410/rootfs/usr/kb/driver
geditkb.c
按键中断驱动程序如代码清单1所示:
代码清单1按键中断驱动程序kb.c
//*****************************头文件********************************
#include<
linux/kernel.h>
linux/module.h>
linux/device.h>
linux/types.h>
linux/version.h>
linux/ioctl.h>
linux/errno.h>
linux/sched.h>
linux/delay.h>
linux/init.h>
linux/cdev.h>
linux/fs.h>
linux/mm.h>
asm/io.h>
asm/arch/regs-gpio.h>
asm/uaccess.h>
linux/irq.h>
linux/interrupt.h>
//***********************定义设备结构体及相关宏***************************
#defineDEVICE_NAME"
kb"
//定义设备名
#defineDEVICE_MAJOR214//手动定义键盘的主设备号为214
#defineKB_IRQIRQ_EINT18//定义触发的中断对应的是外部中断18
#defineKB_IRIOS3C2410_GPG10//定义中断对应的I/O端口
#defineKB_SCAN1S3C2410_GPE5//定义扫描线1对应的I/O端口
#defineKB_SCAN2S3C2410_GPE6//定义扫描线2对应的I/O端口
#defineKB_SCAN3S3C2410_GPE7//定义扫描线3对应的I/O端口
#defineKB_SCAN4S3C2410_GPE8//定义扫描线4对应的I/O端口
//I/O端口的功能定义
#defineKB_IRIO_EINT18S3C2410_GPG10_EINT18
#defineKB_IRIO_OUTPS3C2410_GPG10_OUTP
#defineKB_IRIO_INPS3C2410_GPG10_INP
#defineKB_SCAN1_OUTPS3C2410_GPE5_OUTP
#defineKB_SCAN1_INPS3C2410_GPE5_INP
#defineKB_SCAN2_OUTPS3C2410_GPE6_OUTP
#defineKB_SCAN2_INPS3C2410_GPE6_INP
#defineKB_SCAN3_OUTPS3C2410_GPE7_OUTP
#defineKB_SCAN3_INPS3C2410_GPE7_INP
#defineKB_SCAN4_OUTPS3C2410_GPE8_OUTP
#defineKB_SCAN4_INPS3C2410_GPE8_INP
//定义键值
#defineKEY111
#defineKEY122
#defineKEY133
#defineKEY1414
#defineKEY214
#defineKEY225
#defineKEY236
#defineKEY2424
#defineKEY317
#defineKEY328
#defineKEY339
#defineKEY3434
#defineKEY4141
#defineKEY420
#defineKEY4343
#defineKEY4444
//定义缓冲区大小为16,用来存储键值
#defineMAX_BUF_SIZE16
#defineBUF_HEAD(dev.buf[dev.head])//缓冲区头
#defineBUF_TAIL(dev.buf[dev.tail])//缓冲区尾
#defineINCBUF(x,mod)((++(x))&
((mod)-1))//移动缓冲区指针
staticintkb_major=DEVICE_MAJOR;
/*
head:
pressthebutton,thenthehead++
tail:
processthebuttonevent,thenthetail++
*/
//定义键盘设备结构体
structkb_dev
{
structcdevcdev;
//键盘对应一个字符设备结构体
intbuf[MAX_BUF_SIZE];
//按键缓冲区
unsignedinthead,tail;
//按键缓冲区头和尾
wait_queue_head_twq;
//等待队列
};
staticintflag=0;
staticintkeyValue=-1;
//初始键值
staticstructkb_devdev;
===========================键盘扫描功能表==========================
KB_SCAN1KB_SCAN2KB_SCAN3KB_SCAN4KEYVALUE
01111
00112
01013
0110<
---
00114
10115
10016
1010Nothing
01017
10018
11019
1100Nothing
1110Nothing
10100
1100Nothing
1110Nothing
=========================enddescription=============================
//定义键盘扫描的I/O端口
staticunsignedlongkb_table[]={
KB_SCAN1,
KB_SCAN2,
KB_SCAN3,
KB_SCAN4,
KB_IRIO,
//配置键盘的I/O端口
staticunsignedlongkb_cfg_table[]={
KB_SCAN1_OUTP,
KB_SCAN2_OUTP,
KB_SCAN3_OUTP,
KB_SCAN4_OUTP,
KB_IRIO_EINT18,
//*****************************函数声明********************************
voidS3c2410_kb_InitIO(void);
intS3c2410_kb_KeyScan();
intS3c2410_kb_GetKeyVal(intkey);
voidS3c2410_kb_WaitPutupKey(void);
staticintS3c2410_kb_ReadBuf(void);
//*****************************函数定义********************************
======================================================================
S3c2410_kb_InitIO()
描述:
初始化I/O
参数:
无
返回值:
voidS3c2410_kb_InitIO(void)
inti;
for(i=0;
i<
6;
i++){
s3c2410_gpio_cfgpin(kb_table[i],kb_cfg_table[i]);
//配置I/O端口功能
s3c2410_gpio_setpin(kb_table[i],1);
//配置I/O端口的值
}
}
S3c2410_kb_KeyScan()
描述:
扫描键盘,是否有按键被按下
被按下键的个数
intS3c2410_kb_KeyScan()
intret;
msleep(15);
//去抖动
//第一行检测
s3c2410_gpio_cfgpin(KB_SCAN1,KB_SCAN1_OUTP);
//配置第一行扫描线为输出
s3c2410_gpio_setpin(KB_SCAN1,0);
//配置输出值为0
s3c2410_gpio_cfgpin(KB_SCAN2,KB_SCAN2_INP);
//配置第二行扫描线为输入
s3c2410_gpio_cfgpin(KB_SCAN3,KB_SCAN3_INP);
s3c2410_gpio_cfgpin(KB_SCAN4,KB_SCAN4_INP);
if(0==s3c2410_gpio_getpin(KB_IRIO))//有键按下
{
if(s3c2410_gpio_getpin(KB_SCAN2)==0)ret=12;
//第一行第2列的按键按下
elseif(s3c2410_gpio_getpin(KB_SCAN3)==0)ret=13;
//第一行第3列的按键按下
elseif(s3c2410_gpio_getpin(KB_SCAN4)==0)ret=14;
//第一行第4列的按键按下
elseret=11;
//第一行第1列的按键按下
else
//第二行检测
s3c2410_gpio_cfgpin(KB_SCAN2,KB_SCAN2_OUTP);
s3c2410_gpio_setpin(KB_SCAN2,0);
s3c2410_gpio_cfgpin(KB_SCAN1,KB_SCAN1_INP);
s3c2410_gpio_cfgpin(KB_SCAN3,KB_SCAN3_INP);
s3c2410_gpio_cfgpin(KB_SCAN4,KB_SCAN4_INP);
if(0==s3c2410_gpio_getpin(KB_IRIO))
{
if(s3c2410_gpio_getpin(KB_SCAN1)==0)ret=21;
elseif(s3c2410_gpio_getpin(KB_SCAN3)==0)ret=23;
elseif(s3c2410_gpio_getpin(KB_SCAN4)==0)ret=24;
elseret=22;
}
else
//第三行检测
s3c2410_gpio_cfgpin(KB_SCAN3,KB_SCAN3_OUTP);
s3c2410_gpio_setpin(KB_SCAN3,0);
s3c2410_gpio_cfgpin(KB_SCAN1,KB_SCAN1_INP);
s3c2410_gpio_cfgpin(KB_SCAN2,KB_SCAN2_INP);
s3c2410_gpio_cfgpin(KB_SCAN4,KB_SCAN4_INP);
if(0==s3c2410_gpio_getpin(KB_IRIO))
{
if(s3c2410_gpio_getpin(KB_SCAN1)==0)ret=31;
elseif(s3c2410_gpio_getpin(KB_SCAN2)==0)ret=32;
elseif(s3c2410_gpio_getpin(KB_SCAN4)==0)ret=34;
elseret=33;
}
else
{
//第四行检测
s3c2410_gpio_cfgpin(KB_SCAN4,KB_SCAN4_OUTP);
s3c2410_gpio_setpin(KB_SCAN4,0);
s3c2410_gpio_cfgpin(KB_SCAN1,KB_SCAN1_INP);
s3c2410_gpio_cfgpin(KB_SCAN2,KB_SCAN2_INP);
s3c2410_gpio_cfgpin(KB_SCAN3,KB_SCAN3_INP);
if(0==s3c2410_gpio_getpin(KB_IRIO))
{
if(s3c2410_gpio_getpin(KB_SCAN1)==0)ret=41;
elseif(s3c2410_gpio_getpin(KB_SCAN2)==0)ret=42;
elseif(s3c2410_gpio_getpin(KB_SCAN3)==0)ret=43;
elseret=44;
}
else{
ret=-1;
returnret;