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


仿真结果

在这里插入图片描述

### ROS编写传感器数据采集模块 在ROS中,创建用于传感器的数据采集模块涉及多个方面。为了确保不同节点间有效通信,必须遵循统一的消息格式[^3]。 #### 创建ROS包 首先需要建立一个新的ROS包来容纳所有的源文件和配置项: ```bash catkin_create_pkg sensor_data_collection rospy roscpp std_msgs sensor_msgs ``` 此命令会基于指定依赖关系初始化新项目环境。 #### 编写Python脚本实现数据读取功能 对于具体应用而言,假设目标是从某种类型的传感器获取信息并将其封装成适合ROS处理的形式发送出去,则可以在`src/`目录下新建一个名为`sense_and_publish.py`的Python脚本来完成这项工作: ```python #!/usr/bin/env python import rospy from std_msgs.msg import String, Float64MultiArray import random # 这里仅作为模拟实际硬件接口的例子 def talker(): pub = rospy.Publisher('sensor_readings', Float64MultiArray, queue_size=10) rospy.init_node('data_collector') rate = rospy.Rate(1) # 设置发布频率为每秒一次 while not rospy.is_shutdown(): simulated_sensor_value = [random.uniform(-1.0, 1.0), random.uniform(-1.0, 1.0)] # 模拟两个通道的传感数值 msg_to_send = Float64MultiArray(data=simulated_sensor_value) rospy.loginfo(f"Publishing: {msg_to_send}") pub.publish(msg_to_send) rate.sleep() if __name__ == '__main__': try: talker() except rospy.ROSTimeMovedBackwardsException as e: pass except Exception as ex: template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) print(message) ``` 上述代码展示了如何利用Python编写的简单示例程序定期向特定主题发布来自虚拟化双轴传感器的信息流。当然,在真实场景中应当替换掉随机数生成部分以连接真实的物理设备或者调用相应的库函数访问底层资源[^1]。 #### 配置launch文件简化启动过程 为了让整个系统更易于管理和部署,还可以进一步构建`.launch`文件以便一键式激活所有必要的进程和服务: ```xml <launch> <!-- 启动传感器数据收集器 --> <node name="collector" pkg="sensor_data_collection" type="sense_and_publish.py" output="screen"/> </launch> ``` 这样就完成了从零开始搭建一套简单的ROS框架下的传感器数据采集系统的介绍[^4]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值