arm实训报告.docx
《arm实训报告.docx》由会员分享,可在线阅读,更多相关《arm实训报告.docx(19页珍藏版)》请在冰豆网上搜索。
arm实训报告
【摘 要】本次实训的目的在于利用ARM系统进行简单的系统设计。
而在这次实训中,我利用ARM系统设计函数信号发生器,其基本步骤如下:
总体方案的设计与选择:
根据设计任务要求和给定的条件,分析所要设计电路应完成的功能,并将总体功能分解成若干个单元功能,分清主次和相互的关系,形成若干单元功能然后再组成总体方案。
程序的编写:
编写满足设计要求的程序并写入LPC2138芯片中,通过系统实现对电路的控制,从而达到设计的要求。
程序的调试:
在课程设计的实践过程中程序的调试占有非常重要的地位,它是最基础的阶段,也是将理论转换为实际的一个关键过程,因此调试时要谨慎小心的进行,从各方面考虑不能产生结果的原因。
本次实训制作的是函数信号发生器:
这是一个在实验和实际应用中都有重要作用,此次实训是函数信号发生器的基本功能进行设计。
【关键词】ARM7、LPC2138、DAC、定时器、GPIO、中断、按键、蜂鸣器、数字示波器、杜邦线
目录
1.设计目的与要求………………………………………………1
1.1 设计目的…………………………………………………3
1.2设计要求…………………………………………………3
2.方案设计与论证…………………………………………………3
1、设计分析………………………………………………………………3
2、方案论证………………………………………………………………3
3、方案选择………………………………………………………………3
3.硬件电路………………………………………………………3
1、器件………………………………………………………………3
2、器件连接说明……………………………………………………………4
4.软件设计………………………………………………………………5
5调试……………………………………………………………7
6.结论与心得……………………………………………………………7
7.参考文献………………………………………………………………7
附录实验程序………………………………………………………7
1、设计的目的与要求
1.1设计目的
(1)本次课程设计是在学习了《深入浅出ARM7》课程之后综合利用所学知识完成一个应用系统设计并在实验室实现。
(2)通过实训,加深了对理论知识的理解,并且把理论知识应用在实际中,培养自己的动手能力和解决实际问题的能力,进一步熟悉和掌握ARM的结构及工作原理。
(3)熟悉ARMDevelopersuitv1.2的调试和仿真,提高软件调试的能力,通过对实际程序的设计和调试,进一步掌握模块化程序设计方法和调试技术。
(4)通过完成一个程序开发的完整过程,了解开发一个ARM应用系统的全过程,为今后从事相应事业打下基础。
1.2设计要求
(1)用D/A输出产生幅度可调的正弦波、方波、三角波、锯齿波。
(2)用定时器对波形的输出频率进行控制。
(3)利用KEY3、KEY4、KEY5、KEY6对正弦波、方波、三角波、锯齿波进行控制,并且要求在显示一种波形的时候,能在仿真的LED数码显示器中显示出当前波形的名称。
(4)通过按键KEY1和KEY2,可对波形的幅度进行增加和减小的调节,并且要设置幅度的上下限。
2、方案的设计与论证
2.1设计分析
此次实训的目的在于用ARM7的知识点,在EasyARM2131开发板中进行波形发生器的设计,产生能调幅的正弦波、方波、三角波、锯齿波。
并且能实现各种波形的定时切换和显示波形名称。
2.2方案论证
方案一:
采用ARM的PWM功能产生方波,方波的频率可以达到几百K,外接滤波电路,通过选频,得到各种波形。
可以通过PWM直接调频调幅,也可以通过外接电路实现。
方案二:
利用的EasyARM2131开发板中的D/A转换器产生波形。
通过定时器来控制频率。
D/A输出的波形很稳定。
2.3方案选择
在第一种方案,虽然频率范围比较宽,外接电路也很简单,但实现任意波形有些复杂,而且外接电路固定后,难以改变波形。
在第二种方案中可以通过编写函数,方便的得到想要的波形,不需要外接的电路,而且输出的波形很稳定。
考虑到输出波形的稳定性和自己对波形函数编写的熟悉。
我选择了第二种方案。
3、硬件电路部分
3.1器件原理
(1)EasyARM2131开发板是广州周立功公司设计的EasyARM系列开发套件之一,采用了
PHILIPS公司基于ARM7TDMI-S核、单电源供电、LQFP64封装的LPC2131,具有JTAG
仿真调试、ISP编程等功能。
开发板上提供了一些键盘、LED、蜂鸣器等常用功能部件,还具有RS232接口电路、I2C
存储器电路。
另外,用户也可以更换兼容的CPU进行仿真调试,如LPC2132、LPC2138、
LPC2142等。
灵活的跳线组合(开发板内使用的所有I/O均可断开连接),还有用户I/O接
口,极大地方便了用户进行32位ARM嵌入式系统的开发实验。
EasyARM2131开发板布局图如下图所示。
(2)EasyARM2131开发板可以使用与LPC2131兼容的CPU进行仿真调试,倘若使用
LPC2132/LPC2138芯片,则可以其10位D/A转换器进行DAC输出实验。
D/A转换器的其参考电压与A/D转换器的相同,EasyARM2131开发板的参考源选择如图1.13所示。
如图1.15所示,通过JP3和JP4选择连接,LPC2132/LPC2138的Aout输出经过R14连接到AD0.1,这样就可以直接使用AD0.1来检测Aout输出电压值。
当需要将DAC输出连接到用户的电路时,先把JP3选择短接到“P0.25”端,然后从用
户接口J6引出Aout信号,如图1.16所示。
D/A转换器
具有以下特性:
10位数模转换器;
电阻串连结构;
缓冲输出;
掉电模式;
选择的转换速率与功率有关。
注:
仅LPC2132/2134/2136/2138有D/A。
他的寄存器如下:
写程序时,只要将要转化的值赋给DACR的6到15位,然后定时器定时给他转换的时间。
则可以完成转化。
我们采用10的转化,也即1024个采样点的转化,设定时时间为t0,则波形的频率计算方法为:
f=1/(1024*t0)。
设赋的值为value,则波形的幅度计算方法为A=VALUE/1024*3.3.
(3)中断
LPC2138通过向量中断控制器(VIC)管理中断。
外设中断信号需要经过2个开关才能
到达ARM内核,真正产生异常,逻辑示意图如下图所示。
如果在VIC中使能了相应外
设的中断,外设中断才能到达VIC并向内核发送中断请求;只有使能了内核中断IRQ或者
FIQ,内核才能真正产生异常。
硬件图如下
中断的过程示意图如下:
(4)按键的连接图
不按下时为高电平,按下时变为低电平
3.2器件连接说明
(1)由于D/A转换时要用到基准电压,所以JP5要连接verf;
(2)KEY1连接P0.16;KEY2连接P0.17;KEY3连接P0.18,KEY4连接P0.19,KEY5连接P0.20,KEY6连接P0.21。
(3)数字示波器连接DAC端口和GND端。
4、软件部分设计
系统软件采用C语言编程,程序详情请看程序附录
程序的流程图如下:
4、调试过程及结果
按照器件连接说明连接好EasyARM2131开发板上的跳线后,再将数字示波器的探头分别接在DAC和GND端,运行程序,开始调试。
在一开始时,由于用定时器设置的波形频率太小,导致在示波器上观察到波形不太稳定而且线条很粗,于是自己就试着改定时器上的时间来增大频率。
但是后来又发现把波形频率调大了,波形仍不能很好。
想了很久,都不能明白原因,经老师指点后,发现是在定时中断的子程序那里执行了很多条语句,那些语句是用来在仿真的LED数码显示器上显示函数名称和判断是否有按键的作用。
后来才明白,原来在过短的时间内执行太多的语句,会影响系统的稳定性和效率,因此波形才会不好。
所以我将那些语句放到了主程序中,问题就得到了解决,波形也很好了。
程序的运行结果是在EasyARM2131开发板上不同的按键控制不同类型的波形,从KEY3到KEY6按下,示波器上的波形就变换一次。
因此示波器上会根据人为的控制变换不同的波形,显示正弦波,三角波,方波,锯齿波。
并且在仿真的LED数码显示器中显示相应的波形名称。
当示波器上显示正弦波的时候,在仿真的LED数码显示器中显示SIN,当示波器上显示三角波的时候,在其上显示SANJIAO,当显示方波的时候,在其上显示FANG,当在示波器上显示锯齿波的时候,在其上显示JUCHI。
并且在波形显示的过程中,按键KEY1,KEY2键可以分别增加和减少波形的幅度,增加减少到一定的上下限幅度时又会跳回到原来的幅度。
5、课程设计体会
经过本周的实训之后,我对课本上的ARM知识掌握得更好,并在实训过程中,不断的发现问题,解决问题,提高了自己动手和编程的能力。
在编写程序的过程中,我更加深入的了解了正弦波,三角波,方波和锯齿波的编写方法和EasyARM2131开发板上的D/A转换器的用法,通过不断的调试程序,也掌握了用定时器控制波形输出频率的方法。
在输出波形的不稳定问题上,我困惑了很久,经过老师的指点下,让我明白了,要使波形输出的稳定,首先电源电压要稳定,然后就是在程序的编写中,不能在一小段时间内执行过多的指令。
这样会影响系统的效率。
通过解决了以上问题,波形就变得很好了。
本次实训还让我认识到流程图的重要性,以前在编程前,我就喜欢按照功能写语句,没先把流程图写出来。
但是在此次实训时,这让我走了很大的弯路,有很多的问题是因为自己太过于空想,而把一些语句放在了错误的位置。
当把流程图画出来之后就可以明显发现问题的所在了,也很快的解决了问题。
所以我认识到,以后要编写程序时,先写流程图是很有必要的。
6、参考文献
(1)《深入浅出ARM7》北京航空航天大学出版社
(2)《C程序设计完全手册》人民邮电出版社
(3)《C程序设计》清华大学出版社
(4)《电子报合订本(上)》四川出版集团—四川科学技术出版社
(5)《数字电子技术基础》高等教育出版社
附录:
实训程序
/********************************************************************************************************/
#include"config.h"
#include"math.h"
#include"stdio.h"
typedefstructUartMode
{
uint8datab;//字长度5/6/7/8
uint8stopb;//停止位1/2
uint8parity;//奇偶校验0-无校验,1-奇校验,2-偶校验
}UARTMODE;
constuint32KEY1=1<<16;//P0.16连接KEY1
constuint32KEY2=1<<17;//P0.17连接KEY2
#defineBEEP1<<15//P0.15控制蜂鸣器,低电平蜂鸣
uint32cnt=0,count=9;
uint16delay;
uint16l=0;
uint16k=0,b,c,da=1;
uint16zj_flag=0;
uint16table[1024];
uint16a=0,v=13;
#defineUART_BPS115200//通讯波特率115200
#defineHC595_CS(1<<29)//P0.29口为74HC595的片选
/*
*******************************************************************************************************
**函数名称:
UART0_Init()
**函数功能:
初始化串口0:
波特率115200,8位数据位,1位停止位,无奇偶校验。
**入口参数:
无
**出口参数:
无
*******************************************************************************************************
*/
uint8constDISP_TAB[10]={
//0123456789
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
voidMSPI_Init(void)
{
PINSEL0=(PINSEL0&(~(0xFF<<8)))|(0x55<<8);
SPCCR=0x52;//设置SPI时钟分频
SPCR=(0<<3)|//CPHA=0,数据在SCK的第一个时钟沿采样
(1<<4)|//CPOL=1,SCK为低有效
(1<<5)|//MSTR=1,SPI处于主模式
(0<<6)|//LSBF=0,SPI数据传输MSB(位7)在先
(0<<7);//SPIE=0,SPI中断被禁止
}
uint8MSPI_SendData(uint8data)
{
IOCLR=HC595_CS;//片选74HC595
SPI_SPDR=data;
while(0==(SPI_SPSR&0x80));//等待SPIF置位,即等待数据发送完毕
IOSET=HC595_CS;
return(SPI_SPDR);
}
voidSendByte(uint8data)
{
U0THR=data;
while((U0LSR&0X20)==0);//等待数据发送
}
voidPC_DispChar(uint8no,uint8chr)
{
SendByte(0xff);
SendByte(0x80);
SendByte(no);
SendByte(chr);
SendByte(0x00);
}
uint8UART0_Init(uint32baud,UARTMODEset)
{
uint32bak;
//参数过滤
if((0==baud)||(baud>115200))return(0);
if((set.datab<5)||(set.datab>8))return(0);
if((0==set.stopb)||(set.stopb>2))return(0);
if(set.parity>4)return(0);
//设置串口波特率
U0LCR=0x80;//DLAB=1
bak=(Fpclk>>4)/baud;
U0DLM=bak>>8;
U0DLL=bak&0xff;
//设置串口模式
bak=set.datab-5;
if(2==set.stopb)bak|=0x04;
if(0!
=set.parity)
{
set.parity=set.parity-1;
bak|=0x08;
}
bak|=set.parity<<4;
U0LCR=bak;
return(0);
}
/*********************************
正弦
****************************************************/
voidsin_wave(void)
{a=(a+1)%1024;
DACR=((table[a]*v/26)<<6);//把值送入DACR计算电压
}
/*
***********************************************************
**三角波
*************************************************************
*/
voidtrip_wave(void)
{
if(zj_flag==0)//三角波的递增
{
b+=2;
if(b>1020)
{
zj_flag=1;
}
}
else
{//三角波的递减
b-=2;
if(b<10)
{
b=10;
zj_flag=0;
}
}
DACR=((b*v/26)<<6);//把值送入DACR计算电压
}
/*********************************
方波
****************************************************/
voidfang_wave(void)
{
k++;
if(k<512)
c=512;//方波的高电平
else
c=10;//方波的低电平
if(k>1024)
k=1;
DACR=(c*v/13<<6);//把值送入DACR计算电压
}
/************************************************************
锯齿波
**************************************************************/
voidjuchisave()
{da++;//锯齿波的递增
if(da>=1024)
da=1;
DACR=((da*v/26)<<6);//把值送入DACR计算电压
}
/*
*********************************************************************************************************
**函数名称:
IRQ_Timer0()
**函数功能:
定时器0中断服务程序,取反LED9控制口。
**入口参数:
无
**出口参数:
无
*********************************************************************************************************
*/
void__irqIRQ_Timer0(void)
{
cnt++;
if(cnt<=1000000)//判断是否在10秒内
sin_wave();//显示正弦波
elseif((cnt>1000000)&(cnt<=2000000))//判断是否在10—20秒内
trip_wave();//显示三角波
elseif((cnt>2000000)&(cnt<=3000000))//判断是否在20—30秒内
fang_wave();//显示方波
elseif((cnt>3000000)&(cnt<=4000000))//判断是否在30—40秒内
juchisave();//显示锯齿波
else
cnt=0;
T0IR=0x01;//清除中断标志
VICVectAddr=0x00;//通知VIC中断处理结束
}
/*
*********************************************************************************************************
**函数名称:
Timer1_CapInt()
**函数功能:
定时器1捕获中断服务程序
**入口参数:
无
**出口参数:
无
*********************************************************************************************************
*/
/*
*********************************************************************************************************
**函数名称:
main()
**函数功能:
用P0.7控制BEEP,让BEEP鸣叫。
**调试说明:
需将跳线JP5和LED短接。
*********************************************************************************************************
*/
intmain(void)
{
uint16i;
uint8rcv_data;
constdoubleT=(2*3.1415926)/1024;//把一个周期分成2048份
PINSEL0=0x00005505;//设置P0[7:
4]引脚连接SPIO,P0.0,P0.1引脚连接UART0
PINSEL1=(2<<18)|0x00000000;//设置P0.25连接DAC,设置P0.16,P0.17连接GPIO
UARTMODEuart0_set;
uart0_set.datab=8;
uart0_set.stopb=1;
uart0_set.parity=0;
UART0_Init(115200,uart0_set);
U0FCR=0x01;//FIFO使能
MSPI_Init();//初始化SPI接口
IO0DIR=HC595_CS|BEEP;//设置74HC595片选为输出,设置蜂鸣器端口为输出
IO0SET=BEEP;//设置蜂鸣器端口为高电平
for(i=0;i<1024;i++)//循环1024次
{
table[i]=512*(1+sin(T*i));//定义table数组
}
DACR=(0<<16);//最大定时1US,电流700UA
IRQEnable();//IRQ中断使能
/*定时器0初始化*/
T0TC=0;//定时器设置为0
T0PR=0;//时钟不分频
T0MCR=0x03;//设置T0MR0匹配后复位T0TC,并产生中