FPGA使用XADC测量外部模拟输入电压

这篇具有很好参考价值的文章主要介绍了FPGA使用XADC测量外部模拟输入电压。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、XADC简介

1.1、特性

Xilinx系列的FPGA中都包含了一个内置的XADC,我们可以通过这个XADC进行一些精度不高的外部模拟信号采样以及FPGA片内传感器信号采集。XADC的分辨率为12位,采样率为1MSPS。

1.2、结构框图

  • 两片XADC,ADC A可用于片内传感器采集(温度、参考电源电压),也可用于外部模拟信号采集。ADC B只能用于外部模拟信号采集。
  • 1个专用模拟输入通道和16个复用模拟输入通道
  • 基准源可选:内部基准源和外部基准源
  • 对外接口DRP可通过JTAG或者FPGA内部逻辑进行控制
xadc使用,fpga开发,硬件工程
图1.1 XADC内部结构框图

1.3、XADC接口介绍

  • 初始化接口:
xadc使用,fpga开发,硬件工程
图1.2 XADC初始化接口图
信号名 方向 功能描述
di_in[15:0] input DRP的输入数据总线。
daddr_in[6:0] input DRP的地址总线。
den_in input DPR的使能信号
dwe_in input DRP的写使能信号
drdy_out output DRP的数据准备好信号
do_out[15:0] output DRP的输出数据总线
dclk_in input DRP的输入时钟
reset_in input XADC的复位信号,高电平有效
vp_in/ vn_in input 专用模拟输入通道,可设计为差分模拟信号输入,当设计使用XADC功能但不用VP/VN时,应该将这两个引脚接地
VAUXP[15:0]/VAUXN[15:0] input 16个复用的模拟输入通道,可设计为差分模拟信号输入
ot_out output 过温报警输出信号
channel_out[4:0] input 通道选择输出信号。当前ADC转换的输入MUX通道选择,由该接口输出提供给用户查看。
eoc_out output ADC转换完成信号。当测量值被写入状态寄存器时,该信号在ADC完成转换之后拉高
eos_out output 时序结束信号。自动通道序列中,当最后一个通道的数据被写入状态寄存器时,该信号转为高电平。
busy_out output ADC忙信号。该信号在ADC转换时为一直为高电平。

寄存器接口:
XADC一共有128个寄存器,前64个(00H ~ 3FH)为只读寄存器,后64个(40H~7FH)为可读写的控制寄存器。一般我们用前32个只读寄存器比较多。

xadc使用,fpga开发,硬件工程
1.3 XADC寄存器接口图

ADC通道选择寄存器:
可以看到ADC模拟通道选择的值与对应通道存放数据的状态寄存器的地址相同。
xadc使用,fpga开发,硬件工程

二、硬件电路

2.1、基准电源

XADC的所需要的基本外围电路如图所示。XADC的基准源可使用外步基准源来实现,基准源的电压为1.25V;也可以选择使用内部基准源,外围电路直接将VREFP和VREFN接地即可。
xadc使用,fpga开发,硬件工程

图2.1 基准电源外围电路

2.2、模拟输入通道

XADC模拟信号输入方式有单极性和双极性两种。XADC默认的方式为单极性输入,fpga片上所有传感器的工作模式为单极性输入。

  • 单极性输入: 当使用单极性输入时,输入电压范围为0V ~ 1V,对应ADC编码范围为000h~FFFh,量化分辨率为1V / 212=244uV。
xadc使用,fpga开发,硬件工程
图2.2 单极性输入电压量化图

在单极性输入模式,Vp必须为正,Vn连接到模拟地或者共模信号。Vn连接到共模信号时,该信号电压范围应该为0V0.5V(即Vp与Vn的共模电压范围),由于Vp与Vn的差模电压范围为0V1V,所以在单极性输入模式下,Vp的输入电压最高可达1.5V。

xadc使用,fpga开发,硬件工程
图2.3 单极性输入电压范围图
  • 双极性输入: 当使用双极性输入时,差分输入电压范围为-0.5V ~ +0.5V,XADC编码采用补码格式,对应编码范围为800h ~ FFFh、000h ~ 7FFh。量化分辨率为1V/212=244uV。
