基于ARM9的AD接口驱动程序的设计报告资料.docx

上传人:b****5 文档编号:5845694 上传时间:2023-01-01 格式:DOCX 页数:20 大小:27.83KB
下载 相关 举报
基于ARM9的AD接口驱动程序的设计报告资料.docx_第1页
第1页 / 共20页
基于ARM9的AD接口驱动程序的设计报告资料.docx_第2页
第2页 / 共20页
基于ARM9的AD接口驱动程序的设计报告资料.docx_第3页
第3页 / 共20页
基于ARM9的AD接口驱动程序的设计报告资料.docx_第4页
第4页 / 共20页
基于ARM9的AD接口驱动程序的设计报告资料.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

基于ARM9的AD接口驱动程序的设计报告资料.docx

《基于ARM9的AD接口驱动程序的设计报告资料.docx》由会员分享,可在线阅读,更多相关《基于ARM9的AD接口驱动程序的设计报告资料.docx(20页珍藏版)》请在冰豆网上搜索。

基于ARM9的AD接口驱动程序的设计报告资料.docx

基于ARM9的AD接口驱动程序的设计报告资料

  

目录

第一章引言-1-

第二章设计目的-2-

第三章设计原理-3-

第四章关键技术-4-

4.1ARM9处理器-4-

4.2嵌入式C语言开发技术-4-

4.3ADS开发环境-5-

4.4基于ARM9的硬件-6-

第五章程序流程-7-

5.1初始化和结束程序-7-

5.2服务于I/O请求的函数-7-

5.3中断服务程序-9-

第六章主要源代码-10-

6.1定义与A/D转换相关的寄存器-10-

6.2对A/D转换器进行初始化-10-

6.3获取A/D的转换值-10-

6.4主函数-11-

6.5子函数-15-

第七章结论-23-

第八章心得体会-24-

参考文献-25-

 

第一章引言

由于Linux系统是开源系统,其内核和各种开发工具都可以从网络上轻易获取,使其在嵌入式系统的开发中得到了越来越广泛的应用。

但Linux系统本身并没有对种类繁多的硬件设备都提供现成的驱动程序,特别是由于工程应用中的灵活性,其驱动程序更是难以统一,这时就需开发一套适合于自己产品的设备驱动,使得Linux设备驱动程序的开发在整个嵌入式系统开发工作中占有很重要的地位。

而基于ARM架构的中高档的嵌入式系统应用已经非常广泛,本文针对现在非常流行的一款三星公司生产的ARM9嵌入式微处理器S3C2440,在Linux操作系统下实现了多路AD转换的驱动,通过该驱动程序实例,介绍在Linux系统下驱动程序编写的一般方法,包括驱动程序和测试程序的编写。

1硬件设备硬件系统核心部分采样的是韩国三星公司设计的基于ARM9的嵌入式微处理器S3C2440。

S3C2440配合SDRAM、FLASH、USB、网口和串口等就构成了基本的ARM嵌入式硬件平台。

本文针对现在非常流行的一款三星公司生产的ARM9嵌入式微处理器S3C2410,在Linux操作系统下实现了多路AD转换的驱动,通过该驱动程序实例,介绍在Linux系统下驱动程序编写的一般方法,包括驱动程序和测试程序的编写。

 

第二章设计目的

通过课程设计,熟悉基于ARM微处理器的嵌入式系统开发的过程,掌握嵌入式系统开发的A/D接口原理,掌握S3C2410的AD相关寄存器的配置及编程应用方法,锻炼实践动手能力和团队协作能力。

 

第三章设计原理

A/D转换器是模拟信号和CPU之间联系的接口,它是将连续变化的模拟信号转换为数字信号,以供计算机和数字系统进行分析、处理、存储、控制和显示。

在工业控制和数据采集及许多其他领域中,A/D转换是不可缺少的。

按照转换速度、精度、功能以及接口等因素,常用的A/D转换器有以下两种:

(1)双积分型的A/D转换器

双积分型也称为二重积分式,其实质是测量和比较两个积分的时间,一个是对模拟信号电压的积分时间T,此时间常是固定的,另一个是以充电后的电压为初值,对参考电源Vn的反向积分,积分电容被放电至零,所需的时间Ti。

模拟输入电压Vi与参考电压Vref之比,等于上述两个时间之比。

