AN9238模块数据采集

AN9238模块数据采集

1 AN9238原理

在这里插入图片描述
根据时序图,只要FPGA输出两路时钟信号作为AD模块的AD_clk,便可以采集数据。
其他原理见数据手册

2 板上验证

顶层模块

`timescale 1ns / 1ps

module top(
       input clk50m, //系统时钟
       input reset_n,
       
       output wire [0:0] clk65m_1, //FPGA输出的时钟信号1,作为AD模块的输入时钟1
       output wire [0:0] clk70m_1, //FPGA输出的时钟信号2,作为AD模块的输入时钟2
                         
       input wire [11:0] ad1_in,   // 离散数据输入到FPGA
       input wire [11:0] ad2_in    
    
);
        
  
/****************PLL  产生65M时钟和50M时钟 **************/
//首先PLL产生两路时钟clk65m、clk70m;
//然后将这两个时钟赋值给FPGA的输出时钟clk65m_1和clk70m_1;
//ADC时,将clk65m_1和clk70m_1赋值给ADC的时钟
wire clk65m; 
wire clk70m;
assign clk65m_1=clk65m;
assign clk70m_1=clk70m;

pll pll_inst
(
    // Clock out ports
    .clk_out1(clk65m),        // output clk_out1
    .clk_out2(clk70m),       // output clk_out2
    // Status and control signals
    .reset(~reset_n),         // input reset
    .locked( ),               // output locked
   // Clock in ports
    .clk_in1(clk50m)
  );                        // input clk_in1

   
                 
 /**************** AD 转化模块  ADC数据采样**************/
wire [11:0] ad_ch1;
wire [11:0] ad_ch2;

v_ad v_ad_inst (
    .ad1_clk(clk65m_1) ,//65M
    .ad2_clk(clk65m_1) ,//65M
    
	.ad1_in(ad1_in),//模拟数据输入到AD模块
 	.ad2_in(ad2_in),
 				 
	.ad_ch1(ad_ch1),AD模块输出数字数据
 	.ad_ch2(ad_ch2)
);




 /**************** fifo**************/     
wire wr_en=1;       //写使能
wire rd_en=1;       //读使能
wire [11:0] dout;   // 读数据
wire full;          //写满信号
wire empty;         //读空信号
wire [9 : 0] rd_data_count ;// 可读数据数量
wire [9 : 0] wr_data_count ;//已写入的数据数量
     
     
     
fifo_generator_1 fifo_wr_inst (
  .rst      (~reset_n),                      // input wire rst
  .wr_clk   (clk65m),                // input wire wr_clk
  .rd_clk   (clk70m),                // input wire rd_clk
  .din      (ad1_in),                      // input wire [11 : 0] din
  .wr_en    (wr_en),                  // input wire wr_en
  .rd_en    (rd_en),                  // input wire rd_en
  .dout     (dout),                    // output wire [11 : 0] dout
  .full     (full),                    // output wire full
  .empty    (empty),                  // output wire empty
  .rd_data_count(rd_data_count),  // output wire [9 : 0] rd_data_count
  .wr_data_count(wr_data_count)  // output wire [9 : 0] wr_data_count
);

     
     
// 例化ila,观察波形
ila_0 ila_0_inst (
       .clk(clk50m), // input wire clk
     
       .probe0(ad1_in), // input wire [11:0]  probe0  input 
       .probe1(ad2_in), // input wire [11:0]  probe1 
       .probe2(ad_ch1), // input wire [11:0]  probe2  output
       .probe3(ad_ch2), // input wire [11:0]  probe3
       .probe4(ad1_in), // input wire [11:0]  probe4 
       .probe5(dout), // input wire [11:0]  probe5 
       .probe6(rd_data_count), // input wire [9:0]  probe6 
       .probe7(wr_data_count), // input wire [9:0]  probe7
       .probe8(clk65m), // input wire [0:0]  probe8 
       .probe9(clk70m) // input wire [0:0]  probe9
);

          
endmodule


上面调用了两个三个IP核:
pll:产生65M和70M的时钟信号。
fifo:将AD采集的数据送到fifo中缓存。
ila:观察信号。

AD采集模块

`timescale 1ns / 1ps
// AD 转化模块

module v_ad(
             input              ad1_clk ,//65M
             input              ad2_clk ,//65M
			 input [11:0]       ad1_in  ,
 			 input [11:0]       ad2_in  ,
			 
			 output reg [11:0]  ad_ch1  ,
 			 output reg [11:0]  ad_ch2
			 
    );
//通道1采集数据
always @(posedge ad1_clk)//根据时序,只要给时钟信号clk_A就可以采集数据,在上升沿采集数据
begin
    ad_ch1 <= ad1_in;   
end 

//通道2采集数据
always @(posedge ad2_clk)//根据时序,只要给时钟信号clk_A就可以采集数据,在上升沿采集数据
begin
    ad_ch2 <= ad2_in;   	 
