ADS8345驱动程序设计文档.docx
- 文档编号:27312238
- 上传时间:2023-06-29
- 格式:DOCX
- 页数:33
- 大小:743.46KB
ADS8345驱动程序设计文档.docx
《ADS8345驱动程序设计文档.docx》由会员分享,可在线阅读,更多相关《ADS8345驱动程序设计文档.docx(33页珍藏版)》请在冰豆网上搜索。
ADS8345驱动程序设计文档
ADS8345驱动程序设计文档
隶属项目
高速多路数据采集板
文件状态:
/√/草稿文件
//正式文件
//修订版正式
编写者:
版本:
V0.1
修改审定:
最后修改日期:
2013-4-12
版本历史
版本
作者
参与者
起始日期
备注
V0.1
2013-4-12
2013--
草稿
1引言
1.1编写目的
本文档编写目的是:
方便实验室内部交流、相同工作只做一遍、在不同届学生之间项目的快速交接之目的。
1.2实验环境
1.2.1内核版本:
2.6.32.2(mini2440)2.6.35.7(Tiny210)
1.2.2硬件平台:
mini2440开发板,Tiny210开发板
1.2.3参考资料:
华清远见SPI讲解资料,2010级师兄政越伟论文
1.4术语和缩写词
2关于硬件的说明
2.1ADS8345的简介
ADS8345是一款16位逐次逼近型8通道串行输出的内部采样型模数转换器。
在100khz的转化速率,5v单电源供电的时候最大功耗为8mW。
参考电压可在500mv到1/2电源电源范围内变化。
输入电压范围根据参考电压而相适应。
本设备包括休眠模式,在这个模式下最低功耗可达15uw。
确保正常工作的最低电压是2.7v。
低功耗,高速率,自带多路转换器。
Ads8345是一款典型的逐次逼近型数模转换器。
内部自带采样保持器(SHA)
典型应用电路:
管脚介绍:
管脚
名称
说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CH0
CH1
CH2
CH3
CH4
CH5
CH6
CH7
COM
SHDN
Vref
+Vcc
GND
GND
Dout
BUSY
Din
CS
DCLK
+Vcc
模拟输入端通道0
模拟输入端通道1
模拟输入端通道2
模拟输入端通道3
模拟输入端通道4
模拟输入端通道5
模拟输入端通道6
模拟输入端通道7
公共参考端,这个端口通常接到Vref
待机,到此管脚为低电平,设备进入超低功耗待机模式。
参考电压输入端,输入范围参考电气特性表
电源,2.7-5V。
地
地
串行数据输出
忙碌信号输出
串行数据输入
片选信号
外部时钟输入
电源
工作时需要外部的参考电源,外部时钟。
需要单端电源2.7-5V。
外部参考电源可以是500mV到+Vcc/2。
参考电源的电压直接决定转换器的模拟输入电压范围。
参考电源平均输入电流大小取决于AD的转换速率。
AD的模拟输入是差分的。
通过8通道的多路器获得。
输入电压可以根据COM端的电压设置。
或者使用8路中的4路来组成差分信号。
这些设置可以通过串口来选择。
模拟输入
模拟输入是双极的差分的。
有两种方法来获得AD的模拟输入。
单端型和差分型。
当输入作为单端型的时候,COM端被保持在一个固定的电压。
CHX各个通道的输入电压在这个固定的电压值上下变化,峰峰值为2倍的Vref。
参考电压值决定COM端电压的变化范围。
当输入作为差分输入方式,各通道的输入电压的振幅为CHX端与COM端输入的差值。
每个通道的峰峰值为Vref。
在第一个八个时钟周期内。
可以通过Din端口向AD写入控制字符。
一旦AD获得了足够的控制信息之后就对内部的输入多路器进行设置。
AD就进入到采用模式。
四个或四个以上的时钟周期之后。
收到控制字符后,AD进入到转换模式。
在这个时候,输入采样保持器进入保持模式。
在之后的十六个时钟周期后完成实际的模拟数字转换。
控制字符:
上图中显示出控制字符的每位控制字的写入顺序。
表中详细的给我这些控制字的说明。
第一位“S”为控制字的起始位,必须为逻辑高。
ADS8345会忽略所有的信息。
直到Din端口收到“S”这个开始位。
之后的三个位(A2-A0)可以用来选择模拟输入多路器的八个通道。
2驱动程序的组织结构
2.1Linux的设备模型
SPI接口是Motorola公司首先提出的全双工三线同步串行外围接口,采用主从模式(MasterSlave)架构;一般仅支持单Master,但可以支持多slave模式。
时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前(MSBfirst),低位在后(LSB);SPI接口有两根单向数据线,为全双工通信,目前应用中的数据速率可以达到Mbps级水平。
SPI接口主要应用在EEPROM、FLASH、RTC、ADC、DSP以及数字信号解码器之间。
它在芯片中只占用四根管脚用来控制以及进行数据传输,分别为SCK(时钟信号)、MOSI(主设备输出从设备输入)、MISO(主设备输入从设备输出),CS(片选信号,一般为低电平有效),节约了芯片的管脚数目,同时为PCB在布局上节省了空间。
正是由于这种简单易用的特性,现在越来越多的芯片上都集成了SPI技术。
其总线结构如图4.2所示:
图4.2SPI总线结构
首先,主从设备之间进行的通信,要确保两个设备之间时钟的一致性,要匹配否则就没有办法进行正常的通信了。
对时钟(SCLK)来说,最重要的两个特性就是极性和相位了,只要保证两个设备的极性和相位保持一致,就可以保证两者正常通信。
时钟(SCLK)的空闲时刻,就是当时钟在发送八个比特数据之前和之后的状态,与此对应的就是在时钟发送数据的时候,也就是SPI正常工作的时候。
SPI的极性就是指,当时钟空闲的时候,其电平是高电平还是低电平。
CPOL=0,表示时钟空闲的时候的电平是低电平;CPOL=1表示时钟空闲时候的电平是高电平。
其示时钟极性意图如图4.3:
图4.3时钟极性
从图中可以看出,时钟的波形(CPOL=0)在有输出八个脉冲,而在脉冲输出前和完成后都保持在低电平状态。
此时的状态就是时钟空闲状态或无效状态,因为此时没有脉冲也就不会有数据传输。
同理可以得出CPOL=1的图形,无效状态为高电平。
时钟的相位就是表示当数据有效时刻,是在时钟的第几个条边沿进行采样,是在第一个或者第二个跳变沿进行采样。
CPHA=0表示在时钟的第一个跳变沿进行采样,即读取数据。
CPHA=1表示在时钟的第二个跳变沿进行数据采样。
SPI接口的极性(CPOL)和相位(CPHA)分别可以是0或者是1,对应的组合可以实现SPI通信的四种模式:
Mode0(CPOL=0,CPHA=0)、Mode1(CPOL=0,CPHA=1)、Mode2(CPOL=1,CPHA=0)、Mode3(CPOL=1,CPHA=1)。
其详细对比如表4.1:
表4.1时钟极性和相位组合
时钟空闲
时刻电压
低电平
CPOL=0
高电平
CPOL=1
数据采样时刻,时钟的第几个跳变沿采样
第一个跳变沿
CPHA=0
上升沿采样(开始电压是低电平,而第一个跳变沿只能是从低到高,即上升沿)
下降沿采样
第二个跳变沿
CPHA=1
下降沿采样
上升沿采样(开始电压是高电压,第二个跳变沿肯定是从低电平到高电平)
其中Mode0和Mode3是最常用的模式,本系统采用的SPI接口协议即采用的Mode0,脉冲传输前和完成后都保持在低电平状态,所以CPOL=0即低电平是空闲时的电平。
在第一个跳变沿(上升沿)进行数据采样,第二个跳变沿(下降沿)输出数据,对应着CPHA=0。
其对应的时序图如4.4:
图4.4SPI时序图(MODE0)
2.2Tiny210SPI移植
Linux内核2.6.35.7的内核源码中已经给出了三星s5pv210的SPI驱动,但是Tiny210核心板并没有启用这个驱动,因此需要在开发板中配置这个驱动,使得Tiny210支持SPI接口。
通过对Linux内核相关的学习,得到在BSP包中添加添加SPI接口支持的方法:
1)进入本开发板中的BSP相关的目录下,在Tiny210核心板中即是:
/用户目录/Linux-2.6.35.7/arch/arm/mach-s5pv210,打开Tiny210的板级支持包Mach-mini210.c,加入相关头文件的支持,因为s5pv210的SPI寄存器相关定义和s3c64xx相同,故还是使用s3c64xx中SPI相关的寄存器,加入的头文件如下:
#include
#include
2)在平台相关设备中添加从设备相关结构体的定义,因为核心板有两个SPI控制器,需要填充设备结构体数组structspi_board_infos3c_spi_devs[],在本BSP中的代码如下:
staticstructspi_board_infos3c_spi_devs[]__initdata={
[0]={
.modalias="spidev",
.mode=SPI_MODE_0,
.max_speed_hz=10000000,
.bus_num=0,
.irq=IRQ_SPI0,
.chip_select=0,
},
[1]={
.modalias="ads8345",
.mode=SPI_MODE_0,
.max_speed_hz=1000000,
.bus_num=1,
.irq=IRQ_SPI1,
.chip_select=0,
},
};
本系统运用的是SPI1控制器,设备名字为ads8345,数据采集模式应用为Mode0即是CPOL=0,CPHA=0,采集速率为1MHz,SPI总线为一号总线,片选为低电平有效。
3)在structplatform_device*mini210_devices[]__initdata数组平台中添加SPI控制器设备相关代码,用以在开发板初始化代码中注册进开发板,所添加的代码如下:
&s5pv210_device_spi0,
&s5pv210_device_spi1,
设备结构体初始化代码,也就是SPI控制器设备结构体,包括设备名字,所用的资源等,s5pv210_device_spi0对应SPI第一个控制器,s5pv210_device_spi1对应第2个SPI控制器:
structplatform_devices5pv210_device_spi0={
.name="s3c64xx-spi",
.id=0,
.num_resources=ARRAY_SIZE(s5pv210_spi0_resource),
.resource=s5pv210_spi0_resource,
.dev={
.dma_mask=&spi_dmamask,
.coherent_dma_mask=DMA_BIT_MASK(32),
.platform_data=&s5pv210_spi0_pdata,
},
};
structplatform_devices5pv210_device_spi1={
.name="s3c64xx-spi",
.id=1,
.num_resources=ARRAY_SIZE(s5pv210_spi1_resource),
.resource=s5pv210_spi1_resource,
.dev={
.dma_mask=&spi_dmamask,
.coherent_dma_mask=DMA_BIT_MASK(32),
.platform_data=&s5pv210_spi1_pdata,
},
};
4)在开发板的初始化代码中把上面步骤添加的相关代码,通过调用注册设备函数即在staticvoid__initmini210_machine_init(void)中通过调用spi_register_board_info(s3c_spi_devs,ARRAY_SIZE(s3c_spi_devs))函数进行注册。
2.3mini2440SPI驱动移植
1,在LinuxSourceCode中修改arch/arm/mach-s3c2440/mach-mini2440.c文件,加入头文件:
1.#include
2.#include <../mach-s3c2410/include/mach/spi.h>
然后加入如下代码:
1.static struct spi_board_info s3c2410_spi0_board[] =
2.{
3. [0] = {
4. .modalias = "spidev",
5. .bus_num = 0,
6. .chip_select = 0,
7. .irq = IRQ_EINT9,
8. .max_speed_hz = 500 * 1000,
9. }
10.};
11.
12.static struct s3c2410_spi_info s3c2410_spi0_platdata = {
13. .pin_cs = S3C2410_GPG
(2),
14. .num_cs = 1,
15. .bus_num = 0,
16. .gpio_setup = s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
17.};
18.
19.static struct spi_board_info s3c2410_spi1_board[] =
20.{
21. [0] = {
22. .modalias = "spidev",
23. .bus_num = 1,
24. .chip_select = 0,
25. .irq = IRQ_EINT2,
26. .max_speed_hz = 500 * 1000,
27. }
28.};
29.
30.
31.static struct s3c2410_spi_info s3c2410_spi1_platdata = {
32. .pin_cs = S3C2410_GPG(3),
33. .num_cs = 1,
34. .bus_num = 1,
35. .gpio_setup = s3c24xx_spi_gpiocfg_bus1_gpg5_6_7,
36.};
这里需要了解驱动架构,其中移植过程中容易出问题的地方时S3C2410_GPG
(2)和S3C2410_GPG(3)两处地方,网上一般给的源代码是S3C2410_GPG2,这在2.6.29中可行,但是在2.6.32源代码中没有定义S3C2410_GPG2宏定义,要使用S3C2410_GPG
(2)宏定义。
//注册SPI平台设备到虚拟平台总线上....
在mini2440_devices[]平台数组中添加如下代码:
1.&s3c_device_spi0,
2.&s3c_device_spi1,
最后在mini2440_machine_init函数中加入如下代码:
1.s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata;
2.spi_register_board_info(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board));
3.s3c_device_spi1.dev.platform_data= &s3c2410_spi1_platdata;
4.spi_register_board_info(s3c2410_spi1_board, ARRAY_SIZE(s3c2410_spi1_board));
最后需要修改arch/arm/plat-s3c24xx/KConfig文件
找到如下代码段:
1.config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
2. bool
3. help
4. SPI GPIO configuration code for BUS0 when connected to
5. GPE11, GPE12 and GPE13.
6.
7.config S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7
8. bool
9. help
10. SPI GPIO configuration code for BUS 1 when connected to
11. GPG5, GPG6 and GPG7.
修改为
1.config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
2. bool "S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13"
3. help
4. SPI GPIO configuration code for BUS0 when connected to
5. GPE11, GPE12 and GPE13.
6.
7.config S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7
8. bool "S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7"
9. help
10. SPI GPIO configuration code for BUS 1 when connected to
11. GPG5, GPG6 and GPG7.
最后我们配置编译文件:
1.make menuconfig
图1
图2
图3
图4
图5
最后编译内核
make zImage
至此,SPI驱动移植结束,
2.4SPI移植驱动验证
将编译好的内核导入开发板,并且编译LinuxSource自带的测试程序,在Documentation/spi下,修改spidev_test.c文件,将devicename改为/dev/spidev1.0
交叉编译:
arm-linux-gcc-I~/linux-2.6.32.2/include/spidev_test.c
将编译好的文件下载到开发板上,并且将开发板的SPIMOI和MIO短接,也就是让SPI自己发送自己接收,执行文件,我们看到如下结果:
FFFFFFFFFFFF
400000000095
FFFFFFFFFFFF
FFFFFFFFFFFF
FFFFFFFFFFFF
DEADBEEFBAAD
F00D
到此移植完毕,但要注意,mini2440上的SPI1被K3K4
3ADS8345驱动实现
3.1Linux设备模型
随着计算机的外设越来越丰富,设备管理已经成为现代操作系统的一项重要的任务,对于Linux来说也是同样的情况。
每次Linux内核新版本的发布,都会伴随着一批设备驱动进入内核。
在Linux内核里,驱动程序的代码量占了相当大的比重。
Linux2.6内核最初为了应付电源管理的需求,提出了一个设备模型来管理所有的设备。
在物理上,外设之间是有一种层次关系,为了对计算机设备进行统一的表示和操作,包括设备本身和设备与主机之间的链接关系,人们通过分析PCI和USB这两个总线,它们能够代表当前系统中的大多数设备总线,有着完善的热插拔和电源管理机制,从而得出设备模型的结构。
如在一个典型的计算机系统中,CPU能够直接控制的是PCI总线设备,而USB总线设备是以一个PCI设备的形式接入到PCI总线上的,外部的USB设备再入USB总线设备上;当计算机执行挂起操作时,Linux内核应该以“外部USB设备->USB总线设备->PCI总线设备”的顺序通知每一个设备的执行电源挂起;执行恢复时则以相反的顺序通知每一个设备。
如果不按这样的顺序则将有设备因为没有得到正确的通知,而没有执行电源相关的操作,从而使设备不能正常的工作。
因为有这样的需要,必须能够建立一个树状的结构可以把所有的外设组织起来。
这样就提出了建立Linux设备模型的概念。
当然,既然设备模型已经建立起来,已经有了一个可以组织所有设备和驱动的树状结构,我们就可以通过这棵树去遍历所有的设备,建立设备和驱动程序之间的联系,根据设备类型的不同还可以对设备进行分门别类,这样用户就可以通过不同的视角更清晰的去学习Linux的内核,认识Linux的外部设备。
Linux设备模型把很多设备共有的一些操作属性进行抽象,从而大大的减少了重复代码的编写过程,让开发者能够更加安全快速的开发驱动程序。
上文提到过Linux设备的外设之间有一种层次关系,在Linux内核的设计中频繁地用到了这种思想。
在设备驱动的设计中往往为相似的设备构建一个框架,在框架的核心层实现了这类设备的通用功能。
如果具体的设备驱动函数不想应用核心层提供的函数,还可以重新实现该函数。
图4.7反应了设备驱动核心层与具体设备驱动的关系。
这种层次化的思想在Linux的SPI、TTY、USB等子系统中得到了普遍的应用。
图4.7驱动分层结构
在Linux驱动框架的构建过程中,除了有分层设计的思想外,为了实现代码的重复利用,还充分利用了主机控制器和外设驱动分离的思想。
如果不这样做,那么当同一个外设用在不同种类的CPU上,都需要不同的驱动程序,这将是不可接受的。
所以最佳的办法就是外设驱动不关心主机控制器,而主机控制器也不关心外设驱动,他们之间的通信都是通过中间层来完成。
而这个中间层就是核心层,通过调用核心层的API函数来完成两者之间的信息传递,外设和主机控制器之间可以进行任意的组合,实现代码的最大重用。
具体的分离思想可以用图4.8表示:
图4.8驱动分离结构
Linux2.6的设备模型,是由总线、设备和设备驱动这三个部分构成。
总线的作用就是将设备和设备驱动进行匹配和绑定,在系统每注册一
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ADS8345 驱动程序 设计 文档