由于Vref、T时间固定,而放电时间Ti可以测出,因而可以计算出模拟输入电压的大小。

(2)逐次逼近型的A/D转换器

逐次逼近型也称为逐位比较式,它的应用比积分型更为广泛,通常主要有逐次逼近寄存器SAR、D/A转换器、比较器以及时序和逻辑控制等部分组成。

通过逐次把设定的SAR寄存器中的数字量经D/A转换后得到电压Vc与待转换模拟电压V0进行比较。

比较时,先丛SAR的最高位开始,逐次确定各位的数码应为‘1’还是‘0’,而得到最终的转换值。

其工作原理为:

转换前,先将SAR寄存器各位清零,转换开始时,控制逻辑电路先设定SAR寄存器的最高位为‘1’,其余各位为‘0’,此值经D/A转换器转换成电压Vc,然后将Vc与输入模拟电压Vx进行比较。

如果Vx大于等于Vc,说明输入的模拟电压高于比较的电压,SAR最高位的‘1’应保留;如果Vx小于Vc,说明SAR的最高位应清除。

然后在SAR的次高位置‘1’,依上述方法进行D/A转换和比较。

如此反复上述过程,直至确定出SAR寄存器的最低位为止,此过程结束后,状态线改变状态,表明已完成一次转换。

最后,逐次逼近寄存器SAR中的数值就是输入模拟电压的对应数字量。

位数越多,越能准确逼近模拟量,但转换所需的时间也越长。

 

第四章关键技术

4.1ARM9处理器

新一代的ARM9处理器,通过全新的设计,采用了更多的晶体管,能够达到两倍以上于ARM7处理器的处理能力。

这种处理能力的提高是通过增加时钟频率和减少指令执行周期实现的。

ARM9系列包括三种处理器:

ARM926EJ-S、ARM946E-S和ARM968E-S。

(1)ARM968E-S

面积最小、包含DSP增强功能的ARM9处理器,针对低功耗、数据密集型、嵌入式实时应用。

面积最小、功耗最低的ARM9处理器是众多实时类型应用的理想之选。

通过可轻松从标准接口集成的紧密耦合内存,该处理器可高效工作。

(2)ARM946E-S

具有MPU的DSP增强型高速缓存处理器,针对运行RTOS的实时应用。

一种具有可选高速缓存接口以及完整的内存保护单元的实时处理器。

对于大部分代码位于主存储器的应用,该处理器非常有用,它按需加载到高速缓存中,同时关键的异常处理代码和数据仍本地保留在紧密耦合内存中。

(3)ARM926EJ-S

具有Java加速、DSP扩展和MMU的应用处理器,针对基于操作系统的应用。

ARM926EJ-S处理器为入门级处理器,可支持完全版操作系统,其中包括Linux、WindowsCE和Symbian。

因此,此处理器是众多需要完整图形用户界面的应用的理想之选[1]。

4.2嵌入式C语言开发技术

由于现在越来越多的产品都采用嵌入式开发,所完成的计算和控制工作也日趋复杂,而嵌入式系统是一种资源十分有限的系统(这主要表现在程序存储器资源的不足上),因此在程序设计时如何使用好这些有限的资源就显得十分重要。

用C语言变成虽然具有许多的优点,但是生成的代码相对较长,若编程技术不好,生成的代码有可能比汇编语言生成的代码长几倍,因而对编程者来说,应该注意到嵌入式C语言和一般意义上的标准C语言的区别,对程序进行适当的优化。

嵌入式C语言编程不同于一般的C语言编程的一个显著特点,就是要和程序存储器资源结合起来。

虽然其提供的数据类型十分丰富,但其中只有bit和char等数据类型是机器语言直接支持的数据类型,用此类数据类型的语句所生成的代码较短;而其他的数据类型如整形、浮点型等数据要有一定的内部程序或内部函数的支持,用该类数据类型的语句生成的代码则相对教程。

4.3ADS开发环境

1.运行ADS1.2集成开发环境(CodeWarriorforARMDeveloperSuite),点击File|New,在New对话框中,选择Project栏,其中共有7项,ARMExecutableImage是ARM的通用模板。

选中它即可生成ARM的执行文件。

同时,还要在,Projectname栏中输入项目的名称,以及在Location中输入其存放的位置。

按确定保存项目。

2.在新建的工程中,选择Debug版本,使用Edit|DebugSettings菜单对Debug版本进行参数设置。

