AD转换学习-模拟spi时序 设备驱动学习记录: http://bbs./blog_index.jspa?blog_id=337002&entry_month=&viewall=true&curr_page=1&sort=0 AD的分类: 时间/数字、电压/数字、机械变量/数字 在嵌入式系统中用的最多的是电压/数字转换器 电压/数字转换器可以分为多种类型: 转换方式:直接转换和间接转换 输出方式:串行、并行、串并行 转换原理:计数式、比较式 转换速度:低速、中速、高速 转换精度:3位、4位、8位、10位、12位、14位、16位等 计数式AD 这里以8位计数式AD为例 计数式AD的转换过程: (1),CLR有效(高电平变成低电平),使计数器输出数字信号为00000000,这个00000000的输出送到8位D/A转换器,8位D/A转换器的输出也是0V (2),当CLR恢复为高电平时,计数器准备计数,此时,在计数器输入端上待转换的模拟输入电压为Vi大于Vo,比较器输出电压c位1,这样计数器开始计数 (3),计数器的输入不断增加,D/A转换器输出的模拟电压(Vo)也在不断的增加,当Vo小于Vi时,计数器不断的计数 (4),当Vo上升到某值时,出现Vo>Vi的情况,此时,比较器的输出电压为低电平,使计数器控制信号c=0,计数器停止计数,此时,数字量D0~D7就是模拟电压等效。计数器控制信号由高变为低的副跳变也是A/D转换的结束信号,表示完成一次A/D转换。 优缺点:结构简单,但是转换速度慢。 逐次逼近式A/D转换 逐次逼近式A/D转换的原理 A/D转换开始前,先将SAR寄存器清0,然后进行转换,时钟信号首先将寄存器的最高位置1,使输出为100….000,这个数字将被DA转换器转换成模拟电压Vo送到比较器与Vi进行比较 当Vo大于Vi的时候,这个位的2进制码将会被改为0,如果Vo小于Vi,那么之前位的1将被保留,一直到最低位为止。比较器的值就是所要求的数值输出。 接下来就以ADS7844位例,粗略的分析下linux下编写AD转换驱动 ADS7844的具体的工作原理网上很多,这里就不做介绍了。 ADS7844与s 驱动程序(基于Linux2.6内核)的整体框架: #include<linux/init.h> //模块加载和卸载相关 #include<linux/madule.h> //MODULE_LICENSE() #include<linux/kemel.h> //printk()函数 #include<asm/arch/regs_gpio.h> //$ #include<asm/hardware.h> //s //ADS7844字符设备结构体定义 struct ads7844_dev { struct cdev cdev; unsigned int channel;//通道号 unsigned int adc[8];//8路采集值 } ADS7844设备注册和卸载 int ads7844_init(void) { int result,i; dev_t devno="MKDEV"(ads7844_major,0); if(ads7844_major) result=register_chrdev_region(devno,1,DEVICE_NAME); //指定设备号 else { result=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);//动态生成设备号 ads7844_major=MAJOR(devno); } if(result<0)return result; ads7844_setup_cdev(ads7844_devp,0);//初始化字符设备 . . . } void ads7844_exit(void) { cdev_del(&ads7844_devp->cdev);//移除字符设备 . . . unregister_chrdev_region(MKDEV(ads7844_major,0),1); //释放设备号 } ADS7844设备具体操作设计与实现 在设备注册过程中,构建了ADS7844_fops结构指针。在file_operations结构中定义了一组函数指针。 static const struct file_operations ads7844_fops= { .owner=THIS_MODULE, .open=ads7844_open, .read=ads7844_read, .write=ads7844-_write, .release=ads7844_release, }; 系统就是通过这一组函数指针来实现ADS7844设备的操作的。具体说来,主要有2个方面的工作: 一是对ADS7844进行工作方式的设置和通道的选择; 二是从设备中获取采样数据的信息。它们分别对应ADS7844_read ADS7844_write这2个函数。了解整个驱动设计的框架后,读写函数的实现就比较简单 读操作中数据移出的过程 . . . for(i=0;i<16;i++) { ads7844_result<<=1;//将刚读出的数据移到高位 s3c2410_gpio_setpin(ads7844_table[0],1);//设置时钟为高 udelay(100); s3c2410_gpio_setpin(ads7844_table[0],0);//设置时钟为低 if(s3c2410_gpio_getpin(ads7844_table[2]))//下降沿读出一位数据 ads7844_resuh |=1; udelay(100); } ads7844_result>>=4;//移出低位多余的4个” |
|