ARM9控制LED流水灯程序的设计说明
. .
华东交通大学理工学院
课程设计报告书
课程名称嵌入式系统原理及应用
题目ARM9 I/O口控制LED流水灯程序设计分院电信分院
专业班级通信工程2008-2
学号224
学生骆玉春
指导教师徐涢基
2012年12月30 日
华东交通大学理工学院
课程设计任务书
专业通信工程班级2008级2班骆玉春
一、课程设计题目ARM9 I/O口控制LED流水灯想设计
二、课程设计工作:自2011 年12 月28 日起至2012 年 1 月 2 日止。
三、课程设计的容要求:
1.了解ARM9的I/O口的工作原理;
2.基于arm920T的核,在开发板或者实验箱上,实现LED的流水控制;
3.了解I/O口怎么控制LED的输出;
4.掌握设置I/O口的状态需要设置的寄存器GPB CON、GPBDAT、GPBUP;
5.掌握在ADS环境下建立工程,用H-JTAG来调试程序,生成.HEX 文件;
6.总结本次课程设计的知识点。
学生签名:
201 年月日
课程设计评阅意见
评阅人职称
20 年月日
目录
课程设计任务书 (2)
第1章课程设计目的 (4)
第2章S3C2440的I/O口配置 (5)
第3章S3C2440的I/O口寄存器 (6)
第4章课程设计过程 (9)
4.1 设计步骤 (9)
4.2 部分原理图 (9)
4.3 源程序 (10)
4.4 编译调试结果 (17)
第8章课程设计心得 (19)
参考文献 (20)
第1章课程设计目的
这学期开了嵌入式这门课程,之前就了解到嵌入式系统是当前最热门最有发展前途的IT 应用领域之一。嵌入式系统用在一些特定专用设备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时响应要求很高等。特别是随着消费家电的智能化,嵌入式更显重要。像我们平常常见到的手机、可视、PDA、电子字典、VCD/DVD/MP3 Player、机顶盒(Set Top Box)、数字相机(DC)、数字摄像机(DV)、高清电视(HDTV)、游戏机、智能玩具、交换机、路由器、数控设备或仪表、汽车电子、家电控制系统、医疗仪器、航天航空设备等等都是典型的嵌入式系统。
随着社会的发展,嵌入式在未来的应用会越来越广泛。随着物联网的时代的到来,电器将会与互联网,移动成为一体,通过无线通信技术以及互联网技术将可以使人们在任何时候控制电器等的工作。
通过这次课程设计使我们了解基本的嵌入式编程方法以及培养我们对嵌入式编程的兴趣,与此同时,我们还能巩固一下C编程和汇编编程基础,为将来的嵌入式学习和工作做好充足的准备!
第2章S3C2440的I/O口配置在S3C2440 的CPU中有130多个多功能的输入输出引脚,分为8个端口,如下所示:
- Port A(GPA): 25-output port
- Port B(GPB): 11-input/out port
- Port C(GPC): 16-input/output port
- Port D(GPD): 16-input/output port
- Port E(GPE): 16-input/output port
- Port F(GPF): 8-input/output port
- Port G(GPG): 16-input/output port
- Port H(GPH): 9-input/output port
- Port J(GPJ): 13-input/output port
每个端口可以很容易地通过软件配置,以满足不同的系统配置和设计要求。如果引脚不用于复用功能,则引脚可配置为普通的I/O口。它们的寄存器是相似的:GPxCON用于选择引脚功能,GPxDAT用于都/写引脚数据,GPxUP用于确定是否使用部上拉电阻(x为A、B、..........、H、J,注意没有GPAUP)。
1.GPxCON中每两位控制一根引脚:
00表示输入、01表示输出、10表示特殊功能、11保持不用。其中GPBCON 中共有22位来管理GPB的功能设置,每两位来管理一个口的功能设置,两位共有四种状态,当GPB中的两位值为00时,配置为输入功能;配置为01时,是输出功能;10为复用功能;11为保留状态。
2.GPxDAT用于读/写引脚:
当引脚设为输入时,读此寄存器可知相应引脚的状态是高是低。
当引脚设为输出时,写此寄存器相应位可令此引脚输出低电平或高电平。
3. GpxUP
GPBUP宫11位,每一位代表一个管脚的上拉功能,某位为0时,相应引脚上拉功能被使能,为1时,相应引脚被禁止使用上拉功能。
第3章S3C2440的I/O口寄存器LED灯是接在某一个I/O上的,点亮或者熄灭LED灯其实就是对I/O寄存器的操作。ARM的I/O口寄存器主要包括端口配置寄存器GPXCON、端口数据寄存器GPXDAT、端口上拉电阻使能寄存器GPXUP、MISCELLANEOUS控制寄存器和外部中断寄存器五种(其中X为芯片的I/O口字母)。在这个课程设计我们只用前三个寄存器,下面就对着三个寄存器进行简单的介绍。
对于ARM芯片来说,它的寄存器很多,为了区分不同的寄存器,系统给每个寄存器都分配了一个固定的地址,地址就像每个人的一样,是唯一的。那么当你使用这个地址的时候ARM就知道你要使用哪个寄存器了,所以在编程的时候,首先要声明待操作的寄存器地址。下表就是本次课程设计要用到的寄存器的地址和位定义:
ARM芯片找到相应寄存器后,也先要设置端口配置寄存器GPBCON,也就是告诉寄存器做好接收数据或者输出数据或者响应外部中断的准备,下表为它的功能描述:
ARM设置完I/O口状态后,就准备读/写数据了。这个功能可以通过设置数据寄存器GPBDAT来实现。下表即为它的功能描述:
ARM设置完I/O口状态后,就准备读/写数据了。这个功能可以通过设置数
据寄存器GPBDAT来实现。下表即为它的功能描述:
设置完前两个寄存器后,还要设置上拉电阻使能寄存器GPBUP,顾名思义,它的作用就是告诉ARM这个端口要不要配置上拉电阻。上拉电阻、下拉电阻的作用在于,当IO引脚处于第三态(即不是高电平,也不是低电平,而是高阻态,相当于没接芯片)时,它的电平状态由上拉电阻、下拉电阻确定。下表为它的功能描述:当为0时,上拉电阻是允许的;反之,则上拉电阻是被禁止的。
到此,需要的寄存器就配置完成了,那么接下来介绍下LED在开发板上的电路原理图。
第4章课程设计过程
4.1 设计步骤
1.连接好实验环境,将仿真器的一端通过并口连接到PC机,将仿真器的另一端通过JTAG先连接到开发板JTAG接口。
2.将串口线一端接到PC机,另一端接到S3C2440的UART0接口;打开串口超级终端,设置串口属性为COM1,串口波特率(Baudrout)为115200,校验位无,数据位为8,停止位为1,检查连接是否可靠,可靠后,接入电源线,给系统上电,同时按住空格键,进入VIVI状态。
3.打开ADS codeWarrior,在ADS codeWarrior中创建工程编写代码,并对工程进行编译。
4.使用H-JTAG进行调试。
5.打开ARM的开发环境AXD Debugger,在AXD Debugger中加载可执行映像文件LED_TEXT.axf。
6.在ADS调试环境处下,全速运行映像文件,观察LED灯LED1、LED2、LED3、LED4的闪亮情况—轮流闪烁。
4.2部分原理图
图a
图b
上图a、b是实验的部分原理图,可以看出我们通过GPB5、GPB6、GPB7、GPB8来分别控制LED1、LED2、LED3、LED4。
4.3源程序:
1.main.c
#define rGPBCON (*(volatile unsigned *))0x56000010) //prot B contorl
#define rGPBDAT (*(volatile unsigned *))0x56000010) //prot B data
#define rGPBUP (*(volatile unsigned *))0x56000010) //pull-up control B void xmain(void)
{
ChangeClockDivider(3,1); //设置时钟分频比1:3:6
ChangeMPllValue(127,2,1); //设置主时钟频405MHZ
Port_Init(); //端口初始化
Isr_Init(); //中断初始化
Uart_Init(0, 115200); //串口初始化
Uart_Select(0);
Uart_Printf("the main is running\n");//向超级终端打印"the main is running"
rGPBCON = rGPBCON & (~(0xf<<10)) |( 1<< 10) |(1 << 12);
//将GPB5[11:10] 两位设置为01---即output状态,GPB6[13:12] 两位设置为01---即output状态
rGPBCON = rGPBCON & (~(0xf<<14)) |( 1<< 14) |(1 << 16);
//将GPB7[15:14] 两位设置为01---即output状态,GPB8[17:16] 两位设置为01---即output状态
rGPBUP = rGPBUP&(~(0xF<<5))|(0xF<<5);
//将GPB5、GPB6、GPB7、GPB8上拉电阻设置为disabled
while(1)
{
rGPBDAT = (rGPBDAT|(0xF<<5))&(~(0x1<<5)); //点亮LED1
Delay(10000000);//延时
rGPBDAT =( rGPBDAT|(0xF<<5))&(~(0x2<<5)); //点亮LED2
Delay(10000000);// 延时
rGPBDAT = (rGPBDAT|(0xF<<5))&(~(0x4<<5)); //点亮LED3
Delay(10000000);// 延时
rGPBDAT =(rGPBDAT|(0xF<<5))&(~(0x8<<5)); //点亮LED4
Delay(10000000);// 延时
rGPBDAT = (rGPBDAT|(0xF<<5))&(~(0x4<<5)); //点亮LED3
Delay(10000000);// 延时
rGPBDAT =( rGPBDAT|(0xF<<5))&(~(0x2<<5)); //点亮LED2
Delay(10000000);// 延时
rGPBDAT = (rGPBDAT|(0xF<<5))&(~(0x1<<5)); //点亮LED1
Delay(10000000);// 延时
}
}
2.2440lib.c
//============================================================ =======
// File Name : 2440lib.c
// Function : S3C2440 PLL,Uart, LED, Port Init
// Date :2011/22/28
// Version : 0.1
//============================================================ =======
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include
#include
#include
#include
#include
extern char Image$$RW$$Limit[];
void *mallocPt=Image$$RW$$Limit;
static int delayLoopCount;
void Delay(int time) //延时函数
{
int i, adjust=0;
if(time==0)
{
time = 200;
adjust = 1;
delayLoopCount = 800;
rWTCON = ((PCLK/1000000-1)<<8)|(2<<3);
rWTDAT = 0xffff;
rWTCON = ((PCLK/1000000-1)<<8)|(2<<3)|(1<<5); //Watch-dog timer start
}
for(;time>0;time--)
for(i=0;i if(adjust==1) { rWTCON = ((PCLK/1000000-1)<<8)|(2<<3); //Watch-dog timer stop i = 0xffff - rWTCNT; //1count->64us, 200*800 cycle runtime = 64*i us delayLoopCount = 16000000/(i*64); //200*800:64*i=1*x:100 -> x=160000*100/(64*i) } } void Port_Init(void)//I/O口初始化 { rGPACON = 0x7fffff; rGPBCON = 0x155555; rGPBUP = 0x7ff; // The pull up function is disabled GPB[10:0] rGPCCON = 0xaaaaaaaa; rGPCUP = 0xffff; // The pull up function is disabled GPC[15:0] rGPDCON = 0xaaaaaaaa; rGPDUP = 0xffff; // The pull up function is disabled GPD[15:0] rGPECON = 0xaaaaaaaa; rGPEUP = 0xffff; // The pull up function is disabled GPE[15:0] rGPFCON = 0x55aa; rGPFUP = 0xff; // The pull up function is disabled GPF[7:0] rGPGCON = 0xff95ffba; rGPGUP = 0xffff; // The pull up function is disabled GPG[15:0] rGPHCON = 0x2afaaa; rGPHUP = 0x7ff; // The pull up function is disabled GPH[10:0] rGPJDAT = (1<<12)|(0<<11); rGPJCON = 0x016aaaa; rGPJUP = ~((0<<12)|(1<<11)); rGPJDAT = (0<<12)|(0<<11); rGPJCON = 0x016aaaa; rGPJUP = 0x1fff;//~((1<<12)|(1<<11)); rEXTINT0 = 0x22222222; // EINT[7:0] rEXTINT1 = 0x22222222; // EINT[15:8] rEXTINT2 = 0x22222222; // EINT[23:16] } static int whichUart=1; void Uart_Init(int pclk,int baud)//串口初始化,设置时钟,波特率 { if(pclk == 0) pclk = PCLK; rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable rUFCON1 = 0x0; //UART channel 1 FIFO control register, FIFO disable rUFCON2 = 0x0; //UART channel 2 FIFO control register, FIFO disable rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable rUMCON1 = 0x0; //UART chaneel 1 MODEM control register, AFC disable //UART0 rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bit rUCON0 = 0x245; // Control register rUBRDIV0 = 0x34; //UART1 rULCON1 = 0x3; rUCON1 = 0x245; rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 ); //UART2 rULCON2 = 0x3; rUCON2 = 0x245; rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 ); Uart_TxEmpty(whichUart); } void Uart_Select(int ch) { whichUart = ch; } void Uart_TxEmpty(int ch) { if(ch==0) while(!(rUTRSTAT0 & 0x4)); //Wait until tx shifter is empty. else if(ch==1) while(!(rUTRSTAT1 & 0x4)); //Wait until tx shifter is empty. else if(ch==2) while(!(rUTRSTAT2 & 0x4)); //Wait until tx shifter is empty. } void Uart_SendString(char *pt) { while(*pt) Uart_SendByte(*pt++); } void Led_Display(int data) //LED显示 { rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4); } void Timer_Start(int divider) //0:16us,1:32us 2:64us 3:128us { rWTCON = ((PCLK/1000000-1)<<8)|(divider<<3); //Watch-dog timer control register rWTDAT = 0xffff; //Watch-dog timer data register rWTCNT = 0xffff; //Watch-dog count register rWTCON = (rWTCON & ~(1<<5) & ~(1<<2)) |(1<<5); } int Timer_Stop(void) { rWTCON = ((PCLK/1000000-1)<<8); return (0xffff - rWTCNT); } void ChangeMPllValue(int mdiv,int pdiv,int sdiv) { rMPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv; } void ChangeUPllValue(int mdiv,int pdiv,int sdiv) { rUPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv; } void Isr_Init(void)//中断初始化 { pISR_UNDEF = (unsigned)HaltUndef; pISR_SWI = (unsigned)HaltSwi; pISR_PABORT = (unsigned)HaltPabort; pISR_DABORT = (unsigned)HaltDabort; rINTMOD = 0x0; //All=IRQ mode rINTMSK = BIT_ALLMSK; //All interrupt is masked. rINTSUBMSK = BIT_SUB_ALLMSK; } 4.4 编译调试结果 第5章课程设计心得 通过本次课程设计,使我对S3C2440体系结构理解更加深刻,以及对相应的寄存器操作更熟悉。 通过这次课程设计,加强了我动手、思考和解决问题的能力。在设计过程中,经常会遇到这样那样的情况,就是心里想老着这样的程序设计方法可以行得通,但实际进入编译,总是有这样那样的问题,因此耗费在这上面的时间用去很多。 做课程设计同时也是对课本知识的巩固和加强,由于课本上的知识太多,平时课间的学习并不能很好的理解和运用在实践中,所以在这次课程设计过程中,我了解了很多在平时上课没怎么弄明白的知识,对于其在ARM9中的使用有了更多的认识。 平时看课本时,有时问题老是弄不懂,做完课程设计,那些问题就迎刃而解了。而且还可以记住很多东西。比如一些寄存器的功能,平时看课本,这次看了,下次就忘了,通过动手实践让我对本次课程设计用到的寄存器映象深刻。认识来源于实践,实践是认识的动力和最终目的,实践是检验真理的唯一标准。所以这个课程设计对我的作用是非常大的。 通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。 此次课程设计,学到了很多课学不到的东西,比如独立思考解决问题,出现差错的随机应变,和与人合作共同提高,都受益非浅,今后的制作应该更轻松,自己也都能扛的起并高质量的完成项目。