3.点击DebugSetting按钮,选中TargetSetting项,在Post-linker栏中选中ARMfromELF项。

按OK确定。

这是为生成可执行的代码的初始开关。

4.点击ARMAssembler,在ArchitectureorProcesser栏中选ARM920T。

这是要编译的CPU核。

5.点击ARMCCompliler,在ArchitectureorProcesser栏中选ARM920T。

这是要编译的CPU核。

6.点击ARMlinker,在outpur栏中设定程序的代码段地址,以及数据使用的地址。

ROBase栏中填写程序代码存放的起始地址,RWBase栏中填写程序数据存放的起始地址。

该地址是属于SDRAM的地址。

在options栏中,Imageentrypoint要填写程序代码的入口地址,其他保持不变,如果是在SDRAM中运行,则可在0x30000000—0x33ffffff中选值,这是64MSDRAM的地址,但是这里用的是起始地址,所以必须把你的程序空间给留出来,并且还要留出足够的程序使用的数据空间,而且还必须是4字节对齐的地址(ARM状态)。

通常入口点Imageentrypoint为0x30000000,ro_base也为0x30000000。

在Layout栏中,在Placeatbeginningofimage框内,需要填写项目的入口程序的目标文件名,如,整个工程项目的入口程序是2410init.s,那么应在Object/Symbol处填写其目标文件名2410init.o,在Section处填写程序入口的起始段标号。

7.在DebugSetting对话框中点击左栏的ARMfromELF项,在Outputfilename栏中设置输出文件名*.bin,前缀名可以自己取,在Outputformat栏中选择Plainbinary,这是设置要下载到flash中的二进制文件。

8.到此,在ADS1.2中的基本设置已经完成,可以将该新建的空的项目文件作为模板保存起来。

首先,要将该项目工程文件改一个合适的名字,如S3C2410ARM.mcp等,然后,在ADS1.2软件安装的目录下的Stationary目录下新建一个合适的模板目录名,如,S3C2410ARMExecutableImage,再将刚刚设置完的S3c2410ARM.mcp项目文件存放到该目录下即可。

这样,就能看到该模板。

、9.新建项目工程后,就可以执行菜单Project|AddFiles把和工程所有相关的文件加入,ADS1.2不能自动进行文件分类,用户必须通过Project|CreateGroup来创建文件夹,然后把加入的文件选中,移入文件夹。

或者鼠标放在文件填加区,右键点击,即出!

先选AddFiles,加入文件,再选CreateGroup,创建文件夹,然后把文件移入文件夹内。

读者可根据自己习惯,更改Edit|Preference窗口内关于文本编辑的颜色、字体大小,形状,变量、函数的颜色等等设置。

4.4基于ARM9的硬件

ARM9系统的硬件设计,是一项复杂的系统工程,必须有坚实的准备知识,包括电路基础、模拟电路、数字电路、微机原理、接口技术、嵌入式原理、ARM系统原理等等。

不仅需要硬件相关的知识,而且需要软件方面的知识,如操作系统。

由于是复杂的硬件系统的设计,还需要掌握EDA软件。

此外,由于硬件开发还涉及焊接、调试等工序,所以还应该对元器件的封装、电气特性等有所了解,并掌握焊接技术,能对一般的贴片元件进行手工焊接。

这方面的知识需要在实践中积累经验,很难一蹴而就。

做ARM9系统的硬件设计,一般采用六层板,成本较高。

为了避免因设计的错误而付出沉重的代价,应从简单的硬件设计做起,有助于提高ARM9系统设计的成功率。

第五章程序流程

驱动程序的组成及设计驱动程序是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,使得应用程序可以像操作普通文件一样对硬件设备进行操作。

Linux将设备分为字符设备,块设备和网络设备三种。

A/D转换是属于字符设备。

设备驱动程序主要完成如下功能[4]:

(l)对设备初始化和释放;

(2)把数据从内核传送到硬件和从硬件读取数据;

(3)读取应用程序传送给设备文件的数据并回送应用程序请求的数据;

(4)检测和处理设备出现的错误。

在系统内部,I/O设备的存取是通过一组固定的入口点完成与外部的通信,这些入本驱动程序的工作流程如图1所示,主要由3大模块组成。

5.1初始化和结束程序

