1、通信工程专业课程设计南理工442020年4月19日文档仅供参考,不当之处,请联系改正。通信工程专业课程设计实验报告带有LED指示的图片播放器 指导教师:程风雷 完成日期: .9.20目录一、 实验目的.3二、 实验原理.3三、 实验设备.3四、 设计思想与功能简介.3五、 总体设计方案.4六、 主要模块实现方案.41.矩阵键盘模块.42.LCD显示模块.113.LED显示模块.16七、 整体效果图.20八、 实验结论.23九、 实验总结.23十、 参考文献.24一、 实验目的 随着信息化技术的发展,嵌入式系统已经成为当前IT产业界一个非常热门的话题。嵌入式系统主要由嵌入式处理器、相关支撑硬件和
2、嵌入式软件系统组成,它是集软硬件于一体的可独立工作的“器件”。总体看来,嵌入式系统具有便利灵活、性能价格比高、嵌入性强等特点,能够嵌入到现有任何信息家电和工业控制系统中。从软件角度来看,嵌入式系统具有不可修改性、系统所需配置要求较低、系统专业性和实时性较强等特点。为此我们开展基于SEP3203的通信工程专业课程设计以实现以下目的: 1、经过实验,接触目标开发板、集成开发环境的构建方式和作业方式; 2、经过实验,了解嵌入式系统的硬件和软件、JTAG调试方法,学会如何从头开始着手开发一个嵌入式系统;3、增加交叉编译、目标板程序调试和加载的真知;积累嵌入式系统开发流程、开发方法和开发技巧的经验。经过
3、整个实验流程最终增强实践能力,达到对所学知识的巩固,在实践中加深对嵌入式软件开发的体会。二、 实验原理1. 经过键盘按键判断的工作原理和方法,利用UCB1400的控制方法,实现按键控制切换;2. 基于LCD的物理特性和工作原理及ARM7TDMI内核LCD控制器的工作原理,设计液晶显示文本及图形的方法与程序;3.基于LED的工作原理和控制方法及74HC595移位寄存器的使用,实现键控与LED指示的结合;4.掌握SEP3203 GPIO口的配置和读写方法。三、实验设备1.硬件:HOST机一台、调试器一台、ARM实验平台一套。2.软件:WIN98或 操作系统、ADS或SDT开发环境、调试器驱动程序I
4、CE、键控LCD与LED范例源程序。四、设计思想与功能简介设计思想的最初来源是对于图片和幻灯片的播放,而且利用LED动态的显示与图片匹配的日期或编号或其它信息。经过对实验功能的整合,现取以下两个功能实例展示程序的功能:1、 经过键盘按键控制LCD液晶显示屏切换图片,实现播放。2、 达到播放同时在LED数码管上实时显示图片编号。3、 文字提示信息:当播放成功时会同时显示LCD、LED功能实现成功,在信息提示框中同时显示按键号码、图片号码, 当所按按键无图片时会提示“无图片”信息。4、 程序采用模块并列模式,易于扩展图片数量与LED指示,便于动态添加,这正是播放设备的基本需要。五、 总体设计方案本
5、系统基于SEP3203微处理器,ARM7TDMI内核,主要由矩阵键盘模块、LCD模块、LED模块等部分组成。系统的总体框图如下:矩阵键盘模块LED指示模块LCD播放模块 六、 主要模块实现方案1.矩阵键盘模块1.1 按键位置的确定本系统采用矩阵键盘,矩阵键盘有两种驱动方式,一种是行扫描法,另一种是高低电平翻转法。本系统采用了行扫描法。包括两个步骤:判断键盘中是否有键按下:将全部行线置为低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。 判断闭合键所在的位置:在确认有键按下后,即
6、可进入确定具体闭合键的过程。方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。1.2 键盘中断键盘实验的主函数流程如下图所示: 上述的循环等待过程可由按键中断打断,执行相应的键盘中断函数。键盘中断服务流程能够由下图表示:1.3 实验代码实验代码主要由三个部分的函数组成:顶层实现函数,硬件设置函数,中断服务函数。1.3.1 顶层实现函数void KeyBoardModule(void);键盘实验的顶层函数,实现系统初始化及键盘初始化。1.3.2 硬件设
7、置函数void keyboardinit(void);该函数实现了键盘的初始化。主要调用InitAC97()和int15init(),完成UCB1400初始化及GPIO 口的配置。void int15init(void);GPIO 口的配置函数。void InitAC97(void);UCB1400 的初始化配置函数。void wucb(U32 addr,U32 val);经过向AC97 CRC 寄存器中写入,配置UCB1400 的各寄存器值,该函数用来被查找按键函数调用。U32 rucb(U32 addr);经过读出AC97 CRC 寄存器值,获得UCB1400 的各寄存器值,该函数用来被查
8、找按键函数调用。1.3.3 中断服务函数void keyhandler(void);键盘中断处理函数,调用findkey()函数来查找并显示键号。中断处理函数的流程如下图所示。void findkey(void);查找按键的函数,用于求出被按下按键的键号并打印出来,该函数被键盘处理中断调用。1.4 键盘中断相关代码如下:void key_handler(void)U32 tmp_int_status;U32 i;U8key; char *s;*(RP)INTC_IMSK = 0xffffffff;tmp_int_status = *(RP)INTC_ISTAT;for(i=0;i10000;i
9、+);if(tmp_int_status = 0x20)/int4/*set Y3,Y2,Y1 = 1,1,0,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xffc3;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x20)key = 1;*(RP)PORTE_DATA &= 0xff1f;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x10;*(RP)INTC_IMSK = 0;/*set Y3,Y
10、2,Y1 = 1,0,1,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xffa3;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x20)key = 4;*(RP)PORTE_DATA = 0x0;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x8;*(RP)INTC_IMSK = 0;/*set Y3,Y2,Y1 = 0,1,1,config GPIO*/*(RP)PORTE_DATA |= 0x0
11、0e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xff63;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x20)key = 7;*(RP)PORTE_DATA = 0x0;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x4;*(RP)INTC_IMSK = 0;else if(tmp_int_status = 0x10)/*set Y3,Y2,Y1 = 1,1,0,config GPIO*/*(RP)PORTE_DATA |= 0xe0;*(RP)PORTE_INTRC
12、LR = 0xffff;*(RP)PORTE_DATA &= 0xffc3;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x10)key = 2;*(RP)PORTE_DATA = 0x0;for(i=0;i10000;i+);*(RP)PORTE_INTRCLR |= 0x10;*(RP)INTC_IMSK = 0;/*set Y3,Y2,Y1 = 1,0,1,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xffa3;for(i=0
13、;i5000;i+);if(*(RP)INTC_ISTAT = 0x10)key = 5;*(RP)PORTE_DATA = 0x0;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x8;*(RP)INTC_IMSK = 0;/*set Y3,Y2,Y1 = 0,1,1,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xff63;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x10)key = 8;*(R
14、P)PORTE_DATA = 0x0;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x4;*(RP)INTC_IMSK = 0;else if(tmp_int_status = 0x8)/*set Y3,Y2,Y1 = 1,1,0,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xffc3;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x8)key = 3;*(RP)PORTE_DATA = 0x0;f
15、or(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x10;*(RP)INTC_IMSK = 0;/*set Y3,Y2,Y1 = 1,0,1,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xffa3;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x8)key = 6;*(RP)PORTE_DATA = 0x0;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x8;*(RP)I
16、NTC_IMSK = 0;/*set Y3,Y2,Y1 = 0,1,1,config GPIO*/*(RP)PORTE_DATA |= 0x00e0;*(RP)PORTE_INTRCLR = 0xffff;*(RP)PORTE_DATA &= 0xff63;for(i=0;i5000;i+);if(*(RP)INTC_ISTAT = 0x8)key = 9;*(RP)PORTE_DATA = 0x0;for(i=0;i100;i+);*(RP)PORTE_INTRCLR |= 0x4;*(RP)INTC_IMSK = 0;*(RP)INTC_IMSK = 0x0;*(RP)PORTE_DATA
17、 &= 0xff1f;for(i=0;i100;i+);*(RP)PORTE_INTRCLR = 0xffff; DBG_Printf(key=%xn , key);void findkey(void) U32 intstatus = 0; U32 i = 0; U16 j = 0; U16 k = 0; U16 l = 0; U16 m = 0; U16 n = 0;U32 datareg = 0;U16key = 0; char *s; datareg = rucb(0x5a); / 记录下数据寄存器原始值,用于判断列地址 intstatus = rucb(0x62);/ 记录下中断状态值
18、,用于判断行地址 if(intstatus != 0) for(j=0; jj) | datareg;/ 依次写入 1000 0100 0010 0001 wucb(0x5a,k); / 进行列扫描动作for(n=1000;n1;n-); l = rucb(0x5a); if( (l & 0x1e0) = 0x1e0) / 如果数据寄存器值变化,则输入为1的那列号就为按键所在列 break;/ 此时,j代表的循环数即为列号 n = intstatus 4; / 确定行位置。 for(m=0; m 1; if( (n & 0x1) = 0x1 ) break; / 下面判断按键是否抬起n = 0
19、;wucb(0x5a, 0x1e0);/ 向I/O 0-3写入全0l = rucb(0x5a);while( (l & 0x1e0) != 0x1e0)/ 按键如果已经抬起了key = (U16)(m*4 + j)%16);/ 计算得到的键值if ( key = 10000 )/ 如果在较长时间后,按键依然没有抬起,则快速打印键值 DBG_Printf(keey=%xn , key);wucb(0x5a,0x1e0); / 下一次的判断周期l = rucb(0x5a);*(RP)PORTH_INTRCLR = 0x8; / 清除garfield中断源 wucb(0x62,0x1e0);/ uc
20、b I/O 5-8 清除中断状态 wucb(0x5c, 0x1f); / 配置UCB的I/O口功能,03为数据输出,58为中断输入wucb(0x5a, 0x1e0); / 配置UCB的I/O口初始数据值wucb(0x60, 0x1e0); 2. LCD显示模块2.1 LCDC控制器的可编程控制寄存器本系统中,LCD屏幕用于显示切换图片。该模块需要完成的主要工作是LCD的驱动,在LCD的基本驱动中,需要配置以下寄存器:寄存器地址复位值SSA0x1100 (BASE_LCDC)0x31f00000SIZEBASE_LCDC+0x040x014000F0PCRBASE_LCDC+0x080x2208
21、0009HCRBASE_LCDC+0x0c0x 4040VCRBASE_LCDC+0x100x14008586PWMRBASE_LCDC+0x140x00000114DMACRBASE_LCDC+0x1c0x80070003LCDICRBASE_LCDC+0x200x00000000SEP3203中具有内置的LCD控制器,支持灰度LCD和彩色LCD。控制器负责将显存(在系统存储器中)中的数据送到LCD驱动电路。在灰度LCD上,使用基于时间的抖动算法(time-based dithering algorithm)和FRC (Frame RateControl) 方法,能够支持单色、4级灰度和16
22、级灰度模式的灰度LCD;在彩色LCD上,最多可支持65535(16 位)级彩色。能够经过编程修改相应的LCD控制器寄存器的值,适配不同大小、象素的LCD。2.2 LCD的总体流程图2.3 实验代码实验代码主要由三部分组成:顶层实现函数,硬件设置函数,及两个画图函数。2.3.1 顶层实现函数STATUS ModuleLcdc(void)该函数是Lcdc的顶层函数。它实现了系统供电的初始化及Lcdc模块的初始化,而且根据Lcdc.h中的宏定义决定是否清屏,最后调用画图函数,画出一个矩形并显示出来。2.3.2 硬件设置函数ER lcdc_init(void)该函数实现的是对Lcdc的初始化。其主要功
23、能包括:设置LCD数据帧的起始地址、屏幕尺寸、控制方式选择、灰度级别等。(LCDC初始化的流程见下图)。ER lcdc_clear(void)该函数用于清除屏幕上所显示的内容。2.3.3 画图函数ER lcd_draw2bpp(U8 x1, U8 y1, U8 x2, U8 y2, U8 color)该函数用来在屏幕上画一个由坐标(x1,y1)和(x2,y2)所确定的矩形,参数U8 color表示所画图形的灰度级别。void pic_display(void)该函数经过写屏幕起始地址寄存器,来显示一幅指定的图画。2.4 相关代码如下:STATUS ModuleLcdc(void) U32 i;
24、 init_lcdc(); #ifndef LCD_640_480_Color #ifdefLCDC_CLEAR if(E_OK != lcdc_clear() return E_CTX; #endif pic_display(); #else ShowPics(); #endifER init_lcdc(void) U32 i = 4;U32 k = 0;volatile char tempDot; *(RP)LECR = 0x00000000; /禁用LCDC/*(RP)PORTE_SEL = 0X111;/GPIO to select lcd_backlight/*(RP)PORTE_D
25、ATA =( 0X1 11); /* config the register of lcdc */ #ifdef LCD_V /竖屏时的初始化 *(RP)SSA = VS_BASE;/lcd数据帧的起始地址 *(RP)SIZE = 0x00F00140; /屏幕尺寸设定为240*320 *(RP)PCR = 0x22080009;/LCD被动模式,单色显示,4bit总线宽度,2bpp,象素极性高有效,/小印第安格式,最后刷新率配置必须写奇数这里是9,十分之一的/AMBA频率*(RP)HCR = 0xc80008b4;/;0xc80008ab;*(RP)VCR = 0x14000304;/0x1
26、4000304; /V_WAIT_1=4, V_WAIT_1=4*(RP)PWMR = 0x00000113;/0x00000114; /选取象素时钟,关对比度,最后7位设置输出脉冲数目*(RP)DMACR = 0x80070003;/0x80070003; /burst=1设置DMA高标志7和低标志3,对于固定长度的burst,每次请求/burst长度为高标志减一,这里是716。当buffer中的字数小于低标志/时触发DMA请求 #endif #ifdef LCD_H /横屏时的初始化 *(RP)SSA = VS_BASE;/lcd数据帧的起始地址 *(RP)SIZE = 0x014000F
27、0;/ 320*240 *(RP)PCR = 0x22080009; *(RP)HCR = 0x 4040; *(RP)VCR = 0x14008586; *(RP)PWMR = 0x00000114; *(RP)DMACR = 0x80070003; *(RP)LCDICR = 0x00000000; #endif #ifdef LCD_640_480_Color /彩屏时的初始化 *(RP)SSA = VS_BASE;/lcd数据帧的起始地址 *(RP)SIZE = YMAX | XMAX;*(RP)PCR = TFT|COLOR|PBSIZE|BPIX|PIXPOL|FLMPOL|LPP
28、OL|CLKPOL|OEPOL|END_SEL|ACD_SEL|ACD|PCD;*(RP)HCR = H_WIDTH|H_WAIT_1|H_WAIT_2;*(RP)VCR = V_WIDTH|PASS_FRAME_WAIT|V_WAIT_1|V_WAIT_2;*(RP)PWMR = SCR|CC_EN|PW;*(RP)DMACR = BL|HM|TM; #endif *(RP)LECR = 0x00000001; /使能LCDC *(RP)LCDICR = 0x00000000;/中断在加载帧的最后一个或第一个数据时设置,到LCD之间会有一个延时 #ifndef LCD_640_480_Col
29、or /黑白屏时的四级灰度显示 #ifdef grey4 *(RP)LGPMR = 0x00000000;/灰度寄存器组的使用应根据PCR中bpp的选定,这里PCR设定为2bpp,即四级灰度。*(RP)(LGPMR+1*i) = 0x00000008;*(RP)(LGPMR+2*i) = 0x0000000d;*(RP)(LGPMR+3*i) = 0x0000000f;/to config the grey,16 levels:#elsefor(i=0;i16;i+)*(RP)(LGPMR+4*i) = i;#endif*(RP)LECR = 0x0000001; /使能LCDCfor (k
30、= 0; k 4; k+ )tempDot = k;tempDot = 2;tempDot |= k;tempDot = 2;tempDot |= k;tempDot = 2;tempDot |= k;for (i = 0; i (320 * 60 / 4); i+)*(char*)(VS_BASE + (k * 60 * 320 / 4) + i) = tempDot;for (i = 0; i 1000000; i+); #endif3. LED显示模块本系统经过LED数码管实时显示图片编号,显示时,首先将要显示的数值经过查表的方式译码,再送至LED上显示。3.1 七段译码LED模块采用的
31、七段式的共阴极数码管,它有8个数据输入段,每一个对应于数码管上的一段或者小数点。也就是说,输入一个8位二进制数,就能够得到相应的LED显示的组合。下表是8位二进制数各位和七段码的对应关系。3.2 实验代码实验代码主要由两部分组成:顶层实现函数,硬件设置函数。3.2.1 顶层实现函数STATUS ModuleLed(void);功能描述:LED实验的顶层函数,依次调用其它函数实现实验内容。3.2.2 硬件设置函数void LedDisPlay(U8 data);功能描述:LED显示函数,将data数组里的内容显示在LED上。参数说明:名 称:data类 型:U8数组取值范围:0x00xF说 明:
32、需要显示在LED上的数据void GPIO_Init(void);功能描述:将GPIO PortD的PD0/1/2设置为通用输出口;void LedOut(U8 data, U32 times);功能描述:根据74HC595的工作时序,向PD0/1/2送显示过程的具体实现部分;参数说明:名 称:data类 型:U8数组取值范围:0x00xF说 明:需要显示在LED上的数据名 称:time类 型:U32取值范围:0x000000000xFFFFFFFF说 明:重复显示的次数void LedUpdate(void);功能描述:将74HC595的移位寄存器值锁存到输出引脚,驱动LED显示。3.3 该
33、部分的相关代码如下:U8 SEGMENT16 = (U8)(sect2 + sect3 + sect4 + sect5 + sect6 + sect7),/0(U8)(sect5 + sect6),/1(U8)(sect1 + sect3 + sect4 + sect6 + sect7),/2(U8)(sect1 + sect4 + sect5 + sect6 + sect7),/3(U8)(sect1 + sect2 + sect5 + sect6),/4(U8)(sect1 + sect2 + sect4 + sect5 + sect7),/5(U8)(sect1 + sect2 + se
34、ct3 + sect4 + sect5 + sect7), /6(U8)(sect5 + sect6 + sect7),/7(U8)(sect1 + sect2 + sect3 + sect4 + sect5 + sect6 + sect7),/8(U8)(sect2 + sect3 + sect4 + sect5 + sect6 + sect7),/9(U8)(sect1 + sect2 + sect3 + sect5 + sect6 + sect7),/a(U8)(sect1 + sect2 + sect3 + sect4 + sect5),/b(U8)(sect2 + sect3 + s
35、ect4 + sect7),/c(U8)(sect1 + sect3 + sect4 + sect5 + sect6),/d(U8)(sect1 + sect2 + sect3 + sect4 + sect7),/e(U8)(sect1 + sect2 + sect3 + sect7)/f;U8 prochip8 = 0xce, 0x60, 0x6e, 0x9c, 0xfc, 0xee, 0xce ; / prochip LOGOU8 display8 = 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00;U8 display18 = 0x02,0x00,0x00
36、,0x00,0x00,0x00,0x00,0x00;U8 display28 = 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00;U8 display38 = 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00;/ 实验中显示的数据(00xf)/U8 display8 = 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08;/ 实验中显示的数据(00xf)/#define ROLL;/ 是否以滚屏方式显示: no define: 不滚屏/ define: 滚屏方式STATUSModuleLed(void)/
37、* system initialized */system_init();/ 系统初始化/* GPIO initialized */GPIO_Init();/* led lab body */LedOut(prochip,5);/ 在LED上显示“PROCHIP的logoLedDisPlay(display);/ 显示用户设定的内容return E_OK;STATUSModuleLed1(void)/* system initialized */system_init();/ 系统初始化/* GPIO initialized */GPIO_Init();/* led lab body */Le
38、dOut(prochip,5);/ 在LED上显示“PROCHIP的logoLedDisPlay(display1);/ 显示用户设定的内容return E_OK;STATUSModuleLed2(void)/* system initialized */system_init();/ 系统初始化/* GPIO initialized */GPIO_Init();/* led lab body */LedOut(prochip,5);/ 在LED上显示“PROCHIP的logoLedDisPlay(display2);/ 显示用户设定的内容return E_OK;STATUSModuleLed3(void)