FPGA控制AD7606进行数据采集
目录
一、AD7606数据手册
1.ADC采样原理
2.AD7606使用手册
二、实例
1.状态转移图
2.Verilog代码
3.仿真结果
总结
一、AD7606数据手册
1.ADC采样原理
在实际的工程中,经前端传感器出来的信号基本都是模拟信号,而后端mcu主控芯片是基于数字信号进行处理的,因此需要用到ADC进行模数转换。ADC包括三个基本功能:抽样、量化和编码。抽样过程是将模拟信号在时间上离散化,使之成为抽样信号;量化是将抽样信号的幅度离散化使之成为数字信号;而编码则是将数字信号转换成数字系统所能接受的形式。如何实现这三个功能就决定了ADC的形式和性能。同时,ADC的分辨率(即采样精度)越高,需要的转换时间就越长,转换速度就越低,故ADC的分辨率和转换速率两者总是相互制约的。
对于一个16位的ADC来说,如果输入的模拟信号幅值在0到3.3V,那么采样后输出的数字信号对应的应该在0到65535,采样精度是1/65536。因此,我们发现,采样位数越高的AD,其采样精度越高,信噪比越大,其越接近原始信号。
采样率即是两个采样点之间的间隔时间,两个采样点之间的间隔时间越短,其采样率越高。根据奈奎斯特采样定律,信号的采样率应该大于其最大频率的2倍。而实际应用中,通常选择信号最大频率的几十倍的采样率,为了更加准确有效的恢复出原始信号。
2.AD7606使用手册
AD7606是16位,8通道同步采集模数数据采集系统。各器件均内置模拟输入钳位保护、二阶抗混叠滤波器、跟踪保持放大器、16位电荷再分配逐次逼近型模数转换器、灵活的数字滤波器、2.5V基准电压源、基准电压缓冲以及高速串行和并行接口。
AD7606采用5V单电源供电,可以处理正负10V和正负5V真双极性输入信号,同时所有通道均能以高达200kSPS的吞吐速率采样。输入钳位保护电路可以耐受最高达正负16.5V的电压。无论以何种采样频率工作, AD7606的模拟输入阻抗均为1MΩ。它采用单电源工作方式,具有片内滤波和高输入阻抗,因此无需驱动运算放大器和外部双极性电源。AD7606抗混叠滤波器的3dB截止频率22kHz;当采样率为200kSPS时,它具有40dB抗混叠抑制特性。灵活的数字滤波器采用引脚驱动,可以改善信噪比(SNR),并降低3dB带宽。
下面给出AD7606引脚配置和功能描述,下图是AD7606的引脚图:
下图给出AD7606的引脚功能描述:
其中,AD7606可以选择三种工作模式,通过配置引脚PAR/SER/BYTE SEL和DB15,如下图所示:
上述三种工作模式都需要首先给AD7606一个转换信号,如果是各通道同步采样,则需要同时给出CONVST_A和CONVST_B信号,然后等待BUSY信号,如果选择等待AD转换后读取,则需要等待BUSY信号拉低后再进行数据读取;如果选择在AD转换期间读取,则不需要等待BUSY信号拉低。下面给出两种不同时刻读取数据的时序图:
在读取数据时,需要首先给AD7606一个读取数据的使能信号CS,接着给出读取数据的时钟信号RD/SCLK,然后AD7606给出相应的数据。
如果工作在并行接口模式,在CS信号拉低后,RD给出8个时钟,分别读取8个通道采集到的数据DATA[15:0],在读取通道1时FRSTDATA信号拉高,时序图如下所示:
如果工作在串行接口模式,在CS信号拉低后,SCLK给出16*4=64个时钟,分别读取DOUTA输出的采集到的通道1~4上的数据和DOUTB上输出的采集到的通道5~8上的数据,在读取通道1时,FRSTDATA信号拉高时序图如下所示:
如果工作在并行字节接口模式,在CS信号拉低后,RD给出2*8=16个时钟,两个时钟为一组,分别读取某一通道采集到的数据的高八位和低八位,数据从DATA[7:0]输出,时序图如下所示:
下表给出上述三种模式对应的时序规格:
二、实例
要求:通过AD7606同步采集八个通道的数据,FPGA按照串行读取的操作,分别读取各通道采集到的数据。
1.状态转移图
共定义九个状态进行转换,通过输入caiji_flag标志信号开始每次的数据采集,当数据采集结束后,输出caiji_over结束信号。
2.Verilog代码
module ad7606_1(input clk,input res,input dout_a, //ad7606通道a输入串行读取数据input dout_b, //ad7606通道b输入串行读取数据input ad_busy, //ad7606输入busy信号input caiji_flag, //外界输入开始数据采集的标志output reg ad_cs, //读ad7606的使能信号output reg ad_rd, //读ad7606的时钟信号output reg ad_convstab //ad7606开始转换信号,低电平有效);parameter IDLE = 9'b0_0000_0001;
parameter AD_CONV = 9'b0_0000_0010;
parameter WAIT_1 = 9'b0_0000_0100;
parameter WAIT_BUSY = 9'b0_0000_1000;
parameter READ_CH15 = 9'b0_0001_0000;
parameter READ_CH26 = 9'b0_0010_0000;
parameter READ_CH37 = 9'b0_0100_0000;
parameter READ_CH48 = 9'b0_1000_0000;
parameter READ_STOP = 9'b1_0000_0000; parameter CONV_TIME = 5; //AD_CONV状态持续时间等价转换信号低电平持续时间
parameter WAIT_TIME = 5; //WAIT_1状态持续时间
parameter FIV_CLK = 4;
parameter CNT_CLK = 16; //每个通道一次发送的时钟个数reg [8:0]stata;
reg [5:0]cnt ; //在数据读取状态表示分频系数
reg [4:0]cnt_bite;reg [15:0]databuffa; //a通道串并转换后存储
reg [15:0]databuffb; //b通道串并转换后存储
//存储八个通道采集到的数据
reg [15:0] data_ch1;
reg [15:0] data_ch2;
reg [15:0] data_ch3;
reg [15:0] data_ch4;
reg [15:0] data_ch5;
reg [15:0] data_ch6;
reg [15:0] data_ch7;
reg [15:0] data_ch8;
reg [2 :0] over;
wire caiji_over;always@(posedge clk or negedge res)if(!res)cnt <= 'd0;else if(stata == AD_CONV)if(cnt == CONV_TIME)cnt <= 'd0;else cnt <= cnt + 1;else if(stata == WAIT_1)if(cnt == WAIT_TIME)cnt <= 'd0;else cnt <= cnt + 1;else if(stata == WAIT_BUSY) //为了在下一个状态,cnt从6开始计数,为了让CS和RD信号前后有延时if(ad_busy == 1'b0)cnt <= 'd6;else cnt <= cnt;else if(stata == READ_CH15 || stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)if(cnt == (2*FIV_CLK-1))cnt <= 'd0;elsecnt <= cnt + 1;always@(posedge clk or negedge res)if(!res)cnt_bite <= 'd0;else if(stata == READ_CH15 )if(cnt_bite == (CNT_CLK) && cnt == (2*FIV_CLK-1))cnt_bite <= 'd0;else if(cnt == (2*FIV_CLK-1))cnt_bite <= cnt_bite + 1;else cnt_bite <= cnt_bite;else if( stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))cnt_bite <= 'd0;else if(cnt == (2*FIV_CLK-1))cnt_bite <= cnt_bite + 1;else cnt_bite <= cnt_bite;else cnt_bite <= 'd0;always@(posedge clk or negedge res)if(!res)stata <= 4'd0;else begincase(stata)IDLE : if(caiji_flag == 1'b1)stata <= AD_CONV;else stata <= IDLE;AD_CONV : if(cnt == CONV_TIME)stata <= WAIT_1;else stata <= AD_CONV;WAIT_1 : if(cnt == WAIT_1)stata <= WAIT_BUSY;else stata <= WAIT_1;WAIT_BUSY : if(ad_busy == 1'b0)stata <= READ_CH15;elsestata <= WAIT_BUSY; READ_CH15 : if(cnt_bite == (CNT_CLK ) && cnt == (2*FIV_CLK-1))stata <= READ_CH26;else stata <= READ_CH15;READ_CH26 : if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))stata <= READ_CH37;else stata <= READ_CH26;READ_CH37 : if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))stata <= READ_CH48;else stata <= READ_CH37;READ_CH48 : if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))stata <= READ_STOP;else stata <= READ_CH48;READ_STOP : stata <= IDLE;default:stata <= IDLE;endcaseend //输出信号
always@(posedge clk or negedge res)if(!res)ad_convstab <= 1'b1; else if(stata == AD_CONV)ad_convstab <= 1'b0;else ad_convstab <= 1'b1;always@(posedge clk or negedge res)if(!res)ad_cs <= 1'b1;else if(stata == WAIT_BUSY && ad_busy == 1'b0)ad_cs <= 1'b0;else if(stata == READ_STOP)ad_cs <= 1'b1;else ad_cs <= ad_cs;
always@(posedge clk or negedge res)if(!res)ad_rd <= 1'b1;else if(stata == READ_CH15 || stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)if(cnt == (FIV_CLK-1))ad_rd <= 1'b0;else if(cnt == 2*FIV_CLK-1)ad_rd <= 1'b1;else ad_rd <= ad_rd;else ad_rd <= 1'b1;//处理输入的串行数据
always@(posedge clk or negedge res)if(!res)begindatabuffa <= 16'd0;databuffb <= 16'd0;end else if(stata == READ_CH15 || stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)beginif(cnt == FIV_CLK && ad_rd == 1'b0)begindatabuffa <= {databuffa[14:0],dout_a};databuffb <= {databuffb[14:0],dout_b};end else begindatabuffa <= databuffa;databuffb <= databuffb; end end else begindatabuffa <= 16'd0;databuffb <= 16'd0; end //将采集到的数据存储到data_ch1-data_ch8中
always@(posedge clk or negedge res)if(!res)begindata_ch1 <= 16'd0;data_ch2 <= 16'd0;data_ch3 <= 16'd0;data_ch4 <= 16'd0;data_ch5 <= 16'd0;data_ch6 <= 16'd0;data_ch7 <= 16'd0;data_ch8 <= 16'd0;end else if(stata == READ_CH15 && cnt_bite == (CNT_CLK) && cnt == (2*FIV_CLK-1))begindata_ch1 <= databuffa;data_ch5 <= databuffb;end else if(stata == READ_CH26 && cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))begindata_ch2 <= databuffa;data_ch6 <= databuffb;endelse if(stata == READ_CH37 && cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))begindata_ch3 <= databuffa;data_ch7 <= databuffb;endelse if(stata == READ_CH48 && cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))begindata_ch4 <= databuffa;data_ch8 <= databuffb;endelse begindata_ch1 <= data_ch1 ;data_ch2 <= data_ch2 ;data_ch3 <= data_ch3 ;data_ch4 <= data_ch4 ;data_ch5 <= data_ch5 ;data_ch6 <= data_ch6 ;data_ch7 <= data_ch7 ;data_ch8 <= data_ch8 ;end //八个通道采集结束后,对over信号打拍处理,输出over_flag
assign caiji_over = over[2];
always@(posedge clk or negedge res)if(!res)over <= 3'd0;else if(stata == READ_STOP)beginover[0] <= 1'b1; over[1] <= over[0];over[2] <= over[1];endelse beginover[0] <= 1'b0; over[1] <= over[0];over[2] <= over[1]; end endmodule
下面给出tb测试文件:
`timescale 1ns/1ns
module tb1();
reg clk;
reg res;
reg data_b;
reg data_a;
reg busy;
reg caiji_flag;
wire ad_cs;
wire ad_rd;
wire ad_convstab;
reg ad_convstab_buffer;
wire convstab_flag;reg [9:0]cnt;
initial beginclk <= 1'b0;res <= 1'b0;busy <= 1'b0;data_a <= 1'b0;data_b <= 1'b0;caiji_flag <= 1'b0;#100 res <= 1'b1;end
always #10 clk <= ~clk;//检测ad_convstb的下降沿
always@(posedge clk)ad_convstab_buffer <= ad_convstab;
assign convstab_flag = (~ad_convstab)&ad_convstab_buffer;always@(posedge clk or negedge res)if(!res)cnt <= 0;else if(convstab_flag)cnt <= cnt + 1;else if(cnt == 7)cnt <= cnt;else cnt <= cnt + 1;always@(posedge clk)beginif(cnt >5 && cnt <8)begincaiji_flag <= 1'b1;busy <= 1'b0;end else if(cnt == 8)begincaiji_flag <= 1'b0;busy <= 1'b0;end else if(cnt>8 && cnt<20)beginbusy <= 1'b1;caiji_flag <= 1'b0;end else if(cnt == 20)beginbusy <= 1'b0;caiji_flag <= 1'b0;end else busy <= busy;
end
always@(posedge ad_rd or posedge ad_cs)if(ad_cs)begindata_a <= 1'b0;data_b <= 1'b0;end else begindata_a <= {$random}%2;data_b <= {$random}%2; end ad7606_1 u_ad7606_1( . clk (clk) ,. res (res) ,. dout_a (data_a) , //ad7606 数据. dout_b (data_b) ,. ad_busy (busy) , //ad7606 busy. caiji_flag (caiji_flag) ,. ad_cs (ad_cs) , //ad7606 AD 片选. ad_rd (ad_rd) , //ad7606 AD 串行读数据时钟. ad_convstab (ad_convstab) //ad7606 AD convert start
);
endmodule
3.仿真结果
仿真结果如下图所示:图1给出了前五个状态的时序图,图2给出了后四个状态(数据采集)的时序图,图3给出了整体的时序仿真图。
图1
图2
图3
总结
总体而言,该芯片是一款性能不错的AD芯片,操作时序图相对比较简单,基本能够满足一般系统的性能要求。当然如果系统对数据采集的要求过高,即要求高信噪比,那么在AD选型的过程中可以考虑18位的AD(AD7690、CBM79AD60)或者是24位AD(AD1258)芯片;这里给大家推荐一下AD7690,18位的AD芯片,单通道数据采集,差分输入,串行读取AD数据,其操作时序十分简单,封装为MSOP-10,占用PCB空间较小。
初次创作,难免文章中存在错误,希望读者能够及时纠正并给予私信,望大家共同进步!
FPGA控制AD7606进行数据采集相关推荐
- 【FPGA】FPGA对AD7606进行串行数据采集
个人笔记.这段时间在用FPGA对AD7606进行数据采集,现在把检测过程和遇到的问题记录一下,方便以后避坑.文章最后有相关资料链接. 1.AD7606概述 AD7606是16位,8通道同步采集模数数据 ...
- omapl138 fpga三核高速数据采集处理核心平台方案
支持32路AD采集,32路DA输出. 支持多路RS485.RS232串口: 支持实时系统,控制延时: 支持DSP和ARM的多核通信,提供丰富的采样demo: 支持图形界面编程,触控! 1.OMAP-L ...
- STM32F407控制AD7606 采用HAL库的TIM和SPI
前言 本文介绍基于STM32F407的AD7606 8通道同步采集控制方式,总体思路:PWM驱动AD7606完成模数转换,AD7606转换完成后其BUSY引脚给出下降沿,STM32捕获外部中断并在中断 ...
- FPGA 控制 FLASH 之 Startup 原语使用相关链接
固件远程更新之STARTUPE2原语(fpga控制flash) 上个格式不方便看,看这个转载的: https://blog.csdn.net/Reborn_Lee/article/details/89 ...
- FPGA控制AD7768采集
1.1 FPGA控制AD7768采集 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4) FPGA控制AD7768采集: 5)结束语. 1.1.2 本节引言 "不 ...
- FPGA控制不其他芯片
1.1 FPGA控制不其他芯片 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA控制不其他芯片: 5)结束语. 1.1.2 本节引言 "不积跬步,无以至 ...
- ZYNQ FPGA控制LED灯不闪烁
1.1 ZYNQ FPGA控制LED灯不闪烁 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)ZYNQ FPGA控制LED灯不闪烁: 5)结束语. 1.1.2 本节引言 ...
- FPGA采集AD7606串行输源码加讲解
FPGA采集AD7606串行输源码加讲解 那是2020年,在我上家公司时,由于刚接触FPGA,所以啥也不会,就被大佬安排去写一个国产FPGA的项目,其中就包含AD7606的采集,很遗憾,当时我没能搞定 ...
- FPGA控制TDC-GPX2时间间隔测量(一)
距离上一次使用FPGA控制TDC芯片测量时间间隔已经过去一年多了,当时采用的TDC芯片是TI的一款芯片TDC7200,最后测量结果所能达到的精度为百皮秒级别,最近使用入手了AMS生产的TDC-GPX2 ...
最新文章
- OpenCV之highgui 模块. 高层GUI和媒体I/O: 为程序界面添加滑动条 OpenCV的视频输入和相似度测量 用OpenCV创建视频
- 软件测试矩阵,什么是过程/数据矩阵(U/C矩阵)?
- dell r740如何做raid_戴尔入门级4K、IPS广色域显示器:S2721QS表现如何?
- xml节点的添加和删除
- Initializer provides no value for this binding element and the binding element has no default value
- 蓝桥杯真题-连号区间数-枚举
- [2020-09-11 CQBZ/HSZX多校联测 T2] 泰拳警告(组合数+数学期望)
- 对mysql的总结与反思_深入了解MySQL,一篇简短的总结
- 项目分布式部署那些事(1):ONS消息队列、基于Redis的Session共享,开源共享
- web 3d 资源库大全
- 虚拟机打开了服务器维护,Vmware WorkStation 打开远程服务器上的虚拟机
- RGMII(Reduced Gigabit Media Independent Interface)
- 如何通过word自动生成论文目录
- 基于Bmob的仿微信即时聊天软件
- Pixelmator Pro 2.1.2 图像处理软件
- 程序员被离职赔偿18万,房贷八千,只够还一年半,领导:回来上班
- 怎样用电池给铁锅作防锈
- C语言利用二叉树的操作实现根据给定的字符串生成二叉树并前序、中序、后序输出二叉树。
- gitlab项目的备份与迁移
- 机器学习第三章笔记——决策树
热门文章
- MySQL创建数据库得语句是什么_创建数据库的语句是什么
- Android 高级开发 JNI NDK 介绍与使用
- 清华毕业程序员国企干了14年,去应聘小公司,看到工资后愣了
- mysql通过股票代码查数据_如何在交易数据中查询各个版本交易量前三的股票?(MySQL分组排名)...
- Notepad++ 安装 HexEditor 插件
- win10使用administrator登录却仍然没权限
- html怎样调节字间距,css怎么调整字间距?
- AndroidStudio:The number of method references in a .dex file cannot exceed 64K错误
- JavaWeb HTTP状态 405 - 方法不允许
- 【备战NOIP】专题复习1-动态规划-背包问题