问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

1

S02-CH28 利用LWIP实现ADC DAQ7606数据采集

摘要: 软件版本:VIVADO2017.4操作系统:WIN10 64bit硬件平台:适用米联客 ZYNQ系列开发板米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!28.1 DAQ7606 采集卡图片28.2 项目要求 使用DAQ7606子卡 ...

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

28.1 DAQ7606 采集卡图片

28.2 项目要求

      使用DAQ7606子卡采集数据,通过DMA将数据传输到PS端DDR,PS端使用TCP协议将采集数据发送至PC端。本项目的教程编写参考《DMA_PL_LWIP以太网传输》课时。如果读者对于 ZYNQ 的 DMA 传输,以及 LWIP 的使用还有疑问请先阅读《DMA_PL_LWIP以太网传输》课程并且掌握后再来学习本节课。

28.2.1 功能要求

      PS 通过 AXI GPIO IP核启动 PL 不间断循环构造64bit 位宽的 0~1023 的数据,利用 AXI DMA IP 核,通过 PS的 Slave AXI GP 接口传输至 PS DDR3 的乒乓缓存中。PL 每发完一次 0~1023,AXI DMA IP 核便会产生一个中断信号,PS 得到中断信号后将 DDR3 缓存的数据通过乒乓操作的方式由 TCP协议发 送至 PC 机。

28.2.2 控制协议

      以太网接收控制命令协议格式 

      启动:0xAA55FFA0

      停止:0xAA55FFB1

      复位:0xAA55FFC1

      串口接收控制命令协议格式 

      启动:0xAA55EEA0

      停止:0xAA55EEB1

      复位:0xAA55EEC1

28.3 方案构架

28.3.1 传输方案

      8 路 16bit 200K ADC 经过 PL 采集 送入 128bit 的 FIFO,之后通过 DMA 模块送入 DDR,PS 部分 接收到中断信号后,启动 LWIP 的 TCP 传输,把一包数据发送出去。控制信号,通过以太网口或者 串口发送给开发板,控制启停,复位。

28.3.2 数据包格式

      设计的数据包格式如上图所示,一包数据一共是 1024*128bit。其中包头部分 128bit(32bit*4)格 式,0XAA55AA55 0XAA55AA55 代表了数据包开始,Packet index 代表了数据包的序列号,length 代表了本包数据的长度。

28.4 FPGA 代码介绍

28.4.1 axidma_tcp_demo_wrapper.v

-------所有代码的顶层模块。作用是复制信号之间的连接。关键的信号为 adc_capture_en_reg2使能ADC 采集。 ad_data_valid 代表 ADC 数据有效。

关键代码如下:

always @(posedge  FCLK_CLK1 )//CS

begin

reset_reg1 <= ~peripheral_aresetn;

reset_reg2 <= reset_reg1;

end


assign reset = reset_reg2;


always @(posedge  FCLK_CLK1 )//CS

begin

if(reset) begin

adc_capture_en_reg1 <= 1'd0;

adc_capture_en_reg2 <= 1'd0;

end

else begin

adc_capture_en_reg1 <= gpio_tri_o_0;

adc_capture_en_reg2 <= adc_capture_en_reg1;

end

end


ad7606_ctrl ad7606_ctrl_inst

(

    .clk_i  (FCLK_CLK1),

    .reset_i             (reset),

    .ad_data             (ad_data),

    .ad_busy             (ad_busy),

    .first_data          (first_data),   

    .ad_os               (ad_os),

    .ad_cs               (ad_cs),

    .ad_rd               (ad_rd),

    .ad_reset            (ad_reset),

    .ad_convsta          (ad_convsta),

    .ad_convstb          (ad_convstb),

    .ad_range            (ad_range),

    .ad_ch1_o            (ad_ch1),

    .ad_ch2_o            (ad_ch2),

    .ad_ch3_o            (ad_ch3),

    .ad_ch4_o            (ad_ch4),

    .ad_ch5_o            (ad_ch5),

    .ad_ch6_o            (ad_ch6),

    .ad_ch7_o            (ad_ch7),

    .ad_ch8_o            (ad_ch8),

    .ad_data_valid_o     (ad_data_valid)

    

);  

    

