首页 > 其他分享 >FPGA的ADC采集部分学习整理

FPGA的ADC采集部分学习整理

时间:2024-03-07 14:47:47浏览次数:33  
标签:转换 FPGA SCLK 采集 ADC data reg adc

adc采集部分还是很有用的,模数转换在很多地方都用得到。

使用的EDA模块上的ADC芯片是adc128s102。逐次逼近型ADC(一般单片机用的都是逐次逼近型,速度较快,成本低)。8通道以及12位分辨率。

这边手册上说模拟电源的VA输入范围为2.7V~5.25V


ADC芯片,接入8个模拟输入引脚,输入模拟量。IN0~IN7

引脚DIN是串行数据输入引脚,SCLK上升沿采样输入

引脚DOUT转换结果输出脚,SCLK下降沿输出

SCLK时钟输入,频率范围8~16MHZ,这边采用12.5MHZ,因为是50MHZ的四分之一

CS,片选,下降沿开始测量转换,低电平状态为正在转换

12位数据,是DOUT传出来的,4096分量

所以:

电压值与ADC输出值的的关系为   电压U=adc输出值*3.3V /4096 

这边3.3是引脚的实际电压值。


线性序列机方式,我的理解就是找到其中一个电平时间作为参照物。

这边CS片选,高电平下降到低电平,然后开始工作

SCLK时钟,一帧16个上升沿和下降沿。也是先高到低

一开始三个周期是Track,采样模式

后面13个周期是hold保持模式,转换完成并且完成数据输出

这边以SCLK为线性序列机的时钟参照。以SCLK的时间参照,记录在每个SCLK时间单位到来时,其他寄存器的值去对应。

第三个时钟到第五个时钟下降沿开始选择输入通道。这三个值组成8位通道数 000~111  0~7

看到最后的仿真图,更容易理解,

在lsm_cnt在0~34计数的时候,这边序列机的时间单位是40ns

这边就是记录每个lsm_cnt的值达到时候的寄存器的值。(这边lsm_cnt计数满都是最右边在div_cnt两个时候)

这边主要是din中addr值的确定和dout中的12为adc输出数据的写入data(外部模拟量写入)。 

 代码中对addr和data的值,做了寄存处理,防止端口电平变化造成的一些影响(之前遇到的),锁存操作经常用到。

下面是驱动的框图,这边我准备重新设计一下。

这边我重新设计了一下系统框图。

就是FPGA给驱动时钟信号clk,复位信号reset_n,转换使能信号conv_go(可以用按键触发),通道地址信号addr(8通道用3个拨码开关表示)

外部模拟量通过模拟引脚通过adc芯片转换后adc_dout输出给驱动。每次只有一通道可以采集,这个adc_dout是串行数据输入给驱动

然后驱动输出给adc芯片的有,adc时钟sclk作为线性序列机的参考时钟,输出cs片选信号控制转换开始停止,输出adc_din作为选择通道

最后将模拟量的串行输入信号并行传输给FPGA,以及发送转换停止信号告诉主控(fpga)。

FPGA在收到转换后的并行data数据之后,就可以进一步处理,就是通过之前的数码管显示出来。因为data数据之后12位,所以4数据一组16进制,3个数码管就够用了。

通过按键触发conv_go转换开始标志。data数据就留给数码管显示

ADC的上面的data数据转给disp_data[31:0],因为只有12位,所以高20位全部为0,只用低位3个数码管显示

下面就是数码管的知识了(之前的随笔里面写过)

最后还有一个按键触发的转换开始(是按键消除抖动那边的,也不难)

module adc128s102(
    clk,
    reset_n,
    
    conv_go, //使能单次转换,高脉冲使能一次
    addr,    //通道
    
    conv_done,//单次转换结束,转换结束后产生一个时钟的高脉冲
    data,    //ADC转换结果
    
    adc_sclk,
    adc_cs_n,
    adc_din,
    adc_dout
    );
    
    input   clk;
    input   reset_n;
    
    input   conv_go;
    input   [2:0]   addr;
    
    output  reg conv_done;
    output  reg [11:0] data;
    
    output  reg adc_sclk;
    output  reg adc_cs_n;
    output  reg adc_din;
    input    adc_dout;   //输入类型的端口
    
    parameter   CLOCK_FREQ = 50_000_000;
    parameter   SCLK_FREQ = 12_500_000; //8~16mhz 取12.5Mhz 因为好算
    parameter   MCNT_DIV_CNT = CLOCK_FREQ/(SCLK_FREQ * 2) - 1;//1  40ns
    
    reg [7:0]   div_cnt;
    reg [5:0]   lsm_cnt;//计数到34
    
    reg [2:0] r_addr;
    reg [11:0] data_r;
    
    reg conv_en;
    
    always @(posedge clk or negedge reset_n)
        if(!reset_n)
            conv_en <= 1'd0;
        else if(conv_go)
            conv_en <= 1'd1;  //分频计数器使能
