《嵌入式技术及应用实训报告-基于开发板的完整人机接口设计(15页).docx》由会员分享,可在线阅读,更多相关《嵌入式技术及应用实训报告-基于开发板的完整人机接口设计(15页).docx(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、-嵌入式技术及应用实训报告-基于开发板的完整人机接口设计-第 15 页嵌入式技术及应用实训报告项 目 名 称: 完整人机接口系统设计(44键盘+4位数码LED)专 业: 计算机应用技术 班 级: 计应1xx/1xx 校内指导老师:学 号: 姓 名: 地 点: 崇实楼B区411 时 间: 201x.7.6201x.7.115成绩评定二一五年七月xx日附件3-1:绵阳职业技术学院实验实训(设计)进度检查及成绩评定表日期内容执行情况指导教师签名LPC2132开发板流水灯设计完整人机接口系统设计(44键盘+4位数码LED)温度控制(基于LPC2132+18B20温度检测及控制)基于ARM9的S3C24
2、10嵌入式实验平台的搭建Linux的基本命令使用嵌入式平台的C程序设计学生姓名专业班级学号成绩汇总评分项目评分比例()分数总分指导教师评分40评阅教师评分30答辩小组评分30指导教师过程评语评分签字: 年 月 日评阅教师报告评语评分签字: 年 月 日答辩小组答辩评语评分签字: 年 月 日附件3-2:项目二:完整人机接口系统设计(44键盘+4位数码LED)一、 项目描述键盘子系统(4x4矩阵键盘)和显示子系统(多位LED数码管动态显示),硬件电路参考开发板电路。系统循环检测键盘动作,当某个键被按下,将该键对应的键值输出到最右边的led显示器上,原来显示的数据整体左移一位。二、 硬件组成1. 四位
3、共阳极数码管组成动态LED输出接口电路模块从图可知:LPC2132的P123:16控制数码管的字形段码(A、B、C、D、E、F、G、DP),且各位数码管笔画的同名端并联使用,段码的输出对各位数码管来说都是相同的;各位数码管的共阳极由LPC2132的P021:18位控制Q4Q1来实现4位数码管的位输出控制。因此,同一时刻如果各位数码管的位选都处于选通状态的话,4位数码管将显示相同的字符。如要各位数码管能够显示与本位相应的字符,就必须采用扫描显示方式。即在某一时刻,只让某一位(数码管)的位选处于导通状态,而其他各位的位选线处于关闭状态。同时,段线上输出相应要显示字符的字形码。这样同一时刻,只有选通
4、的哪一位显示出字符,而其他位则是熄灭的,如此循环下去,就可使各位数码管显示出将要显示的字符。 动态显示的特点: 用一个并行接口把所有数码管的笔画段同名端连在一起,而每一个数码管的公共端COM各自独立的受一条I/O线控制。但究竟哪个数码管亮则取决于COM端,COM端与单片机的I/O口相连,由单片机输出位码到LED位码端,以控制何时点亮哪一位数码管。 动态扫描用分时轮流控制各数码管的COM端,使个数码管轮流点亮。在此过程中,每位数码管的点亮时间极为短暂。由于人的视觉暂留现象及发光二极管的余辉,给人的印象就是一组稳定的显示数据 动态显示的特点: 优点:当显示位数较多时,采用动态显示方式比较节省I/O
5、口,硬件电路也较静态显示简单。 缺点:其稳定度不如静态显示方式。而且数据位数较多时,CPU要轮流扫描,占用CPU比较多的时间。2. 4x4键盘电路模块矩阵键盘又称行列式键盘,它是用4条I/O口线作为行线,4条I/O口线作为列线组成的键盘。行线和列线的每个交叉点上设置一个按键。这样的键盘中的按键个数是44,这种行列式键盘结构能够有效的提高单片机系统中I/O口的利用率。三、 软件系统任务概要(方案1)1. 定义显示缓冲区、段码表和位码表。其中常量表格ledsegcode数组保存对应的09十个数字所对应的显示段码。常量表格kscancode数组保存4条行线输出所对应的键盘扫描码。定义键盘代码数组ke
6、ytal44,保存16个键对应的键码。2. 定义延时函数delay()函数、显示函数Display()、按键检测函数Getkey()。3. 定义变量。4. 主程序流程。 系统初始化(GPIO功能、方向设置IOxDIR及各变量初始换)。 根据计数变量j的值,决定是否调用getkey()函数获取键值。 若有键输入,则置于显示缓冲区最低位(缓冲区数组整体左移一位),否则do nothing。 调用display()函数,动态显示缓冲区数据,持续250us 转,循环。四、 关键函数设计1. 显示子程序设计void display(void) uint32 i; ledptr=0; while(ledp
7、trsizeof(disbuff) IO1SET|=(0xff16); /p1.16p1.23 初始值为1IO1CLR|=(segcodedisbuffledptr16); IO0SET|=(0x0f18); /p0.18p0.21 位码输出1,三极管均截止IO0CLR|=(bitcodeledptr18); ledptr+;i=2500; while(i-);2. 44键盘子程序设计uint8 GetKey(void) uint8 row,col; for (col=0;col4;col+) IO0CLR=(0x0f12); IO0SET=(KSCANCODEcol12); if (IO0P
8、IN & nokeypress)!=nokeypress) display();display(); /用显示子程序代替延时子程序,避免LED显示出现闪烁 if (IO0PIN & nokeypress)!=nokeypress) if (IO0PIN & firstline_pressed)=firstline_pressed) row=0; else if (IO0PIN & secondline_pressed)=secondline_pressed) row=1; else if (IO0PIN & thirdline_pressed)=thirdline_pressed) row=2
9、; else row=3; while(IO0PIN & nokeypress)!=nokeypress) display(); keyval=keytabrowcol; return keyval; return 0xff;五、 系统的核心问题本系统程序设计要处理好一对矛盾:(1) 动态显示对刷新显示周期的要求。动态显示要求扫描周期要短(至少20ms内要显示一次)。(2) 键盘扫描周期的要求。键盘扫描周期不能太短,因为键盘的抖动消除要求键盘的扫描周期至少间隔几十ms。因此若扫描键盘和刷新显示两者的周期一致,则会带来问题:要么显示会出现闪烁(显示刷新的周期太长);要么键盘扫描出现错误(键盘扫描
10、周期太短,导致本是按下一次键,却得到两次按下相同的键)。(3) 我们的解决方案是:扫描键盘和刷新显示的周期设定为不同的时间。即:在几次显示刷新之后再扫描一次键盘。换言之,使得键盘的扫描周期是显示刷新周期的若干倍。在程序中使用了计数器变量j,每次while循环必刷新显示,则对变量j进行计数操作,而当变量j为某个数值时才执行键盘扫描任务。六、 程序清单:#include LPC21xx.htypedef unsigned int uint32;typedef unsigned char uint8;#define nokeypress (0x0f8)#define firstline_presse
11、d (0x0e8)#define secondline_pressed (0x0d8)#define thirdline_pressed (0x0b0; dly-)for (i=0; i5000; i+);void display(void) uint32 i; ledptr=0; while(ledptrsizeof(disbuff) IO1SET|=(0xff16); /p1.16p1.23 初始值为1 IO1CLR|=(segcodedisbuffledptr16); IO0SET|=(0x0f18); /p0.18p0.21 位码输出1,三极管均截止IO0CLR|=(bitcodele
12、dptr18);ledptr+;i=2500; while(i-);void init_Key4x4(void) /PINSEL031:16=0x0000, p0.8p0.15 工作于GPIO方式 PINSEL0&=(0xffff16); IO0DIR=IO0DIR&(0xff8)|(0x0f12); /p0.8p0.11 输入 p0.12p0.15输出uint8 GetKey(void) uint8 row,col; for (col=0;col4;col+) IO0CLR=(0x0f12); IO0SET=(KSCANCODEcol12); if (IO0PIN & nokeypress)
13、!=nokeypress) display();display(); if (IO0PIN & nokeypress)!=nokeypress) if (IO0PIN & firstline_pressed)=firstline_pressed) row=0; else if (IO0PIN & secondline_pressed)=secondline_pressed) row=1; else if (IO0PIN & thirdline_pressed)=thirdline_pressed) row=2; else row=3; while(IO0PIN & nokeypress)!=n
14、okeypress) display(); keyval=keytabrowcol; return keyval; return 0xff;void init_disp(void) /PINSEL23=0, p1.16p1.23 工作于GPIO方式 PINSEL2&=(13);/IO1DIR23:16=11111111,p1.16p1.23 方向为输出,接数码管笔画段 A,B,C,D,E,F,G,DP IO1DIR|=(0xff16); IO1SET|=(0xff16); /p1.16p1.23 初始值为1PINSEL1&=(0xff4); /PINSEL111:4=0000 0000,p0.
15、18p0.21 工作于GPIO方式IO0DIR|=(0x0f18); /p0.18p0.21 方向为输出 初始值为1 (三极管截止模式)IO0SET|=(0x0f18); /p0.18p0.21 初始值为1 (三极管截止模式) int main(void) uint8 i,m,j=250; init_disp(); init_Key4x4();while(1) if(j=0)m=GetKey();if (m!=0xff) for (i=0;isizeof(disbuff)-1;i+) disbuffi=disbuffi+1;disbuff3=m;j=250; display(); if(j!=
16、0) j-;七、 编译整个程序八、 下载程序九、 运行效果另一种设计方案(方案2)方案一中要解决动态显示程序的刷新频率和键盘扫描频率二者匹配问题而引入计数器,从而兼顾了LED动态显示对刷新频率的要求,及键盘扫描周期不能太短(按键抖动时间就有几十ms)。本方案采用定时器实现每2ms定时中断一次,在定时器中断服务程序中将显示缓冲器的内容查表送端口,动态点亮一位数码管。这样4位数码管轮流点亮一次共需8ms,可计算出LED数码显示器的刷新频率为1S/8ms=125Hz,远大于23Hz。这样数码显示亮度就更均匀。按键盘时,数码显示不再黑屏。在主程序中扫描键盘,将有效键值送数码显示缓冲区。一、 程序基本架
17、构1. 设计思路(1) 用定时器获得2ms定时。(2) 在定时器中断服务函数中,将显示缓冲区的内容查表送端口,使能对应LED的位选信号,动态点亮一位数码管。同时为点亮下一位数码管做好准备。(3) 主程序中,首先初始化相关端口(LED数码管相关端口)、系统初始化、定时器初始化、中断服务函数初始化。在主循环中,调用扫描函数,判断有无键按下,若有键按下,将键值送显示缓冲区;同时等待定时器中断发生。2. 主程序流程(待完善)3. 2ms定时器中断服务子程序的流程。(待完善)二、 程序清单#include LPC21xx.htypedef unsigned int uint32;typedef unsi
18、gned char uint8;#define nokeypress (0x0f8)#define firstline_pressed (0x0e8)#define secondline_pressed (0x0d8)#define thirdline_pressed (0x0b0; dly-)for (i=0; i5000; i+);void init_Key4x4(void)PINSEL0&=(0xffff16); /PINSEL031:16=0x0000, p0.8p0.15 工作于GPIO方式IO0DIR=IO0DIR&(0xff8)|(0x0f12); /p0.8p0.11 输入 p
19、0.12p0.15输出uint8 GetKey(void) uint8 row,col; for (col=0;col4;col+) IO0CLR=(0x0f12); IO0SET=(KSCANCODEcol12); if (IO0PIN & nokeypress)!=nokeypress)DelayNS(2); if (IO0PIN & nokeypress)!=nokeypress) if (IO0PIN & firstline_pressed)=firstline_pressed) row=0; else if (IO0PIN & secondline_pressed)=secondli
20、ne_pressed) row=1; else if (IO0PIN & thirdline_pressed)=thirdline_pressed) row=2; else row=3; while(IO0PIN & nokeypress)!=nokeypress); keyval=keytabrowcol; return keyval; return 0xff; /无键按下,返回值为0xffvoid init_disp(void) PINSEL2&=(13); /PINSEL23=0, p1.16p1.23 工作于GPIO方式 IO1DIR|=(0xff16); /IO1DIR23:16=1
21、1111111,p1.16p1.23 方向为输出,/接数码管笔画段 A,B,C,D,E,F,G,DPIO1SET|=(0xff16); /p1.16p1.23 初始值为1PINSEL1&=(0xff4); /PINSEL111:4=0000 0000,p0.18p0.21 工作于/ GPIO方式 IO0DIR|=(0x0f18); /p0.18p0.21 方向为输出 初始值为1 (三极管截止模式)IO0SET|=(0x0f18); /p0.18p0.21 初始值为1 (三极管截止模式) void TIMER1_VECT(void) _irq T1IR = 1;/定时器T1通道0中断,该位置1,
22、向该位写1,会复位中断。 IO1SET|=(0xff16); /p1.16p1.23 初始值为1 IO1CLR|=(segcodedisbuffledptr16); IO0SET|=(0x0f18); /p0.18p0.21 位码输出1,三极管均截止 IO0CLR|=(bitcodeledptr18); ledptr+; if (ledptr=sizeof(disbuff) ledptr=0; VICVectAddr = 0; /通知VIC,中断处理结束void Timer1_Init(void) T1PR=99; /fpclk=11.0592Mhz,100分频后为110592hz T1MR0
23、=110592*0.002; /实现2ms定时T1MCR=3; /MR0与TC值匹配时将产生中断;并是TC复位T1TCR=1; /定时器和预分频计数器使能计数VICVectAddr0=(unsigned long)TIMER1_VECT; /中断服务函数入口地址VICVectCntl0=0x20|5; /分配定时器1到通道0VICIntEnable|=(15); /使能定时器1中断void System_Init()#define PLL_VPBDIV 0x00 /fVPB=1/4 fCCLK#define PLL_CFG 0x23 /fcclk=4fosc=4*11.0592Mhz /CCL
24、K=44.2368Mz,PCLK=CCLK/4=11.0592MZ#define MAM_TIM 0x03 /read code 3 colck /PLL(锁相环)允许PLLCON=1; /PLL使能VPBDIV=PLL_VPBDIV; /总线时钟使能(VPB=1/4 CCLK)PLLCFG=PLL_CFG; /(4)倍频PLLFEED=0xaa; /发送PLL馈送序列PLLFEED=0x55;while(PLLSTAT&(110)=0); /等待PLL锁定到指定频率PLLCON=3; /PLL使能连接PLLFEED=0xaa; /发送PLL馈送序列PLLFEED=0x55; /存储加速设备M
25、AMCR=0; /存储器加速器禁止MAMTIM=MAM_TIM; /存储器访问定时控制(3cclk)MAMCR=2; /存储器加速器使能VICIntEnClr=0xffffffff; /中断使能清零VICVectAddr=0; /中断向量地址VICIntSelect=0; /中断类型选择int main(void) uint8 i,m; System_Init(); /系统初始化 Timer1_Init(); /定时器初始化 init_disp(); /显示函数初始化 init_Key4x4(); /键盘初始化while(1) m=GetKey();if (m!=0xff) for (i=0;
26、isizeof(disbuff)-1;i+) disbuffi=disbuffi+1;disbuff3=m;三、 仿真调试四、 效果展示五、 项目拓展:键盘子系统(4x4矩阵键盘)和LCD液晶显示系统(LCD1602),硬件电路参考开发板电路。系统循环检测键盘动作,当某个键被按下,将该键对应的字符依次输出到LCD显示器上。main.c参考程序代码:#include LPC21xx.h#include 1602.c #define nokeypress (0x0f8)#define firstline_pressed (0x0e8)#define secondline_pressed (0x0d
27、8)#define thirdline_pressed (0x0b1)for(n=6553;n1;n-);i-;uint8 GetKey(void) uint8 row,col,keyval; for (col=0;col4;col+) IO0CLR=(0x0f12); IO0SET=(KSCANCODEcol0.19 RW-0.6 EN-0.4 /DATA P1.1623,PINSEL0&=(0x38) ;/P0.4 is GPIO PINSEL09:8=00PINSEL0&=(0x312) ;/P0.6 is GPIO PINSEL013:12=00PINSEL1&=(0x36) ;/P0
28、.19 is GPIO PINSEL07:6=00IO0DIR|=(14)|(16)|(119) ;/P0.4,0.6,0.19 方向输出PINSEL2&=(0x13) ;/P1.161.23 is GPIO mode PINSEL23=0IO1DIR|=(0xff16) ;/P1.161.23 director is outputint main(void)uint8 ch,i;uint8 line116=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;uint8 line216=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;init_Key4x4();in
29、it_lcd_port();init_lcd();lcd_clr();i=0; while(1) ch=GetKey(); if (ch!=0xff) if (i16) line1i+=ch; else if(i0.19 RW-0.6 EN-0.4/DATA 1.1623,/#define lcd_rs_1() lcd_rs_set = 1#define lcd_rs_1() IO0SET|=(119)#define lcd_rs_0() IO0CLR|=(119)#define lcd_rw_1() IO0SET|=(16)#define lcd_rw_0() IO0CLR|=(16)#define lcd_en_1() IO0SET|=(14) #define lcd_en_0() IO0CLR|=(14)/#define set_port_dat(dat) IO1CLR|=(0xff16),IO1SET|=(dat16)/ #define set_port_dat(dat) IOPIN1 = dat0;i-);void set_port_dat(uint8 dat)IO1CLR|=(0xff16);IO1SET|=(dat16); delay1(30);uint8 lcd_busy(void)uint8 i;set_port_dat(0xff);lcd_rs