end
 
endmodule

约束文件

############## clock and reset define##################
create_clock -period 20.000 [get_ports clk50m]
set_property IOSTANDARD LVCMOS33 [get_ports clk50m]
set_property PACKAGE_PIN U18 [get_ports clk50m]

set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
set_property PACKAGE_PIN N15 [get_ports reset_n]




##############AX7020 and AX7010  J11##################
set_property PACKAGE_PIN F16 [get_ports {ad2_in[0]}]
set_property PACKAGE_PIN F20 [get_ports {ad2_in[1]}]
set_property PACKAGE_PIN F19 [get_ports {ad2_in[2]}]
set_property PACKAGE_PIN G20 [get_ports {ad2_in[3]}]
set_property PACKAGE_PIN G19 [get_ports {ad2_in[4]}]
set_property PACKAGE_PIN H18 [get_ports {ad2_in[5]}]
set_property PACKAGE_PIN J18 [get_ports {ad2_in[6]}]
set_property PACKAGE_PIN L20 [get_ports {ad2_in[7]}]
set_property PACKAGE_PIN L19 [get_ports {ad2_in[8]}]
set_property PACKAGE_PIN M20 [get_ports {ad2_in[9]}]
set_property PACKAGE_PIN M19 [get_ports {ad2_in[10]}]
set_property PACKAGE_PIN K18 [get_ports {ad2_in[11]}]



set_property PACKAGE_PIN H20 [get_ports {ad1_in[1]}]
set_property PACKAGE_PIN J20 [get_ports {ad1_in[0]}]
set_property PACKAGE_PIN L17 [get_ports {ad1_in[3]}]
set_property PACKAGE_PIN L16 [get_ports {ad1_in[2]}]
set_property PACKAGE_PIN M18 [get_ports {ad1_in[5]}]
set_property PACKAGE_PIN M17 [get_ports {ad1_in[4]}]
set_property PACKAGE_PIN D20 [get_ports {ad1_in[7]}]
set_property PACKAGE_PIN D19 [get_ports {ad1_in[6]}]
set_property PACKAGE_PIN E19 [get_ports {ad1_in[9]}]
set_property PACKAGE_PIN E18 [get_ports {ad1_in[8]}]
set_property PACKAGE_PIN G18 [get_ports {ad1_in[11]}]
set_property PACKAGE_PIN G17 [get_ports {ad1_in[10]}]


set_property PACKAGE_PIN H17 [get_ports  clk65m_1]
set_property IOSTANDARD LVCMOS33 [get_ports clk65m_1]
set_property PACKAGE_PIN F17 [get_ports  clk70m_1]
set_property IOSTANDARD LVCMOS33 [get_ports clk70m_1]