xadc使用,fpga开发,硬件工程
图2.4 双极性输入电压量化图
在双极性输入模式,Vp-Vn差分模拟输入电压的范围±0.5V,Vn的共模电压应该不超过0.5V。 xadc使用,fpga开发,硬件工程
图2.5 双极性输入电压范围图

2.3、外部模拟输入电路

模拟通道输入为高输入,数据手册上推荐电路由分压电路和滤波电路组成,通过分压和滤波之后输入到XADC的模拟信号电压值应该不超过1V。

xadc使用,fpga开发,硬件工程
图2.6 外部模拟输入电路图

图2.6中 R1与R2为分压电阻,R5用于与R1与R2的并联电阻匹配。R3、R4与C1构成抗混叠滤波器,建立时间计算参考手册ug480。

xadc使用,fpga开发,硬件工程

三、时序图

3.1、连续采样模式的时序图

主要有电压采集和电压转换两个阶段。

xadc使用,fpga开发,硬件工程
图3.1 连续采样模式的时序图

DRP时序图

主要用于XADC寄存器的数据读写。

  • 当DEN为高电平时,信号DADDR[6:0]和信号DWE在DCLK的上升沿才会捕捉到,逻辑设计中通常将DEN仅维持一个DCLK时钟的高电平。
  • 当捕捉DWE为低电平时,表示读操作;捕捉DWE为高电平时,表示写操作。
  • 读操作时,DRDY拉高 表示DRP寄存器的数据已经放在总线DO[15:0]上了,用户可以直接读取;写操作时,DRDY拉高表示写的数据已经成功写入DRP寄存器里。
  • 在DRDY拉低之前,一个新的读写操作是不能进行的。
xadc使用,fpga开发,硬件工程
图3.2 DRP时序图

四、XADC的使用教程

4.1、目的

在ZYQN的pl端使用XADC,完成共6路模拟输入信号的电压采样。其中模拟输入通道包括1个Vp/Vn模拟输入通道和5个复用模拟输入通道VAUXP/VAUXN。

4.2、IP核设置

  • Basic界面
  1. 选择DRP接口,读写时序比较简单。
  2. continuous mode 意味着按照设定 ADC 采样率进行采样,event mode 意味着自行控制 ADC 采样率,但是不可超过设定的最大 ADC 采样率;通道选择为 channel sequencer,即多通道采样时按照指定的通道顺序进行扫描采样,通道号定义参考上文通道选择。
  3. 通道序列
  4. 时钟设置
xadc使用,fpga开发,硬件工程
  • ADC Setup界面
    1.序列器模式选择 continuous 模式,会一直循环采样,通道平均次数可按实际情况来,实际采样率=ADC 设定采样率/平均次数。
    2.采样数据平均次数。
xadc使用,fpga开发,硬件工程
  • Alarms界面
    若不是用检测警告功能,该界面可以全部取消勾选。

    xadc使用,fpga开发,硬件工程
  • Channel Sequencer界面
    选择需要初始化的通道即可。这里使用的模拟通道为Vp/Vn、vauxp0/vauxn0、vauxp2/vauxn2、vauxp3/vauxn3、vauxp10/vauxn10、vauxp11/vauxn11。

    xadc使用,fpga开发,硬件工程
  • Summary界面

xadc使用,fpga开发,硬件工程

4.3、逻辑设计

  • top.v ------顶层文件