在驱动程序设计中通常通过使用__init和__exit声明来定义用户自己的初始化函数和清除函数,然后使用module_init(mydev_int)和module_exit(mydev_cleanup)来完成设备驱动程序的注册和卸载(其mydev_init和mydev_cleanup函数即为用__init和__exit声明的初始化函数和清除函数)。

在本驱动程序中初始化函数adc_init()主要完成一些初始化的工作,包括对硬件设备的初始化、中断的注册、设备的注册等,初始化部分仅在驱动程序初始化的时候被调用一次,而缷载函数则完成相反的功能。

5.2服务于I/O请求的函数

在系统内部,I/O设备的存取是通过一组固定的入口点完成与外部的通信,这些入口点通过一个file_operations数据结构在注册设备文件时与外部调用函数关联起来,它是字符设备驱动程序的核心,结构中的每个成员名字都对应着一个系统调用。

该结构实际就是声明了针对各种设备不同操作的函数指针,Linux下驱动程序的大部分工作,实际上就是完成上述各种操作方法的函数。

但是实际的驱动程序中并不需要为每一个操作都编写相应的实现代码,对于不需要的操作,可在初始化file_oper-ations结构时在相应的位置赋予空指针NULL即可[5]。

本驱动通过调用open入口点,为将要进行的I/O操作做好准备工作,包括初始化中断事件变量、设置AD转换通道等,在此通过一个for循环来设置4个AD转换通道,以实现打开4个AD通道的要求;通过read入口点设置ADCCON控制寄存器启动AD转换,并设置中断事件变量使程序进入等待转换结束,在中断事件激活后,通过copy_to_user内核函数将转换结果传送到用户空间变量指针来完成整个A/D转换。

AD转换大部分过程都是在adc_read()函数(它为应用程序系统调用read函数时调用的函数)里实现的,它是AD转换的主体函数,在此函数中通过判断通道号实现了多通道AD转换,部分实现代码如下:

staticssize_tadc_read(structfile*filp,char*buffer,size_tcount,loff_t*ppos)

{

START_ADC_AIN(adcdev.channel,adcdev.prescale);//启动AD转换

wait_event_interruptible(adcdev.wait,ev_adc);//通过中断的方式等待结果

if(converter_channel==3)//通道的选择

{

converter_channel=0;

}

elseconverter_channel++;

adcdev.channel=converter_channel;value=adc_data;…

intr=copy_to_user(buffer,str,len);//将内核空间中的数据拷贝到用户空间,以供应用程序使用

}

5.3中断服务程序

在Linux系统中,中断是由系统来管理与维护的。

中断服务子程序在初始化函数中调用irq_request函数与相应中断号关联,并将该中断的相关信息添加到系统的中断信息列表中,以便在中断发生时供系统检索。

目标机上完成某一AD转换后,将产生一中断号为IRQ_ADC_DONE的中断,系统将自动检索并调用相应的中断服务子程序。

此处的中断服务子程序完成ADC寄存器中读取转换结果(通过adc_data=ADCDAT0&0x3ff;实现)、激活中断事件变量,从而read函数结束等待状态,返回AD转换结果

本次课程设计仅使用实验教学系统的CPU板。

在进行本实验时,LCD电源开关、音频的左右声道开关、AD通道选择开关、触摸屏中断选择开关等均应处在关闭状态。

在PC机并口和实验箱的CPU板上的JTAG接口之间,连接仿真调试电缆。

使用串口线连接PC机串口1和实验箱CPU板的串口,使用直连线连接底板串口2和PC机上的串口2之间的电缆。

检查连接是否可靠,可靠后,接入电源线,系统上电。

拨码开关SW3为选中的A/D转换的通道,值得注意的是本实验系统八个通道可以同时采集一个信号源。

实验时要选中采集的通道号,即对应的SW3开关拨到ON状态。

例如SW3的1拨到ON状态,说明用AD转换器的通道1采集,如果,8个通道全部选择为ON,则表示用8个通道采集。

本实验程序使用通道1采集数据,所以,SW3的1应该拨到ON状态。

要给ADIN一个输入信号,可以是底板上的SQUARE信号和SINE信号,也可是外部信号,但是必须注意,接外部电压信号时,要共地,以及信号的电压范围为0—2.5V

打开ADS1.2开发环境,连接编译运行通过后,全速运行映象文件。

打开LCD电源开关,检查SW3上选择的是通道几。