set_property IOSTANDARD LVCMOS33 [get_ports {ad1_in[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad2_in[*]}]

#set_property IOB true [get_ports ad2_in[*]]
#set_property IOB true [get_ports ad1_in[*]]

create_debug_core u_ila_0 ila
set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0]
set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0]
set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0]
set_property C_DATA_DEPTH 1024 [get_debug_cores u_ila_0]
set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0]
set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0]
set_property C_TRIGIN_EN false [get_debug_cores u_ila_0]
set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0]
set_property port_width 1 [get_debug_ports u_ila_0/clk]
connect_debug_port u_ila_0/clk [get_nets [list pll_inst/inst/clk_out1]]
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0]
set_property port_width 12 [get_debug_ports u_ila_0/probe0]
connect_debug_port u_ila_0/probe0 [get_nets [list {v_ad_inst/ad1_in[0]} {v_ad_inst/ad1_in[1]} {v_ad_inst/ad1_in[2]} {v_ad_inst/ad1_in[3]} {v_ad_inst/ad1_in[4]} {v_ad_inst/ad1_in[5]} {v_ad_inst/ad1_in[6]} {v_ad_inst/ad1_in[7]} {v_ad_inst/ad1_in[8]} {v_ad_inst/ad1_in[9]} {v_ad_inst/ad1_in[10]} {v_ad_inst/ad1_in[11]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1]
set_property port_width 12 [get_debug_ports u_ila_0/probe1]
connect_debug_port u_ila_0/probe1 [get_nets [list {v_ad_inst/ad2_in[0]} {v_ad_inst/ad2_in[1]} {v_ad_inst/ad2_in[2]} {v_ad_inst/ad2_in[3]} {v_ad_inst/ad2_in[4]} {v_ad_inst/ad2_in[5]} {v_ad_inst/ad2_in[6]} {v_ad_inst/ad2_in[7]} {v_ad_inst/ad2_in[8]} {v_ad_inst/ad2_in[9]} {v_ad_inst/ad2_in[10]} {v_ad_inst/ad2_in[11]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2]
set_property port_width 12 [get_debug_ports u_ila_0/probe2]
connect_debug_port u_ila_0/probe2 [get_nets [list {v_ad_inst/ad_ch2[0]} {v_ad_inst/ad_ch2[1]} {v_ad_inst/ad_ch2[2]} {v_ad_inst/ad_ch2[3]} {v_ad_inst/ad_ch2[4]} {v_ad_inst/ad_ch2[5]} {v_ad_inst/ad_ch2[6]} {v_ad_inst/ad_ch2[7]} {v_ad_inst/ad_ch2[8]} {v_ad_inst/ad_ch2[9]} {v_ad_inst/ad_ch2[10]} {v_ad_inst/ad_ch2[11]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3]
set_property port_width 12 [get_debug_ports u_ila_0/probe3]
connect_debug_port u_ila_0/probe3 [get_nets [list {v_ad_inst/ad_ch1[0]} {v_ad_inst/ad_ch1[1]} {v_ad_inst/ad_ch1[2]} {v_ad_inst/ad_ch1[3]} {v_ad_inst/ad_ch1[4]} {v_ad_inst/ad_ch1[5]} {v_ad_inst/ad_ch1[6]} {v_ad_inst/ad_ch1[7]} {v_ad_inst/ad_ch1[8]} {v_ad_inst/ad_ch1[9]} {v_ad_inst/ad_ch1[10]} {v_ad_inst/ad_ch1[11]}]]
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets clk50m_IBUF]

结果分析
在这里插入图片描述

3 仿真

仿真文件

`timescale 1ns / 1ps

module sim_top;

    //input
    reg clk50m;
    reg reset_n;
    reg [11:0] ad1_in;
    reg [11:0] ad2_in;
    
    //output
    wire [11:0] ad_ch1;
    wire [11:0] ad_ch2;
    // 初始化
    top top_inst( 
    //input     
        .clk50m(clk50m),       
        .reset_n(reset_n),                                      
        .ad1_in(ad1_in),
        .ad2_in(ad2_in)
                      
//         //output  对于FPGA来说,是输入              
//         .ad_ch1(ad_ch1),   
//         .ad_ch2(ad_ch2)       
        
        );
        
 //--------------模拟产生顶层模块所需的输入信号
//1、模拟产生时钟信号和复位信号    
    initial
    begin
     //初始化输入
        clk50m=0;
        reset_n=0;
        #1000;
        reset_n=1;
    end
    // create clock;
    always #10 clk50m=~clk50m;


 //2模拟产生两个通道待采集的模拟数据
 always @(posedge clk50m or negedge reset_n )
 begin 
     if (reset_n==1'b0)
            begin 
               ad1_in <=12'd0;
               ad2_in <=12'd0;
            end                 
     else 
            begin 
                   ad1_in <=ad1_in+1'd1;
                   ad2_in <=ad2_in+2'd2;
            end 
end

endmodule


仿真结果

在这里插入图片描述

  • 1
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
很抱歉,我无法提供完整的代码。但是,我可以给您提供一些关于MQ2气体传感器数据采集和显示的指导。 首先,您需要配置ADC模块以便从MQ2传感器读取模拟信号。这可以通过以下步骤完成: 1. 确定您需要使用的ADC通道和引脚。 2. 初始化ADC模块,并设置采样时间和采样分辨率。 3. 配置ADC通道和引脚,并启用ADC转换。 4. 等待ADC转换完成,并读取转换结果。 以下是一个示例代码片段,演示如何配置ADC模块: ```c ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // Configure ADC pins GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); // Configure ADC module ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure); // Enable ADC module ADC_Cmd(ADC1, ENABLE); // Start ADC conversion ADC_StartOfConversion(ADC1); ``` 一旦您成功地从ADC模块读取了模拟信号,您需要将其转换为实际浓度值。MQ2传感器的输出信号是电阻值,因此您需要使用一些算法将其转换为气体浓度。 以下是一个示例代码片段,演示如何将ADC读数转换为气体浓度值: ```c // Convert ADC reading to resistance in ohms float resistance = ((float)adc_reading / 4095.0) * 3.3 / 0.1; // Calculate gas concentration in ppm float concentration = 0.0; if (resistance >= 0.2 && resistance <= 10.0) { concentration = pow(10, ((log10(resistance / 9.6) + 0.173) / -0.723)); } ``` 最后,您需要将浓度值显示在LCD或其他显示设备上。这可以通过以下步骤完成: 1. 初始化LCD或其他显示设备。 2. 将浓度值转换为字符串。 3. 将字符串显示在LCD或其他显示设备上。 以下是一个示例代码片段,演示如何在LCD上显示浓度值: ```c // Initialize LCD module LCD_Init(); // Convert concentration to string char concentration_str[10]; sprintf(concentration_str, "%.2f ppm", concentration); // Display concentration on LCD LCD_SetCursor(0, 0); LCD_WriteString("Gas Concentration:"); LCD_SetCursor(0, 1); LCD_WriteString(concentration_str); ``` 希望这些指导可以帮助您开始编写MQ2气体传感器数据采集和显示的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值