中南大学
嵌入式系统
实验设计报告
指导老师 吴志虎、李志民 设计者 连金涛 专业班级 测控0801班 学 号 0909081012 时 间 2011年6月
1
实验一 LED灯显示实验
一. 实验目的
1. 熟悉arm开发板基本组成电路,并通过配套教材熟悉arm芯片特性。了
解ADS1.2软件使用,并会用该软件编译调试开发板。
2. 了解H—JTAG软件原理,利用教材中提供的LED测试程序,完成实验。 二. 实验器材
PC机一台,周立功开发板一块。
注意:对LPC2103管脚的寄存器进行配置时,应该对照芯片说明手册,按照索引,找到相关寄存器,对其进行配置。 三.实验原理
EasyARM2103开发板提供了4个绿色发光二极管用作显示,电路如图1.1所示。显示电路采用了灌电流的方式来驱动发光二极管,由于微控制器LPC2103 I/O口提供的灌电流大于其拉电流,采用此驱动方式可以保证二极管发光的亮度。
图1.1 LED电路原理
四. 实验内容及步骤
1. 下面以GPIO的测试程序为例,熟悉EasyJTAG-H软件的使用方法,程序功
能设计为控制单路LED闪烁,硬件电路如图1.1所示。 2. 打开示例工程。示例工程路径:配套光盘内容->光盘内容
v1.00->3.EasyARM2103安装手册->GPIO Test,将此文件夹复制到其它目录下打开,要求存放目录必须无中文路径。打开文件夹后,建议用户先删掉“GPIO_Test_Data”文件夹,然后双击打开“GPIO Test.mcp”文件,即打开示例工程。
3. 点击“user”文件夹,打开main.c文件,见到示例代码。
4. 选择低速GPIO,控制LED灯闪烁,示例程序如程序清单所示。此示例操作
需要短接JP4的P0.17,输出控制LED1。
2
5. 编译连接工程。项目目标栏处选择DebugInFlash模式,然后编译连接工
程。
6. 仿真调试 。将计算机并口与Easy JTAG-H仿真器相连,然后再将Easy
JTAG-H仿真器的JTAG接口连接到Easy ARM2103目标板上,打开H-JTAG,检测到芯片内核信息后,选择Auto Download选项,此时会自动启动H-Flasher软件,选择目标芯片的型号,将当前的配置信息保存起来,建议将配置信息保存到安装路径下的Hconfig文件夹内。
7. 设置完成后,关闭H-JTAG Server和H-Flasher(注意:不能使用Exit项
关闭)。启动AXD,打开【Options】->【Configure Target...】,弹出Choose Target窗口,点击“ADD”添加仿真器的驱动程序,在添加文件窗口选择如D:\\Program Files\\H-JTAG 目录下的H-JTAG .dll,点击“打开”即可。 8. 在AXD环境点击运行,即可看到led亮。
附加:编写程序实现四个LED灯循环闪烁的功能。
五. 实验程序及结果
1. 一个led灯亮的源代码如下: #include \"config.h\"
# define LED1 1 << 17 /* P0.17控制LED1 */
/************************************************************ ** Function name: DelayNS ** Descriptions: 延时函数
** input parameters: uiDly 值越大,延时时间越长 ** output parameters: 无 ** Returned value: 无
************************************************************/ void DelayNS (uint32 uiDly) { uint32 i;
for (; uiDly > 0; uiDly--){
for(i = 0; i < 50000; i++); } }
/************************************************************ ** Function name: main ** Descriptions: 跳线JP4短接,LED1闪烁 ** input parameters: 无 ** output parameters: 无 ** Returned value: 无
************************************************************/ int main (void)
{ PINSEL1 = PINSEL1 & (~(0x03 << 2)); /* 将P0.17设置为GPIO */ IO0DIR = LED1; /* 设置LED控制口为输出 */ IO0SET = LED1; /* LED1熄灭 */ while (1) {
3
IO0SET = LED1; /* LED1熄灭 */ DelayNS(50); /* 延时 */ IO0CLR = LED1; /* LED1点亮 */ DelayNS(50); /* 延时 */ }
return 0; }
/******************** End Of File *********************/
运行程序后,可以看到第一个LED灯亮。
2. 四个LED灯循环闪烁的源代码如下: #include \"config.h\"
# define LED1 1 << 17 /* P0.17控制LED1 */ # define LED2 1 << 18 /* P0.18控制LED2 */ # define LED3 1 << 19 /* P0.19控制LED3 */ # define LED4 1 << 20 /* P0.20控制LED4 */ void DelayNS (uint32 uiDly) { uint32 i;
for (; uiDly > 0; uiDly--){ for(i = 0; i < 50000; i++); } }
int main (void)
{ PINSEL1 = PINSEL1 & (~(0x03 << 2)); /* 将P0.17设置为GPIO PINSEL1 = PINSEL1 & 0x0FFFFFFE7; /* 将P0.18设置为GPIO PINSEL1 = PINSEL1 & 0x0FFFFFF9F; /* 将P0.19设置为GPIO PINSEL1 = PINSEL1 & 0x0FFFFFE7F; /* 将P0.20设置为GPIO while (1) {
IO0DIR = LED1; IO0SET = LED1; /* LED1熄灭 */ DelayNS(50); /* 延时 */ IO0CLR = LED1; /* LED1点亮 */ DelayNS(50); IO0DIR = LED2; /* LED2熄灭 、延时、点亮、延时 */ IO0SET = LED2; DelayNS(50); IO0CLR = LED2; DelayNS(50);
IO0DIR = LED3; /* LED3熄灭 、延时、点亮、延时 */ IO0SET = LED3; DelayNS(50); IO0CLR = LED3; DelayNS(50);
4
*/ */ */ */
}
IO0DIR = LED4; /* LED4熄灭 、延时、点亮、延时 */ IO0SET = LED4; DelayNS(50); IO0CLR = LED4; DelayNS(50); }
return 0;
/************** End Of File ***************/
运行程序后,可看到四个LED一个接一个的亮,实现了跑马灯的功能。
5
实验二 中断实验
一. 实验目的
1. 熟悉arm开发板中断原理。并产生中断。
2. 了解快速中断和普通中断。编写嵌套中断实验。 二. 实验器材
PC机一台,周立功开发板一块 三.实验原理
同实验一
四. 实验内容及步骤
参照实验一中步骤1-8。
附加:1. 编写程序实现三个按钮分别控制三个LED灯亮灭的功能。
2. 自行编写一段实现中断嵌套的程序,阐明嵌套过程。
五. 实验程序及结果
1.一个按钮控制一个LED灯亮灭的源代码 #include \"config.h\"
#define LED 1 << 17
/*************************************************************** ** Function name: Eint0IRQ
** Descriptions: 外部中断0服务程序 ** input parameters: 无 ** ouput parameters: 无 ** Returned value: 无
***************************************************************/ void __irq Eint0IRQ(void) /* 进入中断取反LED */
{ if ((IO0PIN & (1 << 17)) == 0) { IO0SET = 1 << 17; /* 熄灭发光二极管 */ } else {
IO0CLR = 1 << 17; /* 点亮发光二极管 */ }
while((IO0PIN & (1 << 16)) == 0); /* 等待按键松开 */ EXTINT = 0x01; /* 清中断标志 */ VICVectAddr = 0x00; /* 通知VIC中断处理结束*/ }
/*************************************************************** ** Function name: main
** Descriptions: P0.16低电平触发外部中断主函数 ** input parameters: 无 ** ouput parameters: 无 ** Returned value: 无
**************************************************************/
6
int main (void) {
PINSEL1 = PINSEL1 & (~0x03);
PINSEL1 = PINSEL1 | 0x01; /* 设置P0.16为外部中断0管脚 */ INSEL1 = PINSEL1 & (~(0x03 << 2)); /* 设置P0.17为GPIO功能 */ IO0DIR = LED; /* 设置P0.17为输出 */ IO0SET = LED; /* 设置输出为高电平 */ IRQEnable(); /* IRQ中断使能 */
EXTMODE = 0x00; /* 设置外部中断为低电平触发 */ EXTPOLAR = 0x00;
VICIntSelect = 0 << 14; /* 选择EINT0为IRQ中断 */ VICVectCntl0 = 0x20 | 14; /* 将外部中断0分配给向量中断0 */ VICVectAddr0 = (uint32)Eint0IRQ; /* 设置中断服务程序地址 */ VICIntEnable = 1 << 14; /* 使能EINT0中断 */ EXTINT = 0x01; /* 清除EINT0中断标志 */ while(1); return 0; }
运行程序后,按下按钮,LED灯亮;再按一次,灯灭;再按一次,灯亮;再按一次,灯灭;如此循环。
2. 三个按钮分别控制三个LED灯亮灭的源代码 #include \"config.h\"
#define LED1 1 << 17 #define LED2 1 << 18 #define LED3 1 << 19 void __irq Eint0IRQ(void) /*进入中断取反LED */ { if ((IO0PIN & (1 << 17)) == 0) { IO0SET = 1 << 17; } /* 熄灭发光二极管*/ else { IO0CLR = 1 << 17; } /* 点亮发光二极管 */ while((EXTINT & 0x01)!= 0){ EXTINT = 0x01; } /* 按键松开清中断标志*/ VICVectAddr = 0x00; /*通知VIC中断处理结束*/ }
void __irq Eint1IRQ(void) /*进入中断取反LED */ { if ((IO0PIN & (1 << 18)) == 0) { IO0SET = 1 << 18; } /* 熄灭发光二极管 */ else { IO0CLR = 1 << 18; } /* 点亮发光二极管 */ while((EXTINT & 0x02)!= 0){ EXTINT = 0x02;} /* 按键松开清中断标志*/ VICVectAddr = 0x00; /*通知VIC中断处理结束*/ }
void __irq Eint2IRQ(void) /*进入中断取反LED */ { if ((IO0PIN & (1 << 19)) == 0) { IO0SET = 1 << 19; } /*熄灭发光二极管 */ else { IO0CLR = 1 << 19; } /* 点亮发光二极管 */ while((EXTINT & 0x04)!= 0){ EXTINT = 0x04;} /*按键松开清中断标志*/ VICVectAddr = 0x00; /*通知VIC中断处理结束*/ }
7
int main (void)
{ PINSEL1 = PINSEL1 & (~0x03); PINSEL1 = PINSEL1 | 0x01; /* 设置P0.16为外部中断0管脚 */ PINSEL0 = PINSEL0 & (~(0x03 << 30));
PINSEL0 = PINSEL0 | ( 0x01 << 30); /* 设置P0.15为外部中断2管脚 */ PINSEL0 = PINSEL0 & (~(0x03<<28));
PINSEL0 = PINSEL0 | (0x01<<28); /* 设置P0.14为外部中断1管脚 */ PINSEL1 = PINSEL1 & (~(0x03 << 2)); /* 设置P0.17为GPIO功能 */ PINSEL1 = PINSEL1 & (~(0x03 << 4)); /* 设置P0.18为GPIO功能 */ PINSEL1 = PINSEL1 & (~(0x03 << 6)); /* 设置P0.19为GPIO功能 */
IO0DIR = LED1|LED2|LED3; IO0SET = LED1|LED2|LED3; IRQEnable(); /* IRQ中断使能 */ EXTMODE = 0x00; /* 设置外部中断为低电平触发 */ EXTPOLAR = 0x00;
VICIntSelect = 0x00; /* 选择EINT0,EINT1,EINT2为IRQ中断 */ VICVectCntl0 = 0x20 | 14; /* 将外部中断0分配给向量中断0 */ VICVectCntl1 = 0x20 | 15 /* 将外部中断1分配给向量中断1 */ VICVectCntl2 = 0x20 | 16; /* 将外部中断2分配给向量中断2 */
VICVectAddr0 = (uint32)Eint0IRQ; /* 设置中断服务程序地址 */ VICVectAddr0 = (uint32)Eint1IRQ; VICVectAddr2 = (uint32)Eint2IRQ;
VICIntEnable = (1 << 14) | (1<<15)| (1<<16); /*使能EINT0,EINT1,EINT2中断 */ EXTINT = 0x07; /* 清除EINT0中断标志 */ while(1); return 0; }
/********************** END FILE ***********************/
运行程序,可以实现三个按钮分别控制三个LED灯亮灭的功能。
8
实验三 UART接口实验
一. 实验目的
掌握UARTO各控制器的设置,并能使用URTO接收PC机发过来的数据,并将数据送回PC进行显示。
二. 实验器材
PC机一台,周立功开发板一块
三. 实验内容 1.采用中断方式,通过UART0接收上位机发送的字符串,如“Hello EasyARM2103!”,然后送回上位机终端EasyARM-C.exe的数据接收窗口进行显示。
2.UART0设置为通讯波特率115200,8位数据位,1位停止位,无奇偶校验。 3.UART0的通信实验需要短接JP6的P0.0和P0.1引脚
四. 实验步骤
软件设置与调试同实验一和二基本一致,但硬件连线方面需注意: 1.将EasyARM2103教学实验开发平台上的JP6跳线短接
2. 使用串口延长线把EasyARM2103教学实验开发平台的UART0接口与PC机的COM1连接。PC机运行EasyARM软件,设置串口为COM1,波特率为115200,然后选择【设置】->【发送数据】,在弹出的发送数据窗口中点击“高级”即可打开接收窗口。
五.
/******************************************************************************
#include \"config.h\"
# define UART_BPS 115200 /* 串口通信波特率 */
volatile uint8 uiGRcvNew; /* 串口接收新数据的标志 */
uint8 uiGRcvBuf[30] = {0}; /* 串口接收数据缓冲区 */
uint32 uiGNum; /* 串口接收数据的个数 */
/****************************************************************************** ** 函数名称: DelayNS ** 函数功能: 延时函数
** 入口参数: uiDly 值越大,延时时间越长 ** 出口参数: 无
9
实验源程序及运行结果
** 返回值: 无
*****************************************************************************************/
void DelayNS (uint32 uiDly) {
uint32 i;
for (; uiDly > 0; uiDly--){ for(i = 0; i < 50000; i++); } }
/*****************************************************************************************
** 函数名称: UART0_IRQ ** 函数功能: 串口中断服务函数 ** 入口参数: 无 ** 出口参数: 无 ** 返回值: 无
*****************************************************************************************/
void __irq UART0_IRQ (void) {
uiGNum = 0;
while ((U0IIR & 0x01) == 0){ /* 判断是否有中断挂起 */
switch (U0IIR & 0x0E){ /* 判断中断标志 */
case 0x04: /* 接收数据中断 */
uiGRcvNew = 1; /* 置接收新数据标志 */
for (uiGNum = 0; uiGNum < 8; uiGNum++){ /* 连续接收8个字节 */
uiGRcvBuf[uiGNum] = U0RBR; }
break;
case 0x0C: /* 字符超时中断 */
uiGRcvNew = 1;
while ((U0LSR & 0x01) == 0x01){ /* 判断数据是否接收完
10
毕 */
uiGRcvBuf[uiGNum] = U0RBR; uiGNum++; }
break; default: break; } }
VICVectAddr = 0x00; }
/***************************************************************************************** ** 函数名称: ** 函数功能:
UARTInit
串口初始化,设置为8位数据位,1位停止位,无奇偶校验,波特率为
115200
** 入口参数: uiDly 值越大,延时时间越长 ** 出口参数: 无 ** 返回值: 无
*****************************************************************************************/ void UARTInit (void) {
uint16 uiFdiv;
U0LCR = 0x83; /* 允许设置波特率
*/
uiFdiv = (Fpclk / 16) / UART_BPS; /* 设置波特率 */
U0DLM = uiFdiv / 256;
U0DLL = uiFdiv % 256;
U0LCR = 0x03; /* 锁定波特率 */ }
/*****************************************************************************************
** 函数名称: UART0SendByte ** 函数功能: 向串口发送子节数据,并等待数据发送完成,使用查询方式 ** 入口参数: uiDat 要发送的数据
11
** 出口参数: 无 ** 返回值: 无
*****************************************************************************************/
void UART0SendByte (uint8 uiDat)
{
U0THR = uiDat; /* 写入数据 */
while ((U0LSR & 0x20) == 0); /* 等待数据发送完毕 */ }
/*****************************************************************************************
** 函数名称: UART0SendStr ** 函数功能: 向串口发送字符串
** 入口参数: uiStr 要发送的字符串指针 ** uiNum 要发送的数据个数 ** 出口参数: 无 ** 返回值: 无
*****************************************************************************************/
void UART0SendStr(uint8 const *uiStr, uint32 uiNum) {
uint32 i;
for (i = 0; i < uiNum; i++){ /* 发送指定个字节数据 */
UART0SendByte (*uiStr++); } }
/*****************************************************************************************
** 函数名称: ** 函数功能:
main
跳线JP6短接,打开串口调试软件,串口0中断方式通信
** 入口参数: 无 ** 出口参数: 无 ** 返回值: 无
*********************************************************************************************************/ int main (void) {
12
PINSEL0 = PINSEL0 & (~0x0F);
PINSEL0 = PINSEL0 | 0x05; /* 设置I/O连接到UART */
uiGRcvNew = 0;
UARTInit (); /* 串口初始化 */
U0FCR = 0x81; /* 使能FIFO,设置8个字节触发点 */ */
IRQEnable ();
VICIntSelect = 0x00000000; /* 设置所有中断为向量中断 */
VICVectCntl0 = 0x20 | 0x06; /* 设置串口中断为最高优先级
U0IER = 0x01; /* 使能接收中断
*/
VICVectAddr0 = (uint32)UART0_IRQ; /* 设置向量地址
*/
VICIntEnable = 1 << 0x06; /* 使能串口中断 */
while (1){
if (uiGRcvNew == 1){ /* 判断是否有新数据
*/
uiGRcvNew = 0; /* 清除标志 */
UART0SendStr (uiGRcvBuf, uiGNum); /* 向串口发送数据 */ } }
return 0; }
/******************************************************************************
运行程序后可用PC机上的软件观测数据的收发情况
13
14
提高部分:
数字时钟的设计:利用protues的模拟数字时钟的运行,主要使用芯片有:LPC2103、74HC573、led灯
硬件连接图:
15
源程序代码:
#include typedef void (*CPU_FNCT_VOID)(void); #define Fosc 11059200 #define Fcclk (Fosc * 4) #define Fcco (Fcclk * 4) #define Fpclk (Fcclk / 4) * 1 typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; uint8 Select[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //led灯选通信号 uint8 LED_CODES[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-f uint8 miao = 0; uint8 fen = 0; uint8 shi = 0; uint8 times=0; void delay(uint32 x) { } void timer0_ISR (void) { 16 // // // uint32 i,j; for(i=0;i times=0; miao++; if(miao==60) { fen++; miao=0; if(fen==60) { } shi++; fen=0; } } T0IR = 1; //清除定时器0中断 VICVectAddr = 0; //清除向量中断地址寄存器 } void IRQ_Exception(void) { CPU_FNCT_VOID pfnct; pfnct = (CPU_FNCT_VOID)VICVectAddr; if (pfnct != (CPU_FNCT_VOID)0) //返回最高优先级向量地址 // 确保不是错误的指针 { (*pfnct)(); //这句能关联到中断 } } void timer0Init (void) { T0TC = 0; T0PR = 0; T0MR0 = 119999; //匹配寄存器,120000-1,12000000为1秒 T0MCR = 3; //产生中断,重置TC T0TCR = 3; T0TCR = 1; //使能定时计数器 VICIntSelect=0; //初始为IRQ中断 VICVectAddr0 = (uint32)timer0_ISR; VICVectCntl0 = 0x20 | 4; //定时器计数器0为4号中断,设为最高优先级 VICIntEnable = 0x00000010; //开定时计数器0中断 17 } void display_led(uint8 x,uint8 y) { uint32 data; } int main(void) { uint8 miao_low; uint8 miao_high; while(1) { miao_low = miao%10; miao_high = miao/10; fen_low = fen%10; 18 IO0CLR |= (1<<25); data = Select[x]; //片选 IO0PIN = (IO0PIN & 0x0000ffff) | (data << 16); IO0SET |= (1<<25); IO0CLR |= (1<<25); IO0CLR |= (1<<24); data = LED_CODES[y]; //显示 IO0PIN = (IO0PIN & 0x0000ffff) | (data << 16); IO0SET |= (1<<24); IO0CLR |= (1<<24); uint8 fen_low; uint8 fen_high; uint8 shi_low; uint8 shi_high; PINSEL1 &= 0x00000000; IO0DIR |= 0xffff0000; IO0PIN |= 0xffff0000; timer0Init(); //p16-p31 as gpio //p16-p31 as out //初始化IO口 fen_high = fen/10; shi_low = shi%10; shi_high = shi/10; display_led(0,miao_low); delay(30); display_led(1,miao_high); delay(30); display_led(2,fen_low); delay(30); display_led(3,fen_high); delay(30); display_led(4,shi_low); delay(30); display_led(5,shi_high); delay(30); } } 19 因篇幅问题不能全部显示,请点此查看更多更全内容