adc_to_axistream   adc_to_axistream_inst

(

.clk_i  (FCLK_CLK1),

.reset_i  (reset),

.adc_capture_en_i  (adc_capture_en_reg2),

.adc_data_i  ({ad_ch1,ad_ch2,ad_ch3,ad_ch4,ad_ch5,ad_ch6,ad_ch7,ad_ch8}),

//.adc_data_i  (128'h0123456789abcdef0123456789abcdef),

.adc_data_valid_i    (1'b1),


.s_axis_adc_tready   (S_AXIS_tready),

.s_axis_adc_tvalid   (S_AXIS_tvalid),

.s_axis_adc_tdata    (S_AXIS_tdata),

.s_axis_adc_tkeep    (S_AXIS_tkeep),

.s_axis_adc_tlast    (S_AXIS_tlast)

    );


assign s_axis_aclk = FCLK_CLK1;

assign s_axis_aresetn = peripheral_aresetn;



axidma_tcp_demo axidma_tcp_demo_i

    (.DDR_addr(DDR_addr),

     .DDR_ba(DDR_ba),

     .DDR_cas_n(DDR_cas_n),

     .DDR_ck_n(DDR_ck_n),

     .DDR_ck_p(DDR_ck_p),

     .DDR_cke(DDR_cke),

     .DDR_cs_n(DDR_cs_n),

     .DDR_dm(DDR_dm),

     .DDR_dq(DDR_dq),

     .DDR_dqs_n(DDR_dqs_n),

     .DDR_dqs_p(DDR_dqs_p),

     .DDR_odt(DDR_odt),

     .DDR_ras_n(DDR_ras_n),

     .DDR_reset_n(DDR_reset_n),

     .DDR_we_n(DDR_we_n),

     .FCLK_CLK1(FCLK_CLK1),

     .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),

     .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),

     .FIXED_IO_mio(FIXED_IO_mio),

     .FIXED_IO_ps_clk(FIXED_IO_ps_clk),

     .FIXED_IO_ps_porb(FIXED_IO_ps_porb),

     .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),

     .gpio_rtl_tri_i(gpio_tri_i_0),

     .gpio_rtl_tri_o(gpio_tri_o_0),

     .gpio_rtl_tri_t(gpio_tri_t_0),

 .s_axis_aclk(s_axis_aclk),

     .s_axis_aresetn(s_axis_aresetn),

     .S_AXIS_tdata(S_AXIS_tdata),

     .S_AXIS_tkeep(S_AXIS_tkeep),

     .S_AXIS_tlast(S_AXIS_tlast),

     .S_AXIS_tready(S_AXIS_tready),

     .S_AXIS_tvalid(S_AXIS_tvalid),

     .peripheral_aresetn(peripheral_aresetn));

28.4.2 ad7606_ctrl.v

-------ADC7606 数 据 采 集 模 块 , 完 成 数 据 的 采 集 , 并 且 保 存 到 各 个 通 道 的 寄 存 器 , 并 且 以 ad_data_valid通知外部数据完成了采集。

其中关键代码如下:

