精华内容
下载资源
问答
  • AD9361

    千次阅读 2018-03-26 11:50:00
    AD9361框图   1、 Fir滤波器的阶数为64或128 而内插或抽取因子为:1、2或4。  HB1和HB2的内插或抽取因子为1或2而HB3的因子为1、2或3  BB_LPF为:三阶巴特沃斯低通滤波器,3dB点频率可编程,频率可编程范围为:...

    AD9361框图

     

    1、 Fir滤波器的阶数为64或128 而内插或抽取因子为:1、2或4。

      HB1和HB2的内插或抽取因子为1或2而HB3的因子为1、2或3

      BB_LPF为:三阶巴特沃斯低通滤波器,3dB点频率可编程,频率可编程范围为:Tx: 625Khz~32Mhz, Rx : 200Khz~39.2Mhz

    2、  ND_LPF为:第二级低通滤波器的频率可编程范围为2.7~100Mhz

      TIA_LPF为:第一级低通滤波器的频率可编程范围为1~70Mhz ADC_CLK = DAC_CLK或2*DAC_CLK <= 672Mhz

    3、AD9361增益控制 发送功率控制:由一个程控衰减器决定,衰减范围为(0~89.75dB)步进为0.25dB。

      接收增益控制:由模拟增益(由低噪放、混频器、跨阻放大器和低通滤波器等增益组成)和数字增益决定。

      控制方式为 :自动控制和手动控制(SPI 控制和管脚控制)。

      增益范围 :0~90dB,模拟增益最大为76dB,数字增益最大为31dB。

      增益分配 :由查表决定,有单表模式和多表模式。

    4、AD9361数字接口 SPI接口 : 分为3线模式和4线模式 控制字段由16bit组成,[15]为读写标志,高位读;[14:12]为读写的Byte数1~8Byte;[11:10]未使用;[9:0]为读写的起始字节地址; 上升沿发送,下降沿采样 SPI时钟最大为 50Mhz SPI操作在SPI_ENB为低时有效 LVDS或CMOS接口 :均可分为SDR或DDR接口。

       LVDS接口: 传输速率:最大为122.88Mhz。 传输格式:可分为1R1T,2R2T。

      COMS接口 传输速率:最大为122.88Mhz。 传输格式:可分为1R1T,2R2T,1R2T,2R1T。

      接口形式:可分为单端口半双工,单端口全双工,双端口半双工,双端口全双工。

    5、AD9361状态机 状态机控制方式: 通过SPI写寄存器控制 通过管脚控制(分为电平模式和脉冲模式) 状态机模式: FDD模式 TDD模式

     

    6、AD9361辅助功能 GPO : 4bit通用输出,由SPI控制。

       CTRL_IN : 4bit 控制输入,用于手动Rx增益和Tx衰减控制。

       CTRL_OUT : 8bit控制输出,这些是多功能输出,具有可编程功能。可以用于指示AD9361的各种状态信息。

       Aux DAC : 2个10bit的辅助DAC,参考电压分别可取1V、1.5V、2V和2.5V。

       Aux ADC :1个12bit的辅助ADC,输入电压范围为0V~1.3V。 RSSI : 指示接收信号强度。

    7、AD9361控制编程

       1)SPI接口:通过AD9361的SPI接口对AD9361进行初始化配置,难点在于初始化寄存器,而初始化寄存器可以通过ADI的寄存器配置软件生成。

       2)数据接口:接口形式为LVDS和COMS,难点在于速率较高的情况下,需要加合适的约束或者调解AD9361的时延调整寄存器0x06和0x07。

       3)状态机:需要正确控制状态机,否则AD9361会工作你不知道的状态里,可以通过读取状态寄存器判断。

       4)校准时间:注意AD9361的校准时间需要给足够,否则会影响性能,同时ADI的寄存器配置软件生成的配置能够满足基本功能,但是想要性能更好,需要自己去优化

     

    1、AD9361的框架下图所示:
    QQ截图20160708101845.png 
    2、AD9361的信号路径
    图片1.png图片2.png 
    Fir滤波器的阶数为64或128 而内插或抽取因子为:1、2或4。
    HB1和HB2的内插或抽取因子为1或2而HB3的因子为1、2或3
    BB_LPF为:三阶巴特沃斯低通滤波器,3dB点频率可编程,频率可编程范围为:Tx: 625Khz~32Mhz, Rx : 200Khz~39.2Mhz
    2ND_LPF为:第二级低通滤波器的频率可编程范围为2.7~100Mhz
    TIA_LPF为:第一级低通滤波器的频率可编程范围为1~70Mhz
    ADC_CLK = DAC_CLK或2*DAC_CLK <= 672Mhz

    3、AD9361增益控制
    发送功率控制:由一个程控衰减器决定,衰减范围为(0~89.75dB)步进为0.25dB。
    接收增益控制:由模拟增益(由低噪放、混频器、跨阻放大器和低通滤波器等增益组成)和数字增益决定。
    控制方式为   :自动控制和手动控制(SPI 控制和管脚控制)。
    增益范围
    :0~90dB,模拟增益最大为76dB,数字增益最大为31dB。
    增益分配
    :由查表决定,有单表模式和多表模式。

    4、AD9361数字接口
    SPI接口

    分为3线模式和4线模式
    控制字段由16bit组成,[15]为读写标志,高位读;[14:12]为读写的Byte数1~8Byte;[11:10]未使用;[9:0]为读写的起始字节地址;
    上升沿发送,下降沿采样 
    SPI时钟最大为 50Mhz
    SPI操作在SPI_ENB为低时有效

    LVDS或CMOS接口
    :均可分为SDR或DDR接口。
    LVDS接口:
    传输速率:最大为122.88Mhz。
    传输格式:可分为1R1T,2R2T。
    COMS接口
    传输速率:最大为122.88Mhz。
    传输格式:可分为1R1T,2R2T,1R2T,2R1T。
    接口形式:可分为单端口半双工,单端口全双工,双端口半双工,双端口全双工。

    5、AD9361状态机
    状态机控制方式:
    通过SPI写寄存器控制
    通过管脚控制(分为电平模式和脉冲模式)
    状态机模式:
    FDD模式
    TDD模式

    6、AD9361辅助功能
    GPO
    : 4bit通用输出,由SPI控制。
    CTRL_IN
    : 4bit
    控制输入,用于手动Rx增益和Tx衰减控制。
    CTRL_OUT
    : 8bit控制输出,这些是多功能输出,具有可编程功能。可以用于指示AD9361的各种状态信息。
    Aux DAC
    : 2个10bit的辅助DAC,参考电压分别可取1V、1.5V、2V和2.5V。
    Aux ADC 
    :1个12bit的辅助ADC,输入电压范围为0V~1.3V。
    RSSI
    : 指示接收信号强度。

    7、AD9361控制编程
    1)SPI接口:通过AD9361的SPI接口对AD9361进行初始化配置,难点在于初始化寄存器,而初始化寄存器可以通过ADI的寄存器配置软件生成。
    2)数据接口:接口形式为LVDS和COMS,难点在于速率较高的情况下,需要加合适的约束或者调解AD9361的时延调整寄存器0x06和0x07。
    3)状态机:需要正确控制状态机,否则AD9361会工作你不知道的状态里,可以通过读取状态寄存器判断。
    4)校准时间:注意AD9361的校准时间需要给足够,否则会影响性能,同时ADI的寄存器配置软件生成的配置能够满足基本功能,但是想要性能更好,需要自己去优化。8、做这方面的可以加我QQ进行交流: 1038736077

    展开全文
  • AD9361 文档

    2018-03-27 10:44:45
    AD9361 相关文档,包括 寄存器配置说明 AD9361中文版数据手册,
  • <div><p>This is a midle layer between ad9361_api and libtinyiiod. <p>Signed-off-by: Cristian Pop </p><p>该提问来源于开源项目:analogdevicesinc/no-OS</p></div>
  • ad9361_driver.rar

    2020-08-28 14:34:50
    ad9361的驱动源码,基于c语言。 ad9361_synth_lut.h ad9361_gain_tables.h ad9361_filter_taps.h ad9361_device.h ad9361_client.h ad9361_device.cpp
  • AD9361驱动

    2018-04-27 08:35:37
    AD9361驱动,可以加载到Linux内核中,自动识别为IIO设备。
  • <p>Alternatively, <code>ad9361_get_rx_gain</code> could be implemented to do what <code>ad9361_get_split_table_gain</code> was trying to do: see which table index is active, read the gains for that ...
  • AD9361芯片手册

    2018-11-02 11:07:17
    AD9361中文Datasheet,详细介绍了AD9361内部寄存器资源以及各个寄存器的配置,需要的下载
  • 参考文件《AD9361 Interface Spec v2.5.pdf》 AD9361和FPGA的数据接口如下图中红色框标识。可以配置为CMOS模式和LVDS模式。 根据不同的带宽需求,可以配置为不同的模式,如图: 大部分情况下,设置为2T2R,DDR Bus...

    参考文件《AD9361 Interface Spec v2.5.pdf》

    AD9361和FPGA的数据接口如下图中红色框标识。可以配置为CMOS模式和LVDS模式。
    在这里插入图片描述
    根据不同的带宽需求,可以配置为不同的模式,如图:
    在这里插入图片描述
    大部分情况下,设置为2T2R,DDR Bus,Dual Port Full Duplex模式,这种模式最大化使用了AD9361的资源,并且可以覆盖大部分其他模式的功能。如下图所示:
    在这里插入图片描述
    收数据接口时序图如下:
    在这里插入图片描述
    发数据接口时序图如下:
    在这里插入图片描述
    根据以上模式选择,就可以写代码了,代码如下图:

    module axi_ad9361_dev_if (
    // physical interface (receive)
    input rx_frame_in_p,
    input rx_frame_in_n,
    input [5:0] rx_data_in_p,
    input [5:0] rx_data_in_n,
    // physical interface (transmit)
    output tx_clk_out_p,
    output tx_clk_out_n,
    output tx_frame_out_p,
    output tx_frame_out_n,
    output [5:0] tx_data_out_p,
    output [5:0] tx_data_out_n,
    // internal clock
    input data_clk,
    input iddr_clk,
    input oddr_clk,
    // receive data path interface
    output reg adc_valid,
    output reg [11:0] adc_data_i1,
    output reg [11:0] adc_data_q1,
    output reg [11:0] adc_data_i2,
    output reg [11:0] adc_data_q2,
    output reg adc_status,
    input adc_r1_mode,
    // transmit data path interface
    input dac_valid,
    input [11:0] dac_data_i1,
    input [11:0] dac_data_q1,
    input [11:0] dac_data_i2,
    input [11:0] dac_data_q2,
    input dac_r1_mode
    );
    // internal registers
    reg [ 5:0]  rx_data_n     = 'd0;
    reg         rx_frame_n    = 'd0;
    reg [11:0]  rx_data       = 'd0;
    reg [ 1:0]  rx_frame      = 'd0;
    reg [11:0]  rx_data_d     = 'd0;
    reg [ 1:0]  rx_frame_d    = 'd0;
    reg         rx_error_r1   = 'd0;
    reg         rx_valid_r1   = 'd0;
    reg [11:0]  rx_data_i_r1  = 'd0;
    reg [11:0]  rx_data_q_r1  = 'd0;
    reg         rx_error_r2   = 'd0;
    reg         rx_valid_r2   = 'd0;
    reg [11:0]  rx_data_i1_r2 = 'd0;
    reg [11:0]  rx_data_q1_r2 = 'd0;
    reg [11:0]  rx_data_i2_r2 = 'd0;
    reg [11:0]  rx_data_q2_r2 = 'd0;
    reg [ 2:0]  tx_data_cnt   = 'd0;
    reg [11:0]  tx_data_i1_d  = 'd0;
    reg [11:0]  tx_data_q1_d  = 'd0;
    reg [11:0]  tx_data_i2_d  = 'd0;
    reg [11:0]  tx_data_q2_d  = 'd0;
    reg         tx_frame      = 'd0;
    reg [ 5:0]  tx_data_p     = 'd0;
    reg [ 5:0]  tx_data_n     = 'd0;
    // internal signals
    wire    [ 3:0]  rx_frame_s;
    wire    [ 3:0]  tx_data_sel_s;
    wire    [ 5:0]  rx_data_ibuf_s;
    wire    [ 5:0]  rx_data_p_s;
    wire    [ 5:0]  rx_data_n_s;
    wire            rx_frame_ibuf_s;
    wire            rx_frame_p_s;
    wire            rx_frame_n_s;
    wire    [ 5:0]  tx_data_oddr_s;
    wire            tx_frame_oddr_s;
    wire            tx_clk_oddr_s;
    genvar          l_inst;
    //receive data path interface
    assign rx_frame_s = {rx_frame_d, rx_frame};
    always @(posedge data_clk)
      begin
        rx_data_n   <=rx_data_n_s;
        rx_frame_n  <=rx_frame_n_s;
        rx_data     <={rx_data_n,rx_data_p_s};
        rx_frame    <={rx_frame_n,rx_frame_p_s};
        rx_data_d   <=rx_data;
        rx_frame_d  <=rx_frame;
      end
    //receive data path for single rf, frame is expected to qualify i/q msb only
    always @(posedge data_clk)
      begin
        rx_error_r1<=((rx_frame_s==4'b1100)||(rx_frame_s==4'b0011))?1'b0:1'b1;
        rx_valid_r1<=(rx_frame_s==4'b1100)?1'b1:1'b0;
        if (rx_frame_s==4'b1100)
          begin
            rx_data_i_r1<={rx_data_d[11:6],rx_data[11:6]};
            rx_data_q_r1<={rx_data_d[ 5:0],rx_data[ 5:0]};
          end
      end
    //receive data path for dual rf, frame is expected to qualify i/q msb and lsb for rf-1 only
    always @(posedge data_clk)
      begin
        rx_error_r2<=((rx_frame_s==4'b1111)||(rx_frame_s==4'b1100)||(rx_frame_s==4'b0000)||(rx_frame_s== 4'b0011))?1'b0:1'b1;
        rx_valid_r2<=(rx_frame_s==4'b0000)?1'b1:1'b0;
        if(rx_frame_s==4'b1111)
          begin
            rx_data_i1_r2<={rx_data_d[11:6],rx_data[11:6]};
            rx_data_q1_r2<={rx_data_d[ 5:0],rx_data[ 5:0]};
          end
        if(rx_frame_s==4'b0000)
          begin
            rx_data_i2_r2<={rx_data_d[11:6],rx_data[11:6]};
            rx_data_q2_r2<={rx_data_d[ 5:0],rx_data[ 5:0]};
          end
      end
    //receive data path mux
    always @(posedge data_clk)
      begin
        if(adc_r1_mode==1'b1)
          begin
            adc_valid   <=rx_valid_r1;
            adc_data_i1 <=rx_data_i_r1;
            adc_data_q1 <=rx_data_q_r1;
            adc_data_i2 <=12'd0;
            adc_data_q2 <=12'd0;
            adc_status  <=~rx_error_r1;
          end
        else
          begin
            adc_valid   <=rx_valid_r2;
            adc_data_i1 <=rx_data_i1_r2;
            adc_data_q1 <=rx_data_q1_r2;
            adc_data_i2 <=rx_data_i2_r2;
            adc_data_q2 <=rx_data_q2_r2;
            adc_status  <=~rx_error_r2;
          end
      end
      
    //ila_0 ila_1 (
    //      .clk(data_clk),
    //      .probe0({
    //          rx_frame_s,
    //          adc_valid,
    //          adc_data_i1,
    //          adc_data_q1,
    //          adc_data_i2,
    //          adc_data_q2})
    //  );  
    // transmit data path mux (reverse of what receive does above)
    // the count simply selets the data muxing on the ddr outputs
    //------------------data format 1t--------------------------
    //valid :~~~ ___ ~~~ ___ ~~~ ___ ~~~ ___                  //
    //datai :i1      i1      i1      i1                       //
    //dataq :q1      q1      q1      q1                       //
    //cnt   :    100 101 100 101 100 101 100                  //
    //------------------data format 2t--------------------------
    //valid :~~~ ___ ___ ___ ~~~ ___ ___ ___ ~~~ ___ ___ ___  //
    //datai :i1              i1              i1               //
    //dataq :q1              q1              q1               //
    //datai :i2              i2              i2               //
    //dataq :q2              q2              q2               //
    //cnt   :    100 101 110 111 100 101 110 111 100 101 110  //
    //----------------------------------------------------------
    assign tx_data_sel_s={tx_data_cnt[2],dac_r1_mode,tx_data_cnt[1:0]};
    always @(posedge data_clk)
      begin
        if (dac_valid)
          begin
            tx_data_cnt<=3'b100;
            tx_data_i1_d<=dac_data_i1;
            tx_data_q1_d<=dac_data_q1;
            tx_data_i2_d<=dac_data_i2;
            tx_data_q2_d<=dac_data_q2;
           end
        else if(tx_data_cnt[2]==1'b1)
          tx_data_cnt<=tx_data_cnt+1'b1;
        case (tx_data_sel_s)
          4'b1101:
            begin
              tx_frame  <=1'b0;
              tx_data_p <=tx_data_i1_d[ 5:0];
              tx_data_n <=tx_data_q1_d[ 5:0];
            end
          4'b1100:
            begin
              tx_frame  <=1'b1;
              tx_data_p <=tx_data_i1_d[11:6];
              tx_data_n <=tx_data_q1_d[11:6];
            end
          4'b1011:
            begin
              tx_frame  <=1'b0;
              tx_data_p <=tx_data_i2_d[ 5:0];
              tx_data_n <=tx_data_q2_d[ 5:0];
            end
          4'b1010:
            begin
              tx_frame  <=1'b0;
              tx_data_p <=tx_data_i2_d[11:6];
              tx_data_n <=tx_data_q2_d[11:6];
            end
          4'b1001:
            begin
              tx_frame  <=1'b1;
              tx_data_p <=tx_data_i1_d[ 5:0];
              tx_data_n <=tx_data_q1_d[ 5:0];
            end
          4'b1000:
            begin
              tx_frame  <=1'b1;
              tx_data_p <=tx_data_i1_d[11:6];
              tx_data_n <=tx_data_q1_d[11:6];
            end
          default:
            begin
              tx_frame  <=1'b0;
              tx_data_p <=6'd0;
              tx_data_n <=6'd0;
            end
        endcase
      end
    // receive data interface, ibuf  -> iddr
    generate
    for (l_inst=0;l_inst<=5;l_inst=l_inst+1)
    begin:g_rx_data
    IBUFDS i_rx_data_ibuf(.I(rx_data_in_p[l_inst]),.IB(rx_data_in_n[l_inst]),.O(rx_data_ibuf_s[l_inst]));
    IDDR #(
    .DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"    ),
    .INIT_Q1      (1'b0                     ),
    .INIT_Q2      (1'b0                     ),
    .SRTYPE       ("ASYNC"                  ))
    i_rx_data_iddr  ( 
    .CE           (1'b1                     ),
    .R            (1'b0                     ),
    .S            (1'b0                     ),
    .C            (iddr_clk                 ),
    .D            (rx_data_ibuf_s[l_inst]   ),
    .Q1           (rx_data_p_s[l_inst]      ),
    .Q2           (rx_data_n_s[l_inst]      ));
    end endgenerate
    // receive frame interface, ibuf  -> iddr
    IBUFDS i_rx_frame_ibuf (.I(rx_frame_in_p),.IB(rx_frame_in_n),.O(rx_frame_ibuf_s));
    IDDR #(
    .DDR_CLK_EDGE   ("SAME_EDGE_PIPELINED"  ),
    .INIT_Q1        (1'b0                   ),
    .INIT_Q2        (1'b0                   ),
    .SRTYPE         ("ASYNC"                ))
    i_rx_frame_iddr ( 
    .CE             (1'b1                   ),
    .R              (1'b0                   ),
    .S              (1'b0                   ),
    .C              (iddr_clk               ),
    .D              (rx_frame_ibuf_s        ),
    .Q1             (rx_frame_p_s           ),
    .Q2             (rx_frame_n_s           ));
    // transmit data interface, oddr -> obuf
    generate
    for (l_inst=0;l_inst<=5;l_inst=l_inst+1)
    begin: g_tx_data
    ODDR #(
    .DDR_CLK_EDGE   ("SAME_EDGE"            ),
    .INIT           (1'b0                   ),
    .SRTYPE         ("ASYNC"                ))
    i_tx_data_oddr  (   
    .CE             (1'b1                   ),
    .R              (1'b0                   ),
    .S              (1'b0                   ),
    .C              (oddr_clk               ),
    .D1             (tx_data_p[l_inst]      ),
    .D2             (tx_data_n[l_inst]      ),
    .Q              (tx_data_oddr_s[l_inst] ));
    OBUFDS i_tx_data_obuf (.I(tx_data_oddr_s[l_inst]),.O(tx_data_out_p[l_inst]),.OB(tx_data_out_n[l_inst]));
    end endgenerate
    // transmit frame interface, oddr -> obuf
    ODDR #(
    .DDR_CLK_EDGE   ("SAME_EDGE"            ),
    .INIT           (1'b0                   ),
    .SRTYPE         ("ASYNC"                ))
    i_tx_frame_oddr (
    .CE             (1'b1                   ),
    .R              (1'b0                   ),
    .S              (1'b0                   ),
    .C              (oddr_clk               ),
    .D1             (tx_frame               ),
    .D2             (tx_frame               ),
    .Q              (tx_frame_oddr_s        ));
    OBUFDS i_tx_frame_obuf (.I(tx_frame_oddr_s),.O(tx_frame_out_p),.OB(tx_frame_out_n));
    // transmit clock interface, oddr -> obuf
    ODDR #(
    .DDR_CLK_EDGE   ("SAME_EDGE"            ),
    .INIT           (1'b0                   ),
    .SRTYPE         ("ASYNC"                ))
    i_tx_clk_oddr   (
    .CE             (1'b1                   ),
    .R              (1'b0                   ),
    .S              (1'b0                   ),
    .C              (oddr_clk               ),
    .D1             (1'b0                   ),
    .D2             (1'b1                   ),
    .Q              (tx_clk_oddr_s          ));
    OBUFDS i_tx_clk_obuf (.I(tx_clk_oddr_s),.O(tx_clk_out_p),.OB(tx_clk_out_n));
    endmodule
    

    这个代码其实是兼容1T1R的,通过adc_r1_mode和dac_r1_mode设置。如果你要用这个代码,这两个信号输入0,就是默认的2T2R模式了

    展开全文
  • AD9361开发资料合集.rar

    2020-06-01 06:26:46
    包括AD9361参考手册UG-570、AD9361寄存器映射参考手册UG-671、AD9361中文版数据手册、AD9361寄存器配置软件AD9361 Evaluation Software、AD9361内部结构框图等
  • AD9361芯片AD元件封装

    2019-04-13 23:21:10
    AD9361芯片AD元件封装,可以用来设计软件无线电收发平台,亲测有效。
  • ad9361原理

    2016-05-16 22:00:58
    了解ad9361原理、框架 寄存器配置。
  • ad9361.png

    2020-03-12 20:05:40
    ad9361的数据手册,可以用来参考以便进行电路设计
  • AD9361中文资料

    2018-12-05 14:53:48
    AD9361中文资料,内容讲述了9361的使用,希望对射频开发者有用,
  • 这个AXI_AD9361模块跟上述分析仪的PACK和UNPACK模块相比,除了连接片内其他模块之外还连接AD9361芯片。应该说是AD9361跟内部其他模块的接口。 我们来看看都链接那些9361芯片的引脚: 上图中黄色线是链接9361...

    这个AXI_AD9361模块跟上述分析仪的PACK和UNPACK模块相比,除了连接片内其他模块之外还连接AD9361芯片。应该说是AD9361跟内部其他模块的接口。

    我们来看看都链接那些9361芯片的引脚:

     

     

    上图中黄色线是链接9361模块的,我们再放大看看:

     

    在模块左边的脚是输入接收AD9361芯片的输出。右边的脚是输出给AD9361芯片。

    各自分析一下这些脚:

    rx_clk_in_p和rx_clk_in_n 是AD9361输出给FPGA(ZYNQ)的时钟频率。用来同步rx_frame_in和rx_data。

    rx_frame_in_p和rx_frame_in_n是AD9361输出给FPGA(ZYNQ)的数据有效信号,也可以认为是同步信号。

    rx_data_in_p和rx_data_in_n是AD9361输出给FPGA(ZYNQ)的数据,可以配置成双边缘的,也可以配置成单边缘的。配置成双边缘时候注意布线一定严格差分和组等长。

    一路txnrx输出。输出那路是对应控制ad9361的收发状态。 

    一路enable输出。输出那路是对应控制ad9361的内部状态机的转换。 【考虑可能是跟txnrx配合使用的】。

    至于up_txnrx和up_enable,那并没有接到ad9361芯片上,接在了ps的EMIO上。估计是可能为了实现多个AD9361数控控制的级联而预留的。

     

     

     

     

     

    展开全文
  • ad9361工程原理图

    2018-10-05 17:39:07
    ad9361工程原理图,使用ad9361进行射频信号的开发与实践
  • ad9361寄存器配置资料

    2019-01-28 10:56:34
    AD9361芯片详细的寄存器配置资料,根据该资料可以实现AD9361的各种功能
  • AD9361的datasheet

    2018-11-03 21:48:55
    AD9361的datasheet,纯英文手册,详细介绍了AD9361的各寄存器及其使用
  • ad9361_vivado例程

    2021-06-04 21:10:51
    一个基于vivado2016.4的ad9361例程,可参考使用
  • AD9361校准指南.pdf

    2020-06-07 18:13:51
    英文版,AD9361 Initialization and Factory Calibration Guide,零中频收发器AD9361的校准指南
  • AD9361 程序配置模版

    2018-09-12 16:42:32
    AD9361 R2 Auto Generated Initialization Script: This script was // generated using the AD9361 Customer software Version 2.1.3
  • AD9361资料

    2015-06-10 10:40:56
    AD9361的资料,有关注射频和软件无线电的可以看看
  • ad9361学习记录

    2018-12-10 16:42:40
    ad9361学习记录包括系统构成、初始化注意、滤波器配置、射频工作状态机控制等
  • AD9361寄存器映射

    2016-09-23 10:05:09
    ad9361寄存器配置文档
  • AD9361配置软件

    2018-08-08 11:48:07
    AD9361配置软件,可在软件内完成相关配置然后生成寄存器配置文件。
  • AD9361 datasheet

    2019-01-03 15:04:57
    The AD9361 is a high performance, highly integrated radio frequency (RF) Agile Transceiver™ designed for use in 3G and 4G base station applications. Its programmability and wideband capability make ...
  • AD9361参数设置总结

    千次阅读 多人点赞 2019-12-10 09:39:01
    5 AD9361 参考设计说明(PS侧软件部分) 5.1 AD9361 no-OS Software 概述 AD9361 no-OS Software是ADI公司提供的AD9361的软件部分,运行在CPU(也就是Zynq的ARM)中,该程序为裸机程序(即无操作系统的程序),...

    作者邮箱:dfei55555@163.com

    5 AD9361 参考设计说明(PS侧软件部分)

    5.1 AD9361 no-OS Software 概述

    AD9361 no-OS Software是ADI公司提供的AD9361的软件部分,运行在CPU(也就是Zynq的ARM)中,该程序为裸机程序(即无操作系统的程序),可以AD9361各个参数进行配置,对PL中的一些寄存器进行读写,控制发送数据源,控制DMAC(DMA控制器)对发送和接收的数据进行传输,从而实现AD9361的基本功能:对数据的接收、处理和发送。整个程序是使用C语言来完成的。

    5.2 AD9361 no-OS Software 顶层目录说明

    在ADI官网可以下载到no-OS-Software的源码,下载到的源码包含了很多ADI的收发器,
     列出的是AD9361的no-OS-Software中的文件和文件夹目录结构
    

    目录 子文件 解释说明

    console_commands command.h 、command.c
    console.h、console.c
    1 2

    platform_altera Altera平台的相关文件(使用Xilinx平台无需该文件)
    platform_generic 通用平台的相关文件(使用Xilinx平台无需该文件)
    platform_linux Linux平台相关的文件(使用Xilinx平台无需该文件)
    platform_xilinx adc_core.h、adc_core.c 模数转换模块控制文件,包括模块的初始化和数据传输等
    dac_core.h、dac_core.c 模数转换模块控制文件,包括模块的初始化和数据传输等
    Platform.c、platform.h Xilinx平台一些驱动文件
    parameters.h 以上文件所用到的参数的宏定义文件
    ad9361.c AD9361的驱动文件,比如增益控制函数等
    ad9361.h
    ad9361_api.c AD9361应用编程接口驱动文件,比如AD9361的初始化函数
    ad9361_api.h
    common.h 通用驱动文件,包含时钟结构体和通用宏定义
    config.h AD9361和 AD9361 API的配置文件
    main.c 整个软件部分的main函数文件
    util.c util驱动文件
    util.h
    | | |
    表 1 AD9361 no-OS-Software源码目录结构

    5.3 main.c文件

    main.c文件是main函数所在文件,是整个程序的入口。
    main.c文件的开头是需要条件编译的头文件和宏定义。

    /****************************Include Files ***********************************/
    
    #include "config.h"
    #include "ad9361_api.h"
    #include "parameters.h"
    #include "platform.h"
    #ifdef CONSOLE_COMMANDS
    #include "command.h"
    #include "console.h"
    #endif
    #ifdef XILINX_PLATFORM
    #include <xil_cache.h>
    #endif
    #if defined XILINX_PLATFORM || defined LINUX_PLATFORM
    #include "adc_core.h"
    #include "dac_core.h"
    #include "adc_interrupt.h"
    #include "SD_card.h"
    #endif
    

    因此,在使用时需要根据情况在程序最开始对一些参数进行宏定义,
    使用ZC702需要添加语句:
    #define XILINX_PLATFORM
    如需使用命令行控制AD9361,需要添加语句:
    #define CONSOLE_COMMANDS
    如需使用ADC的数据捕获功能,需要添加语句:
    #define CAPTURE_SCRIPT

    然后是命令行函数所用到的一些变量的定义、对AD9361初始化所需要参数的变量定义和AD9361接收和发射端滤波器的定义。

    AD9361_InitParam default_init_param = {
      /* Identification number */
      0,    //id_no;
      /* Reference Clock */
      40000000UL, //reference_clk_rate
      /* Base Configuration */
      0,    //two_rx_two_tx_mode_enable *** adi,2rx-2tx-mode-enable
      1,    //one_rx_one_tx_mode_use_rx_num *** adi,1rx-1tx-mode-use-rx-num
      1,    //one_rx_one_tx_mode_use_tx_num *** adi,1rx-1tx-mode-use-tx-num
      1,    //frequency_division_duplex_mode_enable *** adi,frequency-division-duplex-mode-enable
      0,    //frequency_division_duplex_independent_mode_enable *** adi,frequency-division-duplex-independent-mode-enable
      0,    //tdd_use_dual_synth_mode_enable *** adi,tdd-use-dual-synth-mode-enable
      0,    //tdd_skip_vco_cal_enable *** adi,tdd-skip-vco-cal-enable
      0,    //tx_fastlock_delay_ns *** adi,tx-fastlock-delay-ns
      0,    //rx_fastlock_delay_ns *** adi,rx-fastlock-delay-ns
      0,    //rx_fastlock_pincontrol_enable *** adi,rx-fastlock-pincontrol-enable
      0,    //tx_fastlock_pincontrol_enable *** adi,tx-fastlock-pincontrol-enable
      0,    //external_rx_lo_enable *** adi,external-rx-lo-enable
      0,    //external_tx_lo_enable *** adi,external-tx-lo-enable
      5,    //dc_offset_tracking_update_event_mask *** adi,dc-offset-tracking-update-event-mask
      6,    //dc_offset_attenuation_high_range *** adi,dc-offset-attenuation-high-range
    

    之后的部分是整个软件部分的主函数,主函数的程序流程图如图 6所示(默认定义了XILINX_PLATFORM常量):main流程图.vsdx

    图 9 main函数流程图
    main
    DAC模块初始化使用的函数为dac_init函数

    ADC数据捕获使用到的函数为adc_capture函数
    这两个函数是控制数据传输的主要函数,下面的章节将会详细介绍这两个函数。

    5.4 dac_init函数

    dac_init为DAC模块初始化函数,也负责DMA传输部分,将DDR中的数据送给AD9361。
    dac_init函数的函数声明为:

    第一个参数 struct ad9361_rf_phy *phy 为指向AD9361的射频设备结构体的指针。
    第二个参数 uint8_t data_sel为 需要发送的数据源的选择:

    enum dds_data_select 
    {
      DATA_SEL_DDS,
      DATA_SEL_SED,
      DATA_SEL_DMA,
      DATA_SEL_ZERO,  /* OUTPUT 0 */
      DATA_SEL_PN7,
      DATA_SEL_PN15,
      DATA_SEL_PN23,
      DATA_SEL_PN31,
      DATA_SEL_LB,  /* loopback data (ADC) */
      DATA_SEL_PNXX,  /* (Device specific) */
      USER_DATA,
    };
    
    

    0表示发送DDS生成的信号;
    2表示通过DMA发送DDR中的信号数据,该数据在dac_core.c开头定义;
    3表示发送全0信号;
    4-7表示发送随机数信号;
    8表示发送从ADC中接收到的数据信号;
    9表示发送选定设备的信号;
    10为用户数据(需要在函数中添加代码)
    第三个参数为DMA设置的标准位,0表示设置;1表示不设置。

    下图为dac_init函数的流程图:dac_init流程图.vsdx
    图 10 dac_init函数流程图

    其中需要重点关注配置DAC的DMAC的部分(橙色部分),配置DMAC的流程图如图 8所示:

    图 11 dac DMAC部分流程图
    源代码如下:

    dac_dma_write(AXI_DMAC_REG_CTRL, 0);//初始化DMA
    dac_dma_write(AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE);//DMA通道使能
    dac_dma_write(AXI_DMAC_REG_SRC_ADDRESS, DAC_DDR_BASEADDR);//设置DMA的传输源地址为DDR的基地址
    dac_dma_write(AXI_DMAC_REG_SRC_STRIDE, 0x0);
    dac_dma_write(AXI_DMAC_REG_X_LENGTH, length - 1);//Number of bytes to transfer - 1
    dac_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0);       //Number of rows to transfer - 1
    dac_dma_write(AXI_DMAC_REG_START_TRANSFER, 0x1); //向传输队列中加入传输请求
    

    dac_dma_write函数的作用是向选定地址(第一个参数)中写入数值(第二个参数)
    以上这些宏定义都是DMAC的寄存器地址:

    AXI_DMAC_REG_CTRL:DMAC总控制寄存器,两位00表示关闭DMA通道;01表示使能DMA通道;
    AXI_DMAC_REG_SRC_ADDRESS:传输源地址寄存器,内容为DMA传输的源地址(即数据所在地址);
    AXI_DMAC_REG_SRC_STRIDE:传输每行的字节数;
    AXI_DMAC_REG_X_LENGTH:传输数据的总字节数;
    AXI_DMAC_REG_Y_LENGTH:传输数据的行数;
    AXI_DMAC_REG_START_TRANSFER:传输开始寄存器,写入1会将新的传输加入传输队列;
    关于这些寄存器和其完整的说明在HDL Core RegMap.pdf

    DMA传输支持2维传输(即按行列传输),但是目前只需要一维传输,因此,在源代码里向AXI_DMAC_REG_SRC_ADDRESS和AXI_DMAC_REG_Y_LENGTH写入0表示只使用一维传输。

    在传输用户数据时,也应该在将用户数据进行调制后,参照以上代码,使用DMA方式发送数据

    5.5 adc_capture函数

    adc_capture函数为数据捕获函数,也负责DMA传输数据到	DDR
    

    adc_init函数的函数声明为:

    第一个参数size为要捕获的数据量(个);
    第二个参数为start_adress存储捕获数据的目的地址。

    图 9为dac_init函数的流程图:

    图 12 adc_captur函数流程图

    源代码如下:

    int32_t adc_capture(uint32_t size, uint32_t start_address)
    {
      uint32_t reg_val;
      if(adc_st.rx2tx2)
      {
        length = (size * 8);
      }
      else
      {
        length = (size * 4);
      }
    

    上图的源码为adc_capture函数的第一部分——数据单位转换部分,adc_capture函数的第一个参数size为用户想要捕获到的数据量,单位是“个”,但是在DMAC的很多寄存器中,比如AXI_DMAC_REG_X_LENGTH寄存器,其中的数值为传输的数据的总字节数,单位为“字节”,因此需要将size单位转换为“字节”。如果打开了双通道,那么捕获的数据数据会占用双倍的存储空间。

    adc_dma_write(AXI_DMAC_REG_CTRL, 0x0); //初始化DMA通道
    adc_dma_write(AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE);//DMA通道使能
    
    adc_dma_write(AXI_DMAC_REG_IRQ_MASK, 0x0);//取消屏蔽.
    
    //adc_dma_read(AXI_DMAC_REG_TRANSFER_ID, &transfer_id);//读取下一个传输的ID号(5位)
    
    adc_dma_read(AXI_DMAC_REG_IRQ_PENDING, &reg_val);    /*读取中断状态:一个传输完成后 END_OF_TRANSFER 即 [1]位 置 1,
                                                    一个传输加入队列后 START_OF_TRANSFER 即 [0]位 置 1 */
    
    adc_dma_write(AXI_DMAC_REG_IRQ_PENDING, reg_val);//写入中断状态寄存器,使中断寄存器初始化
    
    adc_dma_write(AXI_DMAC_REG_DEST_STRIDE, 0x0);//设置目的地址中从一行的开始和下一行之间的字节数
    adc_dma_write(AXI_DMAC_REG_X_LENGTH, length - 1);//传输的字节数
    adc_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0);//传输的行数
    
    
    adc_dma_write(AXI_DMAC_REG_DEST_ADDRESS, start_address); //设置传输的目的地址(destination address)
    adc_dma_write(AXI_DMAC_REG_START_TRANSFER, 0x1);//加入传输队列
    

    上图为adc_capture函数的第二部分——DMA配置部分,其中与ADC模块相比不同的寄存器为:
    AXI_DMAC_REG_IRQ_MASK:中断屏蔽寄存器,[1]位为EOT(End Of Transfer)IRQ,[0]位为SOT(Start Of Transfer) IRQ,哪一位置1,就表示那一位的中断请求被屏蔽;
    AXI_DMAC_REG_IRQ_PENDING:读取中断状态:一个传输完成后 END_OF_TRANSFER 即 [1] 位 置 1,一个传输加入队列后 START_OF_TRANSFER 即 [0] 位 置 1 */
    AXI_DMAC_REG_TRANSFER_ID:该寄存器的数值为下一次传输的ID号。

       //Wait until the new transfer is queued.
      do
      {
        adc_dma_read(AXI_DMAC_REG_START_TRANSFER, &reg_val);
      }
      while(reg_val == 1);*/
    
      // Wait until the current transfer is completed.
    do
      {
        adc_dma_read(AXI_DMAC_REG_IRQ_PENDING, &reg_val);
      }
      while(1);//reg_val !=0011b*/
    
      //Wait until the transfer with the ID transfer_id is completed.
    do
      {
        adc_dma_read(AXI_DMAC_REG_TRANSFER_DONE, &reg_val); //读取传输完成的ID号
       }
      while((reg_val & (1 << transfer_id)) != (1 << transfer_id));
    
    上图为上图为adc_capture函数的第三部分——判断与等待
    

    1.等待,直到一个新的传输加入传输队列

    读取AXI_DMAC_REG_START_TRANSFER寄存器的值,值为1时循环,值为0时跳出循环。
    之前已经向AXI_DMAC_REG_START_TRANSFER写入了1,在这时判断AXI_DMAC_REG_START_TRANSFER的值,若是1,表示新的传输仍然在排队,若是0,表示新的传输已经开始。

    2.等待,直到目前的传输完成。

    读取AXI_DMAC_REG_IRQ_PENDING的值,当传输进行时,AXI_DMAC_REG_IRQ_PENDING的[0]位SOT位始终为1,当传输完成时,[1]为EOT位由0置为1,之后两位都会被清0。因此,当AXI_DMAC_REG_IRQ_PENDING的值为3时,表示传输完成。

    3.等待,直到ID为transfer_id的传输完成

    这一步是为了验证之前设置的传输已经完成。

    MCU如何配置AD9361请参考该文章

    展开全文
  • AD9361设计包.zip

    2020-05-29 10:01:09
    AD9361设计包.zip
  • AD9361资料包

    2018-01-23 11:00:34
    包含使用AD9361搭建的无线软件平台,含介绍,原理图,其它芯片资料

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 428
精华内容 171
关键字:

ad9361