`timescale 1ns / 1ps
///
// Create Date: 2023/07/18 16:36:43

module top(
    //时钟
    input pl_clk,   
    //模拟输入
    input vp_in,
    input vn_in,
    input vauxp0,
    input vauxn0,
    input vauxp2,
    input vauxn2,
    input vauxp3,
    input vauxn3,
    input vauxp10,
    input vauxn10,
    input vauxp11,
    input vauxn11


    );
    
wire den_in;
wire dwe_in;
wire drdy_out;              //数据有效输出
wire [15:0] di_in, do_out;  //数据输入 数据输出
wire [6:0] daddr_in;        //寄存器地址
wire [4:0] channel_out;     // 通道选择输出
wire eoc_out;               // 转换完成信号
wire eos_out;               // 时序结束信号
wire alarm_out;
wire busy_out;
wire rst_n;
//模拟通道读取的ADC值
wire [11:0] vpvnData;
wire [11:0] vaux0Data, vaux2Data,vaux3Data,vaux10Data,vaux11Data;

//XADC IP例化
xadc_wiz_0 inst_xadc_wiz_0 (
    .dclk_in(pl_clk),           // input wire dclk_in
    .di_in(di_in),              // input wire [15 : 0] di_in
    .daddr_in(daddr_in),        // input wire [6 : 0] daddr_in
    .den_in(den_in),            // input wire den_in
    .dwe_in(0),                 // input wire dwe_in     仅用到读操作,故一直设置为零
    .drdy_out(drdy_out),        // output wire drdy_out
    .do_out(do_out),            // output wire [15 : 0] do_out
    .reset_in(0),               // input wire reset_in  不用复位功能
    .vp_in(vp_in),              // input wire vp_in
    .vn_in(vn_in),              // input wire vn_in
    .vauxp0(vauxp0),            // input wire vauxp0
    .vauxn0(vauxn0),            // input wire vauxn0
    .vauxp2(vauxp2),            // input wire vauxp2
    .vauxn2(vauxn2),            // input wire vauxn2
    .vauxp3(vauxp3),            // input wire vauxp3
    .vauxn3(vauxn3),            // input wire vauxn3
    .vauxp10(vauxp10),          // input wire vauxp10
    .vauxn10(vauxn10),          // input wire vauxn10
    .vauxp11(vauxp11),          // input wire vauxp11
    .vauxn11(vauxn11),          // input wire vauxn11
    .channel_out(channel_out),  // output wire [4 : 0] channel_out
    .eoc_out(eoc_out),          // output wire eoc_out
    .alarm_out(alarm_out),      // output wire alarm_out
    .eos_out(eos_out),          // output wire eos_out
    .busy_out(busy_out)         // output wire busy_out
);    

//对DRP接口操作,完成XADC寄存器数据的读取  
xadc_capture inst_xadc_capture(
    .dclk(pl_clk),
    .rst_n(1),                  //不用复位功能
    .di_in(di_in),
    .daddr_in(daddr_in),
    .den_in(den_in),
    .dwe_in(dwe_in),
    .drdy_out(drdy_out),
    .eoc_out(eoc_out),
    .do_out(do_out),
    .channel_out(channel_out),
    .xadc_vpvn_data(vpvnData),
    .xadc_vaux0_data(vaux0Data),
    .xadc_vaux2_data(vaux2Data),
    .xadc_vaux3_data(vaux3Data),
    .xadc_vaux10_data(vaux10Data),
    .xadc_vaux11_data(vaux11Data)
    
);

endmodule

  • xadc_capture.v ------XADC的寄存器数据读取操作
`timescale 1ns / 1ps
///
// Create Date: 2023/07/18 16:36:13

module xadc_capture(
    input           dclk, 
    input           rst_n, 
    //XADC IP 接口 
    output reg[15:0]di_in,          // 写入xadc总线上的数据
    output reg[6:0] daddr_in,       // 读取xadc寄存器地址
    output reg      den_in,         // 控制使能
    output reg      dwe_in,         // 写使能
    input           drdy_out,       // 数据有效输出
    input           eoc_out,
    input   [15:0]  do_out,         // 读取xadc总线上的数据
    input   [4:0]   channel_out,    // 通道选择输出
    //内部逻辑接口 
    output reg[11:0] xadc_vpvn_data,    //XADC 读出的 Vp/Vn 采样数据 
    output reg[11:0] xadc_vaux0_data,   //XADC 读出的 vaux0 采样数据    
    output reg[11:0] xadc_vaux2_data,   //XADC 读出的 vaux2 采样数据
    output reg[11:0] xadc_vaux3_data,   //XADC 读出的 vaux3 采样数据
    output reg[11:0] xadc_vaux10_data,  //XADC 读出的 vaux10 采样数据
    output reg[11:0] xadc_vaux11_data   //XADC 读出的 vaux11 采样数据
    
    );
    
 