//        else if((lsm_cnt <= 6'd34) && (div_cnt == MCNT_DIV_CNT))
        else if(conv_done)
            conv_en <= 1'd0;
        else
            conv_en <= conv_en;
    
    //确保端口传输时电平的变化造成的传输没完成会影响最后传输
    //先锁存一下
//    always @(posedge clk)
//        if(conv_go)
//            r_addr <= addr;
//        else
//            r_addr <= r_addr;
    always @(posedge clk or negedge reset_n)
        if(!reset_n)
            r_addr <= 3'd0;
        else if(conv_go)
            r_addr <= addr;
        else
            r_addr <= r_addr;
    
    //最小单位计数器
    //40ns
    always @(posedge clk or negedge reset_n)
        if(!reset_n)
            div_cnt <= 0;
        else if(conv_en) begin    //计数使能信号
            if(div_cnt == MCNT_DIV_CNT)
                div_cnt <= 0;
            else
                div_cnt <= div_cnt + 1'd1;
        end
        else
            div_cnt <= 0;
    
    //序列计数器,线性序列击0~34
    always @(posedge clk or negedge reset_n)
        if(!reset_n)
           lsm_cnt <= 6'd0;
        else if(div_cnt == MCNT_DIV_CNT) begin
            if(lsm_cnt == 6'd34)
                lsm_cnt <= 6'd0;
            else
                lsm_cnt <= lsm_cnt + 1'd1;
        end
        else
            lsm_cnt <= lsm_cnt; 
            
     always @(posedge clk or negedge reset_n)
        if(!reset_n)begin
            data_r <= 12'd0;
            adc_sclk <= 1'd1;
            adc_din <= 1'd1;
            adc_cs_n <= 1'd1;
            //adc_dout <= 1'd1;
        end
        else if(div_cnt == MCNT_DIV_CNT)begin
            case(lsm_cnt)
                 0 : begin adc_cs_n <= 1'd1; adc_sclk <= 1'd1; end
                 1 : begin adc_cs_n <= 1'd0; end
                 2 : begin adc_sclk <= 1'd0; end
                 3 : begin adc_sclk <= 1'd1; end
                 4 : begin adc_sclk <= 1'd0; end
                 5 : begin adc_sclk <= 1'd1; end
                 6 : begin adc_sclk <= 1'd0; adc_din <= r_addr[2]; end
                 7 : begin adc_sclk <= 1'd1; end
                 8 : begin adc_sclk <= 1'd0; adc_din <= r_addr[1]; end
                 9 : begin adc_sclk <= 1'd1; end
                 10 : begin adc_sclk <= 1'd0; adc_din <= r_addr[0]; end
                 11 : begin adc_sclk <= 1'd1; data_r[11] <= adc_dout; end
                 12 : begin adc_sclk <= 1'd0; end
                 13 : begin adc_sclk <= 1'd1; data_r[10] <= adc_dout; end
                 14 : begin adc_sclk <= 1'd0; end
                 15 : begin adc_sclk <= 1'd1; data_r[9] <= adc_dout; end
                 16 : begin adc_sclk <= 1'd0; end
                 17 : begin adc_sclk <= 1'd1; data_r[8] <= adc_dout; end
                 18 : begin adc_sclk <= 1'd0; end
                 19 : begin adc_sclk <= 1'd1; data_r[7] <= adc_dout; end
                 20 : begin adc_sclk <= 1'd0; end
                 21 : begin adc_sclk <= 1'd1; data_r[6] <= adc_dout; end
                 22 : begin adc_sclk <= 1'd0; end
                 23 : begin adc_sclk <= 1'd1; data_r[5] <= adc_dout; end
                 24 : begin adc_sclk <= 1'd0; end
                 25 : begin adc_sclk <= 1'd1; data_r[4] <= adc_dout; end
                 26 : begin adc_sclk <= 1'd0; end
                 27 : begin adc_sclk <= 1'd1; data_r[3] <= adc_dout; end
                 28 : begin adc_sclk <= 1'd0; end
                 29 : begin adc_sclk <= 1'd1; data_r[2] <= adc_dout; end
                 30 : begin adc_sclk <= 1'd0; end
                 31 : begin adc_sclk <= 1'd1; data_r[1] <= adc_dout; end
                 32 : begin adc_sclk <= 1'd0; end
                 33 : begin adc_sclk <= 1'd1; data_r[0] <= adc_dout; end
                 34 : begin adc_cs_n <= 1'd1; end
                 default : adc_cs_n <= 1'd1;
             endcase
             end
                      
       always @(posedge clk or negedge reset_n)
            if(!reset_n)begin
                data <= 12'd0;
                conv_done <= 0;
            end
            else if((lsm_cnt == 34) && (div_cnt == MCNT_DIV_CNT))begin
                conv_done <= 1'd1;  //转换完成标志信号
                data <= data_r;
            end
            else begin
                conv_done <= 1'd0;
                data <= data;
            end    
            
endmodule

 

标签:转换,FPGA,SCLK,采集,ADC,data,reg,adc
From: https://www.cnblogs.com/cjl520/p/18057139

相关文章

  • 基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench
    1.算法运行效果图预览    数据导入到matlab显示图像 2.算法运行软件版本vivado2019.2 matlab2022a 3.算法理论概述       离散余弦变换(DiscreteCosineTransform,DCT)是一种广泛应用于图像和信号处理领域的变换技术。在图像处理中,DCT常被用于图像压......
  • 河北稳控科技岩土工程安全监测仪器振弦采集仪的原理与应用
    岩土工程安全监测仪器振弦采集仪的原理与应用岩土工程安全监测仪器振弦采集仪是一种用于测量土地和岩石的动力特性的仪器。其原理是利用振动传播在土壤和岩石中的速度来推断地下结构物的品质,如土质的密度、弹性模量、泊松比等。河北稳控科技振弦采集仪的工作原理基于谐波振动的......
  • m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测
    1.算法仿真效果Vivado2019.2仿真结果如下:  2.算法涉及理论知识概要        级联码是一种通过将两种或多种纠错码结合使用来提高纠错能力的编码方案。在RS+卷积级联编码中,通常首先使用卷积码对原始数据进行编码,以增加冗余并提供一定的纠错能力。然后,将卷积码的输......
  • 基于EP4CE6F17C8的FPGA开发流程(以半加器为例)
    一、电路模块1、芯片FPGA芯片型号为EP4CE6F17C8,属于ALTERA公司CycloneIV系统的产品。此型号为BGA封装,共有256个引脚。芯片实物图如下所示。其主要参数如下表所示。2、LED开发板板载了4个用户LED发光二极管。4个用户LED部分的原理图如下图所示,当FPGA的引脚输出为逻辑0......
  • 河北稳控科技振弦采集仪在岩土工程监测中的作用与优势
    振弦采集仪在岩土工程监测中的作用与优势河北稳控科技振弦采集仪是一种用于岩土工程监测的重要仪器设备。它的作用是通过测量振弦的振动频率和振动幅度,来判断岩土体或结构物的固有频率和振动特性。在岩土工程监测中,振弦采集仪具有以下优势: 1.高精度测量:振弦采集仪可以精确地......
  • 阿里巴巴/1688 api接口 获取商品详情 数据采集
    iDataRiver平台https://www.idatariver.com/zh-cn/提供开箱即用的阿里巴巴1688电商数据采集API,供用户按需调用。接口使用详情请参考阿里巴巴1688接口文档接口列表1.获取商品详情参数类型是否必填默认值示例值描述apikeystring是idr_***从控制台里复制api......
  • 电表 采集配置表达式,导致数据用表达式计算 ,值不对
    采集电表    力创电表EX8+    https://www.sdlckj.com/products_detail/977022133852790784.html表达式配置后,计算结果不对。调整一下表达式顺序,勉强解决问题。   erwa.cn二娃备忘 ......
  • 河北稳控科技振弦采集仪在岩土工程中的数据采集与分析
    河北稳控科技振弦采集仪在岩土工程中的数据采集与分析河北稳控科技振弦采集仪在岩土工程中用于测量土壤和岩石中的振动响应,以评估地基的稳定性和土体的动力特性。它通过悬挂在土壤或岩石表面的振弦感应器,测量由外部激发源引起的振动信号。振弦采集仪的数据采集步骤通常包括以下......
  • 高云FPGA直驱HDMI显示器
    HDMI显示实现的方案同LVDS一样,只是HDMI采用自带的DVITXIP实现并行RGB转TMDS协议,点亮HDMI接口的显示器,需要注意的是HDMI的并行时钟和串行时钟除以5实现的,此部分可以阅读代码和官方的DVITXIP文档,文档有详细介绍。硬件设计上需要注意HDMITX的应用,框起来的部......
  • FPGA数码管知识点整理
    知识点:  数码管控制分为位选和段选,通过位控制哪一个数码管亮,通过段选控制数码管中某一段亮。  我硬件买的上面的是共阳极的,也就是段选位给低电平就能亮。  下面是段选的位控制要显示的数据。比如数字0只要让G位灭掉就行,通过给段选8'h1100_0000 (共阳极),将g和点灭掉就是0......