湘南学院
课程设计报告
课程名称: 嵌入式系统 设计题目: 键盘驱动 专业班级: 学生姓名: 学生学号: 指导老师:
2013年 12月 23 日
目 录
1.概述 .................................................................................................................. 1 1.1背景 .............................................................................................................. 1
1.2设计要求 ...................................................................................................... 1 1.3开发环境 ...................................................................................................... 1 1.4关键技术 ...................................................................................................... 1 2.概要设计 .......................................................................................................... 2 2.1、软件结构 ................................................................................................... 2 2.2、各功能模块设计 ....................................................................................... 2
2.2.1 S3C2410的I/O介绍………………………………………..2 2.2.2 S3C2410中断介绍…………………………………………...3 2.2.3 按键驱动………………………………………………………..4 3.详细设计与实现 .............................................................................................. 7 3.1、界面说明 ................................................................................................... 7 3.2、程序流程 ................................................................................................... 8 3.3、关键代码 ................................................................................................... 8 4.测试分析 ........................................................................................................ 12 4.1.测试方法.................................................................................................... 12 4.2 测试用例 ................................................................................................... 12 4.3 测试结果 ................................................................................................... 12 5.小结 ................................................................................................................ 13 参考文献 ............................................................................................................... 13
嵌入式 课程设计报告
1.概述
1.1背景
许多嵌入式系统,尤其是一些人机交互(HMI)较频繁的嵌入式系统,键盘是一种应用最为广泛的输入设备。由于嵌入式设备的功能互异性,为其提供一种通用性键盘是不可行的,一般都需要根据嵌入式系统的实际功能来设计所需的特殊键盘,并实现相应的驱动程序。
在嵌入式设备上扩展键盘的常用方式是通过使用CPU的GPIO端口扫描实现的,显然,这种方式会占用系统的GPIO资源,特别是在GPIO资源比较紧张而按键又较多的系统,这个问题就特别突出。当然,也可以通过外扩GPIO(如8255等)或外扩专用的键盘接口(如8279等)方式实现,但这种方式显然增加了系统的复杂度,在实际系统设计中颇感不便。因此我们将借用嵌入式知识用软件来实现键盘驱动程序。
1.2设计要求
用户设计行列键盘接口,一般常采用三种方法读取键值。一种是中断式,另外两种是扫描法和发转法。
键盘扩展我们将采用SPI接口的键盘显示控制芯片ZLG7289。 所包含的功能应该有:硬件中断,按键识别,键值显示。
1.3开发环境
硬件环境:S3C2410嵌入式开发板,JTAG仿真器。
软件环境:PC机操作系统Win98,Win2000或WinXP,ADS1.2集成开发环境,仿真器驱动程序,超级终端驱动程序。
1.4关键技术
中断式技术的应用,在键盘按下时产生一个外部中断通知 CPU,并由中断处理程序通过不同的地址读取数据线上的状态,判断哪个按键被按下。本实验采用中断式实现用户键盘接口。
中断源向 CPU 发出中断请求,若优先级别最高,CPU 在满足一定的条件下,可以中断当前程序的运行,保护好被中断主程序的断点及现场信息。然后,根据中断源提供的信息,找到中断服务子程序的入口地址,转去执行新的程序段,这就是中断响应。CPU 响应中断是有条件的,如内部允许中断、中断未被屏蔽、当前指令执行完等。
CPU 响应中断以后,就会终止当前的程序,转去执行一个中断服务子程序,以完成为相应设备的服务。
a.保护现场(由一系列的压栈指令完成)。目的是为了保护那些与主程序中有冲突的寄存
- 1 -
嵌入式 课程设计报告
器,(如 R0,R1,R2 等),如果中断服务子程序中所使用的寄存器与主程序中所使用的寄存器等没有冲突的话,这一步可以省略。
b.中断处理,中断处理程序在检查到相应的中断源后,调用对应的中断处理程序完成。 c.恢复现场并返回(由一系列的出栈指令完成)。是与保护现场对应的,但要注意数据恢复的次序,以免混乱。由于中断服务子程序需要打断主程序的执行,因此其处理应该及时完成,较长时间的延时将导致系统性能严重下降。
2.概要设计
2.1、软件结构
初始化部分。这部分包括硬件层和软件层上的初始化。在本例中,需要先对矩阵电路和SN74hc164芯片所使用到的GPIO端口作配置,以使CPU可以对它们进行控制和访问。为了要将某个GPIO端口配置成输入输出或者是中断源,需要在对应的GPIO控制寄存器中设置正确的值,具体的值可以通过查阅S3C2410开发板手册来获得。比如,为了将GPB1设置成SN74hc164的输入端,需要将GPBCON这个控制字中2,3两位设置成二进制的01,为了将GPG6设置成电压低跳变中断源,需要将GPGCON中12,13两位设置成二进制的10。在完成了硬件初始化操作以后,就是软件层上的初始化了。首先将键盘中断处理函数注册到系统,然后设置好一个定时器结构,以便在中断发生时将其挂到内核的定时器队列中去,该定时器将触发对键盘的扫描操作。最后通过SN74hc164将矩阵电路的16列置零。
2.2、各功能模块设计 2.2.1 S3C2410的I/O介绍
(1)输入输出端口引脚:
PortA(GPA):32个输入/输出端口 PortB(GPB):11个输入/输出端口 PortC(GPC):16个输入/输出端口 PortD(GPD):16个输入/输出端口 PortE(GPE):16个输入/输出端口 PortF(GPF):8个输入/输出端口 PortG(GPG):16个输入/输出端口 PortH(GPH):11个输入/输出端口
- 2 -
嵌入式 课程设计报告
(2)端口控制说明
端口配置寄存器(GPACON――GPHCON)
在S3C2410中,大部分的引脚是复用的,所以必须对于每个引脚要求定义一个功能,端口配置寄存器定义了每个引脚的功能。 端口数据寄存器(GPADAT――GPHDAT)
如果端口配置成输出端口,数据能够被写到端口数据寄存器的对应位,然后通过管脚输出。如果端口配置成输入端口,能从端口数据寄存器对应的位中读出管脚上的电平。 端口上拉寄存器(GPBUP――GPHUP)
端口上拉寄存器控制着每个端口组的上拉寄存器的使能或禁止,当对应位为0,这个引脚的上拉寄存器是允许的,当为1时,上拉寄存器是禁止的。
2.2.2 S3C2410中断介绍
(1)源中断请求寄存器SRCPND
SRCPND寄存器32位中的每一位对应着一个中断源,每一位被设置为1,则相应的中断源产生中断请求并且等待中断被服务。因此,这个寄存器表明了哪个中断源在等待中断请求被处理。注意,SRCPND寄存器的每一位时由中断源自动设置的,而不管INTMSK寄存器中的屏蔽位。另外,SRCPND寄存器不影响中断控制器的优先级逻辑。
在指定中断源的中断服务程序中,SRCPND寄存器相对应的位必须被清楚来正确相应来自统一中断源的中断请求。如果从ISR返回而没有清除相应的位,也就是SRCPND寄存器中的对应位还是为1,那么就会一直响应这个中断请求。 对应位清楚的时间依赖于用户的需求,如果想要从同一中断源接收另一次有效中断请求,你在第一次就应该清除相应的位,并且使能中断。 (2)中断请求寄存器INTPND
中断请求寄存器32位中的每一位对应着相应的中断请求,经过优先级逻辑后,INTPND寄存器只能有一位被设置为1,并且向ARM产生中断请求。在IRQ中断服务子程序,能够读取这个寄存器的指来决定32个中断源的那一个中断被服务。
同SRCPND寄存器,在中断服务子程序里,这个寄存器的值需要被清除。我们可以向INTPND寄存器写一个数据来清楚寄存器的制定位。 (3)外部中断判断寄存器(EINTPND)
EINTPND用来判断外部的20个中断源(EINT[23:4]),用户可以通过向EINTPEND寄存器的相应位写“1”,这样可以清楚该位。
- 3 -
嵌入式 课程设计报告
2.2.3 按键驱动
(1)按键驱动程序流程图
图4 按键驱动程序流程图
设计行列键盘接口,一般常采用 3 种方法读取键值。一种是中断式,另外两种是扫描法和反转法。我们采用的是中断式。
中断式:在键盘按下时产生一个外部中断通知 CPU,并由中断处理程序通过不同的地址读取数据线上的状态,判断哪个按键被按下。本实验采用中断式实现用户键盘接口。中断方式的原理示意图如图5所示:
图5 中断处理示意图
中断源向 CPU 发出中断请求,若优先级别最高,CPU 在满足一定的条件下,可以中断当前程序的运行,保护好被中断主程序的断点及现场信息。然后,根据中断源提供的信息,找到中断服务子程序的入口地址,转去执行新的程序段,这就是中断响应。CPU 响应中断是有条件的,如内部允许中断、中断未被屏蔽、当前指令执行完等。 (2)中断服务子程序
CPU 响应中断以后,就会终止当前的程序,转去执行一个中断服务子程序,以完成为相应设备的服务。
- 4 -
嵌入式 课程设计报告
中断服务子程序的一般结构如下图6所示:
图6 中断服务子程序处理流程
a.保护现场(由一系列的压栈指令完成)。目的是为了保护那些与主程序中有冲突的寄存器,(如 R0,R1,R2 等),如果中断服务子程序中所使用的寄存器与主程序中所使用的寄存器等没有冲突的话,这一步可以省略。
b.中断处理,中断处理程序在检查到相应的中断源后,调用对应的中断处理程序完成。 c.恢复现场并返回(由一系列的出栈指令完成)。是与保护现场对应的,但要注意数据恢复的次序,以免混乱。由于中断服务子程序需要打断主程序的执行,因此其处理应该及时完成,较长时间的延时将导致系统性能严重下降。
扫描法:对键盘上的某一行送低电平,其它行为高电平,然后读取列值。若列值中有一位是低,则表明该行与低电平对应列的键被按下;否则扫描下一行。
反转法:先将所有行扫描线输出低电平,读列值。若列值有一位是低,则表明有 键按下;然后所有列扫描线输出低电平,再读行值。根据读到的值组合就可以得到相应的键码。 (3)ZLG7289 1工作原理 ○
ZLG7289 可用行线 R0~R2 和列线 C0~C7 构成矩阵键盘。同时在芯片内部可自动完成扫描、译码、去抖动处理等任务。当 ZLG7289 检测到有效的按键时,按键有效指示“KEY”引脚将从低电平变为高电平,并一直保持到按键代码被读取为止。“KEY”为高电平期间,如果 ZLG7289 接收到“读键盘数据”命令,(即“CS”管脚变低),则输出当前按键的键盘代码,ZLG7289键盘代码的范围为00H-0FH。如果在接收到“读键盘数据”时没有按键按下,ZLG7289 将输出 0xFFH。在一次读键盘过程完成后,按键有效指示“KEY”将变为低电平。利用按键有效指示“KEY”与单片机的外部中断端相连,可完成具有中断的键盘监控功能,从而提高 CPU 的工作效率,减少按键响应时间。ZLG7289工作时需要外接RC振荡电路以供系统工作,RC元件的典型值 R=3.3kΩ,C=20pF,此时的振荡频率约为 4MHz,由于此振荡频率较高,故在印制电路板布线时,所有元件尤其是振荡
- 5 -
嵌入式 课程设计报告
电路的元件应尽量靠近芯片,并尽量使电路连线最短。
ZLG7289 的 RESET 复位端在一般应用情况下,可以直接与正电源连接,在需要较高可靠性的情况下,可以连接外部 RC 复位电路,在上电或接收到 RESET 端的复位信号后,ZLG7289 大约需要经过 25ms 的复位时间才会进入到正常工作状态。程序中应尽可能地减少 CPU 对 ZLG7289 的访问次数,以提高程序的效率。
值得注意的是,如果有 2 个键同时被按下,则 ZLG7289 只能给出其中一个按键的代码,因此 ZLG7289 不适合应用于需要 2 个或 2 个以上按键同时被按下的应用场合。如确实需要双键组合使用或组合增加键盘数量,可在单片机的某 I/O 脚接入一键与 ZLG7289 共同组双键键盘监控电路。 2串行接口及时序 ○
ZLG7289采用串行方式与单片机或微处理器接口,串行数据从“DIO”引脚输出,并由“CLK”端发出同步时钟脉冲。当ZLG7289检测到有键按下时,按键有效指示“KEY”变高,单片机检测到“KEY”信号变高后,便将片选端“CS”拉低,从而使得ZLG7289 将取得的键盘数据在“CLK”引脚的上升沿从“DIO”脚依次送出。在单片机发出8个时钟脉冲后,即可从“DIO”端读取8位键值编码,该编码值的D7为最高位,D0为最低位,然后单片机再使片选“CS”变高,并使“KEY”端重新输出低电平,至此,读键值过程结束。ZLG7289的串行接口时序如图7所示。图中,T1表示从“CS”下降沿至第一个CLK 上升沿的延时,典型值为 15µs;T2为CLK 脉冲宽度,典型值为10µs;T3为CLK 脉冲时间间隔,典型值为 10µs。
图
7 ZLG7289串行接口时序图
- 6 -
嵌入式 课程设计报告
3.详细设计与实现
3.1、界面说明
我们在PC机上是通过超级终端与实验板进行通信后,在实验板的键盘上敲击,将会出现下图的界面 如下图:
图8 实验效果图
- 7 -
嵌入式 课程设计报告
3.2、程序流程
图9 程序流程图
3.3、关键代码
#include \"def.h\" #include \"option.h\" #include \"2410addr.h\" #include \"2410lib.h\" #include \"2410slib.h\" #include \"2410keypad.h\"
void __irq KeyPad_Int(void); //also Eint1 int int KeyPadInit(void);
/**************************************************************** * OURS2410EDU KEYPAD configuration * * KEYPAD CHIP UR5HCSPI * * GPB6=/CS, GPG7 =SPIMISO0, GPE12=SPIMOSI0, GPE13=SPICLK0 * * GPB6 =/CS, GPG5 =SPIMISO1, GPG6 =SPIMOSI1, GPG7 =SPICLK1 * * GPB0 =DIO DIRECTION 0:MOSI→DIO 1: DIO→MISO * ****************************************************************/ #define ONEBIT 0x1
#define KEYPADCSDIS (rGPBDAT |=(ONEBIT << 6))
- 8 -
嵌入式 课程设计报告
#define KEYPADCSEN (rGPBDAT &=~(ONEBIT << 6)) #define KEYPADDIRMO (rGPBDAT &=~(ONEBIT << 0)) #define KEYPADDIRMI (rGPBDAT |=(ONEBIT << 0)) void Delay30us(void) {
unsigned int i;
for (i=0;i<0x4ff;i++); }
void Delay60us(void) {
unsigned int i;
for (i=0;i<0x9ff;i++); }
int putcToKBCTL(U8 c) {
U32 i;
// UINT rxbuf[10]; // UINT x;
KEYPADCSEN; KEYPADDIRMO; Delay60us();
while((rSPSTA1 & ONEBIT)==0);
rSPTDAT1 = c;
while((rSPSTA1 & ONEBIT)==0);
KEYPADCSDIS;
i = rSPRDAT1;
return(i); }
U8 readKBValue(void) {
unsigned char i;
KEYPADCSEN; KEYPADDIRMO; Delay60us();
// wait while busy // write left justified data // wait while busy - 9 -
嵌入式 课程设计报告
while((rSPSTA1 & ONEBIT)==0); // wait while busy
rSPTDAT1 = 0x15; // write read key value command
while((rSPSTA1 & ONEBIT)==0); // wait while busy
Delay30us();//delay 30us
KEYPADDIRMI;
rSPTDAT1 = 0xff; // write read key value command
while((rSPSTA1 & ONEBIT)==0); // wait while busy
i = rSPRDAT1;
KEYPADCSDIS; KEYPADDIRMO;
return(i); }
int KeyPadInit() {
int t;
char dummy = (char)0xff;
// Setup IO port for SPI interface & Keyboard // Setup EINT1 (KBDINT) rGPFCON &= ~(0x3 << 2); // Clear GPF1 rGPFCON |= (0x2 << 2); // Set GPF1 to EINT1 for Keyboard interrupt rEXTINT0 &= ~(0x7 << 4); // Clear EINT1
rEXTINT0 |= (0x2 << 4); // fallig edge triggered for EINT1 // setup SPI interface
// GPG5 : SPIMISO (KBDSPIMISO) // GPG6 : SPIMOSI (KBDSPIMOSI) // GPG7 : SPICLK (KBDSPICLK)
rGPGCON &= ~((0x3 << 10) | (0x3 << 12) | (0x3 << 14)); // Clear GPG5,6,7 rGPGCON |= ((0x3 << 10) | (0x3 << 12) | (0x3 << 14)); // setup _SS signal(nSS_KBD)
rGPBCON &= ~(0x3 << 12); // Clear GPB6
rGPBCON |= (ONEBIT << 12); // Set Port GPB6 to output for nSS signal
KEYPADCSDIS; // Set /SS high // setup Dir signal (KEYBOARD) CPU->7289
rGPBCON &= ~(0x3 << 0); // Clear GPB0
- 10 -
嵌入式 课程设计报告
rGPBCON |= (ONEBIT << 0); // Set Port GPB0 to output for _PWR_OK signal // rGPDDAT &=~(ONEBIT << 0); // set _PWR_OK to 0 KEYPADDIRMO; // Setup SPI registers
// Interrupt mode, prescaler enable, master mode, active high clock, format B, normal mode
// rSPCON1 = (ONEBIT<<5)|(ONEBIT<<4)|(ONEBIT<<3)|(0x0<<2)|(ONEBIT<<1); // Poll mode, prescaler enable, master mode, active high clock, format A, normal mode rSPCON1 = (0<<5)|(ONEBIT<<4)|(ONEBIT<<3)|(0x0<<2)|(0<<1);
// Developer MUST change the value of prescaler properly whenever value of PCLK is changed.
rSPPRE1 = 255; // 99.121K = 203M/4/2/(255+1) PCLK=50.75Mhz FCLK=203Mhz SPICLK=99.121Khz putcToKBCTL(0xa4); //send init command Uart_Printf(\"Key Pad Init complete:\\n\");
rSRCPND = BIT_EINT1; //to clear the previous pending states rINTPND = BIT_EINT1; //Define the keypad int entry
pISR_EINT1 = (unsigned)KeyPad_Int; rINTMSK=~(BIT_EINT1); //enable Eint return(TRUE);}
void __irq KeyPad_Int(void) {
U8 ui8ScanCode;
ui8ScanCode=readKBValue();
Uart_Printf(\"中断产生 key %d pressed!\\n\ ClearPending(BIT_EINT1); }
- 11 -
嵌入式 课程设计报告
4.测试分析
4.1.测试方法
直接在实验板的键盘上敲击。
4.2 测试用例
输入:1,2,3,4,5,6,7,8,9
4.3 测试结果
如下图:
图10 实验效果图
- 12 -
嵌入式 课程设计报告
5.小结
为期数周的课程设计将要结束了。在这两周的学习中,我学到了很多,也找到了自己身上的不足。感受良多,获益匪浅。
这数周中,我们小组分工合作、齐心协力,一起完成了课程设计前的准备工作(阅读课程设计相关文档)、小组讨论分工、完成系统开发的各个文档、课程设计总结报告,个人小结的任务。在课程设计的第一天我们便对这次任务进行了规划和分工。在以后的几天中,我们组的成员一起努力,查阅资料、小组讨论、对资料进行分析,并在这段时间里完成了按键驱动程序的设计,并最后撰写课程设计报告及个人总结。
在课程设计的过程中,我们经历了感动,经历了一起奋斗的酸甜苦辣。也一起分享了成功的喜悦。这次的课程设计对我们每个人来说都是一个挑战。课程设计中文档的撰写我从来就没有担心过,就是按键驱动程序设计我真的很担心,平时对这方面的知识接触的就不是很深,而且对于软件我就更抓狂了。这时候小组的力量就体现出来了,各司其职,各尽其能。发挥了集体的效用。
其实这次的课程设计我的的感受不仅仅是知识的获得,更是人格的磨练和团队的合作。 课程设计这样集体的任务光靠团队里的一个人或几个人是不可能完成好的,合作的原则就是要利益均沾,责任公担。如果让任务交给一个人,那样既增加了他的压力,也增大了完成任务的风险,降低了工作的效率。所以在集体工作中,团结是必备因素,要团结就是要让我们在合作的过程中会征求同学的意见,会主动认错,找出共同点;会接受帮助,信守诺言,尊重别人,保持自己的特色。
课程设计结束了,但我们一起奋斗的精神和这份宝贵的经历将会成为人生道路上一道亮丽的风景线。
参考文献
[1]ARM嵌入式系统原理与开发 【M】 人民邮电出版社 王诚,梅霆主编 [2]嵌入式基础实验教程
- 13 -
因篇幅问题不能全部显示,请点此查看更多更全内容