///
//产生 XADC 读时序  
always @(posedge dclk or negedge rst_n) begin
    if(!rst_n) begin 
        den_in <= 1'b0; 
        dwe_in <= 1'b0;        
        daddr_in <= 7'd0;
        di_in <= 7'd0;
    end
    else if(eoc_out) begin
        daddr_in <= {2'b00, channel_out}; //XADC 数据读取寄存器地址 直接连接到通道选择输出channel_out[4:0]
        den_in <= 1'b1;                   //产生den_in一个时钟周期的高电平     
    end
    else begin
        daddr_in <= 7'd0;
        den_in <= 1'b0;
    end

end  
 
///  
//读 XADC 输出数据   
always @(posedge dclk or negedge rst_n) begin
    if(!rst_n) begin 
        xadc_vpvn_data  <= 0;
        xadc_vaux0_data <= 0;       
        xadc_vaux2_data <= 0;
        xadc_vaux3_data <= 0;
        xadc_vaux10_data <= 0;
        xadc_vaux11_data <= 0;
    end   
    else if(drdy_out) begin
        case(channel_out[4:0])
            5'h03: begin
                xadc_vpvn_data <= do_out[15:4];               
            end
            5'h10: begin
                xadc_vaux0_data <= do_out[15:4];               
            end
            5'h12: begin
                xadc_vaux2_data <= do_out[15:4];               
            end
            5'h13: begin
                xadc_vaux3_data <= do_out[15:4];               
            end
            5'h1a: begin
                xadc_vaux10_data <= do_out[15:4];               
            end
            5'h1b: begin
                xadc_vaux11_data <= do_out[15:4];               
            end
            default: begin
         
            end
        endcase
    end
    
end
  
endmodule

  • xadc.xdc ------约束文件
#时钟物理约束
set_property PACKAGE_PIN AD20 [get_ports pl_clk]
set_property IOSTANDARD LVCMOS33 [get_ports pl_clk]

#时钟周期约束
create_clock -name clk -period 10 [get_ports pl_clk ]

提示: 当使用复用模拟通道时(VAUXP[15:0]和VAUXN[15:0]),在fpga逻辑设计中不需要对相应的引脚进行约束,只用在顶层模块中调用IP例化模块,并连接到顶层的信号输入即可,这样该引脚就可以作为模拟输入通道。在约束文件中仅对时钟进行了约束。

xadc使用,fpga开发,硬件工程
  • 为方便大家下载官方参考文档,已将这两个文档上传 供大家免费下载。至此,希望能够帮助路过的你。若文章对大家有帮助,也希望能够赏个赞,你们的点赞是我写文章的动力(比心)。欢迎交流学习~

参考文档

  • ug480_7Series_XADC;

  • XADC Wizard v3.3;

  • 百度网盘连接:
    https://pan.baidu.com/s/1GgqPdtemoABWpRRT-owCpQ
    提取码:216p文章来源地址https://www.toymoban.com/news/detail-668183.html

到了这里,关于FPGA使用XADC测量外部模拟输入电压的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 基于HAL库的STM32的单定时器的多路输入捕获测量脉冲频率(外部时钟实现)

    基于HAL库的STM32的单定时器的多路输入捕获测量脉冲频率(外部时钟实现)

    目录 写在前面 一般的做法(定时器单通道输入捕获) 以外部时钟的方式(高低频都适用) 测试效果 STM32的定时器本身有输入捕获的功能。可选择双端捕获,上升沿捕获或者是下降沿捕获。对应捕获频率来说,连续捕获上升沿或下降沿的时间间隔就是其脉冲的周期. 定时器设置频率

    2024年02月08日
    浏览(9)
  • 如何使用ADC测量我们设备的锂电池电压

    如何使用ADC测量我们设备的锂电池电压

    电路设计: 首先当我们想知道设备还有多少电的时候,我们就需要有一个电压监测电路  通常我们会想到通过两个电阻分压的方式来获取电压,通过两个电阻分压,连接到单片机的ADC引脚。ADC测到的电压,就是锂电池电压的一半 因为锂电池的电压范围大概在2.7V到4.2V之间,所

    2024年02月01日
    浏览(9)
  • 【LabVIEW FPGA入门】模拟输入和模拟输出

    【LabVIEW FPGA入门】模拟输入和模拟输出

             1.打开项目,在FPGA终端下面新建一个VI         2.本示例以模拟输入卡和模拟输出卡同时举例。         3.新建一个VI编写程序,同时将卡1的输出连接到卡2的输入使用物理连线。         4.编译并运行程序,观察是否能从通道中采集和输出信号。         5.同时

    2024年01月17日
    浏览(11)
  • 交流电压220V如何用单片机测量电压?

    交流电压220V如何用单片机测量电压?

    要用单片机测量交流220V的电压,需要三个步骤: 将高压的220V电压变压成低压交流信号; 一般通过电压互感器将220V的电压转换为低压交流信号, 电压互感器的电路如下:   电压互感器的规格为初级电流和次极电流的比值为1:1,上图的电路中,初级的额定电流峰值为1.55mA,选

    2024年02月08日
    浏览(11)
  • 使用定时器外设的输入捕捉功能及测量脉冲宽度

    使用定时器外设的输入捕捉功能及测量脉冲宽度

    在汽车电子系统中,经常需要通过编码器反馈机械结构的位置信息,微控制器芯片解析编码器的信号时,会使用到定时器的 输入捕获 功能测量编码器输出的脉冲宽度。绝大多数带有多通道输入输出的定时器,都设计了输入捕获功能。基本的硬件输入捕获功能只是对外部的触

    2024年01月25日
    浏览(6)
  • 温湿度测量模块DHT11使用方法(FPGA)

    温湿度测量模块DHT11使用方法(FPGA)

            DHT11采用了简化的单总线通讯。当DHT11在上电一秒后收到来自控制器(FPGA)发出的起始信号后,会向控制器发送一个响应信号,随后便会发送40位的数据。         起始信号:一个时长大于18ms小于30ms的低电平         响应信号:         数据格式:         工

    2024年02月02日
    浏览(8)
  • STM32CubeMX | 使用STM32定时器的PWM输入模式测量脉冲宽度和周期

    STM32CubeMX | 使用STM32定时器的PWM输入模式测量脉冲宽度和周期

    本篇博客以STM32F103C8为例,其他系列MCU可能稍有不同,但原理一样。 相关链接博文: STM32CubeMX | STM32使用HAL库实现定时器PWM输出 STM32CubeMX | STM32使用HAL库进行脉冲宽度和周期测量 1、介绍 以前写过一篇博文,介绍的是如何使用定时器的输入捕获功能测量脉冲的宽度以及周期,适

    2024年02月13日
    浏览(8)
  • 【STM32】HAL库ADC测量精度提高方案(利用内部参考电压VREFINT计算VDDA来提高精度)

    【STM32】HAL库ADC测量精度提高方案(利用内部参考电压VREFINT计算VDDA来提高精度)

    【STM32】HAL库ADC测量精度提高方案(利用内部参考电压VREFINT计算VDDA来提高精度) 多数STM32的MCU 都没有内部基准电压 如L496系列 但在外接VDDA时(一般与VCC 3.3V连接) 有可能VCC不稳定 导致参考电压不确定 从而使ADC测量不准确 STM32内置一个测量VREFINT的ADC通道 且在寄存器VREFINT_

    2024年01月17日
    浏览(6)
  • STM32cubemx定时外部模式测量10M以上频率

    STM32cubemx定时外部模式测量10M以上频率

    本文讲解利用定时器的外部时钟功能,巧妙测量高频外部信号频率。范围可以到高达30M以上。 所需工具: 开发板:STM32F103RCT6 STM32CubeMX IDE: Keil-MDK 定时器的时钟 我们在正常使用TIM定时器的时候,在cubemx里面的时钟树里,随便点击配置,就可以选择好定时器的时钟。比如下面这

    2024年02月11日
    浏览(12)
  • STM32CubeMX学习笔记(48)——USB接口使用(MSC基于外部Flash模拟U盘)

    STM32CubeMX学习笔记(48)——USB接口使用(MSC基于外部Flash模拟U盘)

    USB(Universal Serial BUS)通用串行总线 ,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、Microsoft 等多家公司联合提出的。 USB 发展到现在已经有 US

    2024年01月16日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包