确认后,观察LCD上1通道当前采集的情况。

由于液晶的显示速度比波型慢许多,所以要暂停程序才会看到比较清楚的波形。

由于信号源输出后,电压经过缩放和偏置处理。

使得的ARMCPU板所采集到的电压值的变化范围不足0—2.5V,故而采集到的数字值,不能满程。

但这些不会影响实验原理的显示。

第六章主要源代码

6.1定义与A/D转换相关的寄存器

#defineradcCON(*(volatitleunsigned*))0x58000000)//ADC控制寄存器

#defineradcTSC(*(volatitleunsigned*))0x58000004)//ADC控制寄存器

#defineradcDLY(*(volatitleunsigned*))0x58000008)//ADC控制寄存器

#defineradcDAT0(*(volatitleunsigned*))0x5800000c)//ADC控制寄存器

#defineradcDAT1(*(volatitleunsigned*))0x58000010)//ADC控制寄存器

6.2对A/D转换器进行初始化

VoidAD_init(unsignedcharch)

{

rADCDLY=100; //ADC启动或间隔延时

rADCTSC=0;//选择ADC模式

rADCCON=(1<<14)|(49<<6)|(ch<<3)|(0<<2)|(0<<1)|(0);//设置ADC控制寄存器

}

6.3获取A/D的转换值

IntGET_AD(unsignedcharch)

{

IntI;

Intval=0;

If(ch>7)return0;

For(i=0;i<16:

i++)

{

Radccon|=0x1;

Radccon=radccon&0xffc7|(ch<<3);

While(radccon&0x1);

While(!

(Radccon&0x8000));

Val+=(Radcdat0&0x03ff);

Delay(10);

}

Return(val>>4);

}

6.4主函数

#include"..\lcddrv\inc\lcd.h"

#include"..\..\lcddrv\inc\lcdlib.h"

#include"..\gui\glib\glib.h"

#include"target.h"

#include"2410LIB.h"

#include"2410addr.h"

#include"adc.h"

externGUI_FONTGUI_Font8x16;

#defineLength640

voidShowWave(short*buffer,intp,short*buffer2)

{

inti,j;

j=0;

//Set_Color(GUI_BLUE);

//Fill_Rect(0,0,319,239);

for(i=p-1;i

{

Draw_Point(j,buffer2[i]);

j++;

}

for(i=0;i

{

Draw_Point(j,buffer2[i]);

j++;

}

Set_Color(GUI_RED);

j=0;

for(i=p;i

{

Draw_Point(j,buffer[i]);

j++;

}

for(i=0;i

{

Draw_Point(j,buffer[i]);

j++;

}

Uart_Printf("%d\n",buffer[i]);

}

voidShowWavebuffer(short*buffer)

{

inti,j;

j=0;

Set_Color(GUI_BLUE);

Fill_Rect(0,0,639,479);

Set_Color(GUI_RED);

for(i=0;i

{

Draw_Point(i,buffer[i]);

}

}

voidMain(void)

{

inti,p=0;

unsignedshortbuffer[Length];

unsignedshortbuffer2[Length];

Target_Init();

GUI_Init();

Set_Color(GUI_BLUE);

Fill_Rect(0,0,639,479);

Set_Color(GUI_RED);

Draw_Line(0,250,639,250);

Set_Font(&GUI_Font8x16);//设定字体类型API

Set_Color(GUI_WHITE);

Set_BkColor(GUI_BLUE);//设定背景颜色API

Fill_Rect(0,0,639,3);

Fill_Rect(0,0,3,479);

Fill_Rect(636,0,639,479);

Fill_Rect(0,476,639,479);

Disp_String("ADCDEMO",(640-8*8)/2,50);

for(i=0;i

buffer[i]=0;

while

(1)

{

buffer[p]=Get_AD(0);

ShowWave(buffer,p,buffer2);

Buffer2[p]=buffer[p];//doublebuffer

p++;

if(p>=Length)

p=0;

}

while

(1)

{

p=0;

for(i=0;i

{

buffer[p]=Get_AD(0);

p++;

}

p=0;

for(i=0;i

{

Uart_Printf("%d\n",buffer[p]);

p++;

}

p=0;

for(i=0;i

{

buffer[p]=AD2Y(buffer[p]);

p++;

}

p=0;

for(i=0;i

{

Uart_Print

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1