`timescale 1ns / 1ns

//////////////////////////////////////////////////////////////////////////////////

// Module Name:    ad7606

//////////////////////////////////////////////////////////////////////////////////

module ad7606_ctrl(

    input         clk_i,                  //50mhz

input               reset_i,

input[15:0] ad_data,            //ad7606 采样数据

input         ad_busy,            //ad7606 忙标志位

    input         first_data,         //ad7606 第一个数据标志位  

output[2:0] ad_os,              //ad7606 过采样倍率选择

output          ad_cs,              //ad7606 AD cs

output          ad_rd,              //ad7606 AD data read

output     reg ad_reset,           //ad7606 AD reset

output          ad_convsta,         //ad7606 AD convert start

output          ad_convstb,         //ad7606 AD convert start

output              ad_range,

output              ad_ch1_o,

output              ad_ch2_o,

output              ad_ch3_o,

output              ad_ch4_o,

output              ad_ch5_o,

output              ad_ch6_o,

output              ad_ch7_o,

output              ad_ch8_o,

output              ad_data_valid_o

    );


wire[15:0] ad_data;

wire       ad_busy;

wire       first_data;

wire[2:0]  ad_os;

reg        ad_cs;

reg        ad_rd;

reg        ad_convsta;

reg        ad_convstb;

wire       ad_range;

reg[15:0]  ad_ch1_o;

reg[15:0]  ad_ch2_o;

reg[15:0]  ad_ch3_o;

reg[15:0]  ad_ch4_o;

reg[15:0]  ad_ch5_o;

reg[15:0]  ad_ch6_o;

reg[15:0]  ad_ch7_o;

reg[15:0]  ad_ch8_o;

reg        ad_data_valid_o;


reg [7:0] cnt;

reg [7:0] i;

reg [15:0] cnt5us;

reg [7:0] ad_state;


assign ad_os=3'b000;  //无过采样

assign ad_range = 1'b1; //±10V真直流输入范围


//ad复位

always@(posedge clk_i)

begin        

    if(reset_i)   

        ad_reset<=1'b0;            

    if(cnt<4'hf)

    begin

        cnt<=cnt+1'b1;

        ad_reset<=1'b1;

    end

    else

        ad_reset<=1'b0;  //计数器停止,ad_reset拉低,复位结束     

end            


//设置采样频率

always@ (posedge clk_i)   //200k采样率

begin

        if(reset_i)

            cnt5us <= 16'd0;

        if((cnt5us < 16'd249)&&(cnt==8'hf))

            cnt5us <= cnt5us + 1'b1;

        else

            cnt5us <= 16'd0;

end


//状态循环

always @(posedge clk_i)

begin

    if(reset_i)

    begin

        ad_cs<=1'b1;

        ad_rd<=1'b1;

        ad_convsta<=1'b1;   

        ad_convstb<=1'b1;   

        i<=8'd0;   

        ad_ch1_o<=16'd0;

        ad_ch2_o<=16'd0;

        ad_ch3_o<=16'd0;

        ad_ch4_o<=16'd0;

        ad_ch5_o<=16'd0;

        ad_ch6_o<=16'd0;

        ad_ch7_o<=16'd0;

        ad_ch8_o<=16'd0;

        ad_data_valid_o <= 1'b0;

        ad_state<=8'd0;

    end

    else if(ad_reset)

    begin

        ad_cs<=1'b1;

        ad_rd<=1'b1;

        ad_convsta<=1'b1;   

        ad_convstb<=1'b1;   

        i<=8'd0;   

        ad_state<=8'd0;

    end

    else        

    begin

        case(ad_state)     

  8'd0: begin

                     ad_cs<=1'b1;

                     ad_rd<=1'b1;

                     ad_convsta<=1'b1;

                     ad_convstb<=1'b1;

                     ad_data_valid_o <= 1'b0;    

                     ad_state <= 8'd1;

  end

  

8'd1: begin

                          if(i == 8'd5)            

                          begin

                              i<=8'd0;             

                              ad_state<=8'd2;

                          end

                          else

                          begin

                              i<=i+1'b1;

                              ad_state<=8'd1;

                          end

                    end

                    

                    8'd2: begin       

                           if(i==8'd2)     

                           begin                        //等待2个lock,convstab的下降沿最少为25ns,故至少需要两个时钟

                               i<=8'd0;             

                               ad_convsta<=1'b1;

                               ad_convstb<=1'b1;

                               ad_state<=8'd3;                                          

                           end

                           else

                           begin

                               i<=i+1'b1;

                               ad_convsta<=1'b0;

                               ad_convstb<=1'b0;                     //启动AD转换

                               ad_state<=8'd2;

                           end

                    end

                    

                    8'd3: begin            

                           if(i==8'd5)

                           begin                           //等待5个clock, 等待busy信号为高(tconv)

                               i<=8'd0;

                               ad_state<=8'd4;

                           end

                           else

                           begin

                               i<=i+1'b1;

                               ad_state<=8'd3;

                           end

                    end        

                    

                    8'd4: begin            

                             if(!ad_busy)

                             begin                    //等待busy为低电平  即转换之后读取模式         

                                 ad_state<=8'd5;

                             end

                             else

                                 ad_state<=8'd4;

                    end    

                    

                    8'd5: begin

                            ad_cs<=1'b0;                              //cs信号有效  直到读取8通道结束  

                            ad_rd<=1'b0;                       

                            ad_state<=8'd6;  

                     end

                    

                    8'd6: begin            

                            ad_state<=8'd7;

                    end

                    

                    

                    8'd7: begin  

                            if(first_data)                       

                                ad_state<=8'd8;

                            else

                                ad_state<=8'd7;    

                     end

                     

                     8'd8: begin

                           if(i==8'd1)

                           begin

                               ad_rd<=1'b1;

                               ad_ch1_o<=ad_data;                        //读CH1               

                               i<=8'd0;

                               ad_state<=8'd9;                 

                           end

                           else

                           begin  

                               i<=i+1'b1;

                               ad_state<=8'd8;

                           end

                     end

                     8'd9: begin

                           if(i==8'd1)

                           begin

                               ad_rd<=1'b0;              

                               i<=8'd0;

                               ad_state<=8'd10;                 

                           end

                           else

                           begin  

                               i<=i+1'b1;

                               ad_state<=8'd9;

                           end

                     end

                     

                     8'd10: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b1;

                                ad_ch2_o<=ad_data;                        //读CH2

                                i<=8'd0;

                                ad_state<=8'd11;                 

                            end

                            else

                            begin

                                i<=i+1'b1;

                                ad_state<=8'd10;

                            end

                    end

                    8'd11: begin

                           if(i==8'd1)

                            begin

                                ad_rd<=1'b0;

                                i<=8'd0;

                                ad_state<=8'd12;                 

                            end

                            else

                            begin                           

                                i<=i+1'b1;

                                ad_state<=8'd11;  

                            end

                    end        

                      

                    8'd12: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b1;

                                ad_ch3_o<=ad_data;                        //读CH3

                                i<=8'd0;

                                ad_state<=8'd13;                 

                            end

                            else

                            begin    

                                i<=i+1'b1;

                                ad_state<=8'd12;

                            end

                    end

                    8'd13: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b0;

                                i<=8'd0;

                                ad_state<=8'd14;                 

                            end

                            else

                            begin                                 

                                i<=i+1'b1;

                                ad_state<=8'd13;

                            end

                    end

                    

                    8'd14: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b1;

                                ad_ch4_o<=ad_data;                        //读CH4

                                i<=8'd0;

                                ad_state<=8'd15;                 

                 &nb


路过

雷人

握手

鲜花

鸡蛋
发表评论

最新评论

引用 范明慧 2023-4-17 09:11
这个代码不是全部的啊,在哪能看到全部内容?

查看全部评论(1)

本文作者
2019-9-6 19:37
  • 7
    粉丝
  • 12584
    阅读
  • 1
    回复

关注米联客

扫描关注,了解最新资讯

联系人:汤经理
电话:0519-80699907
EMAIL:270682667@qq.com
地址:常州溧阳市天目云谷3号楼北楼201B
热门评论
排行榜
  • 日
  • 周
  • 月

  • 优质服务商家

    严格准入,海量云服务

  • 7*8小时在线服务

    实时咨询,安心购物

  • 专业测试 品质保证

    安全监测,保证品质

  • 退款售后无忧

    不满意可退款

  • 微信公众平台

  • 扫描访问手机版

  • QQ: 270682667

    客服电话

    0519-80699907

    电子邮件

    admin@uisrc.com

    在线时间:8:30-21:00(周一~周六)

  • 返回顶部