作者邮箱: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-enable1,    //one_rx_one_tx_mode_use_rx_num *** adi,1rx-1tx-mode-use-rx-num1,    //one_rx_one_tx_mode_use_tx_num *** adi,1rx-1tx-mode-use-tx-num1,    //frequency_division_duplex_mode_enable *** adi,frequency-division-duplex-mode-enable0,    //frequency_division_duplex_independent_mode_enable *** adi,frequency-division-duplex-independent-mode-enable0,    //tdd_use_dual_synth_mode_enable *** adi,tdd-use-dual-synth-mode-enable0,    //tdd_skip_vco_cal_enable *** adi,tdd-skip-vco-cal-enable0,    //tx_fastlock_delay_ns *** adi,tx-fastlock-delay-ns0,    //rx_fastlock_delay_ns *** adi,rx-fastlock-delay-ns0,    //rx_fastlock_pincontrol_enable *** adi,rx-fastlock-pincontrol-enable0,    //tx_fastlock_pincontrol_enable *** adi,tx-fastlock-pincontrol-enable0,    //external_rx_lo_enable *** adi,external-rx-lo-enable0,    //external_tx_lo_enable *** adi,external-tx-lo-enable5,    //dc_offset_tracking_update_event_mask *** adi,dc-offset-tracking-update-event-mask6,    //dc_offset_attenuation_high_range *** adi,dc-offset-attenuation-high-range

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

图 9 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参数设置总结相关推荐

  1. 2021年大数据Hadoop(二十九):​​​​​​​关于YARN常用参数设置

    全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 关于yarn常用参数设置 设置container分配最小内 ...

  2. 设置最大值_电机变频器参数设置不当会怎样

    我们知道变频器驱动电机运行是需要设置参数的,包括变频器运行控制模式如启动.停止,频率给定的命令来源,变频器频率的上下限.加减速等等参数都要根据实际情况来正确的设置. 控制模式与接线方式的不统一造成的, ...

  3. Socket中的异常和参数设置

    1.常见异常 1.java.net.SocketTimeoutException . 这个异 常比较常见,socket 超时.一般有 2 个地方会抛出这个,一个是 connect 的 时 候 , 这 ...

  4. Selenium2(WebDriver)总结(二)---Firefox的firebug插件参数设置(补充)

    Selenium2(WebDriver)总结(二)---Firefox的firebug插件参数设置(补充) 本文是对上一节的补充:http://www.cnblogs.com/puresoul/p/4 ...

  5. Vcastr 2.2 flv 网络播放器 参数设置

    Vcastr 2.2 flv 网络播放器 参数设置 参数名称 参数说明 默认值 vcastr_file 方法2传递影片flv文件地址参数,多个使用|分开 空 vcastr_title 影片标题参数,多 ...

  6. myeclipse.ini内存参数设置及其含义

    =================================== 目前的配置 -vmargs -Xmx1024m -XX:MaxPermSize=256m -XX:ReservedCodeCac ...

  7. oracle自动分区maxvalue,分区表中的maxvalue参数设置-Oracle

    分区表中的maxvalue参数设置 结论:partition p3 values less than (maxvalue)   分区表中maxvalue如果用具体参数来代替,则整个表中可插入的最大值不 ...

  8. R语言ggplot2可视化分面图(facet_grid)、自定义缩小分面图标签栏的高度、但是不改变标签栏标签文本的大小、通过element_text函数的margin参数设置实现

    R语言ggplot2可视化分面图(facet_grid).自定义缩小分面图标签栏的高度.但是不改变标签栏标签文本的大小.通过element_text函数的margin参数设置实现 目录

  9. python使用matplotlib可视化、使用subplots函数将可视化的画布划分为网格状的若干子区、通过nrows和ncols参数设置设置行数和列数

    python使用matplotlib可视化.使用subplots函数将可视化的画布划分为网格状的若干子区.通过nrows和ncols参数设置设置行数和列数 目录

最新文章

  1. 换脸火了,我用 Python 快速入门生成模型
  2. chrome Native Client 让你可以使用 C 以及 C++ 语言开发 Web 应用
  3. Java竞选组长发言_竞选组长的发言稿_450字
  4. html复制文件到目录,复制指定目录下的全部文件到另一个目录中
  5. Atitit.mybatis的测试  以及spring与mybatis在本项目中的集成配置说明
  6. 撸个微信小程序的省市区选择器
  7. Project2007工具栏没有Pert分析按钮
  8. 三角形的外心 内心 重心 垂心 九点圆心与各圆半径的算法
  9. 人工智能助力复工复产,模版OCR轻松搞定健康码识别
  10. 中科院微生物所真菌学国家重点实验室高佳鑫组招聘启事
  11. #Paper Reading#Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts
  12. python基础教程:Python绘制正余弦函数图像的方法
  13. 图像处理1--傅里叶变换(Fourier Transform )
  14. 为了买基金,写个基金理投资财分析系统,哈哈可以凑活用
  15. GPU加速在前端的应用
  16. Java9中2个被废弃的使用方法
  17. spacedesk投影,将电脑屏幕投影或者扩展到手机
  18. FastReport——打印和打印设置
  19. SAP接口debug设置外部断点
  20. 标准曲线制作、SEM检验、使用知识大全

热门文章

  1. 办公室装修的五要四不要
  2. 随机梯度下降(SGD)与经典的梯度下降法的区别
  3. 机械键盘简要介绍。。。。
  4. [c语言+easyx]GUI界面 年会抽奖系统
  5. 【留言板】在这聊个天勾搭一下神犇之类的
  6. php amr格式转换,php 微信amr转mp3的方法
  7. 大文件传输软件的优势你了解吗?
  8. Java游戏服务器架构的并发问题及解决方案
  9. 基于ArcGIS:GIS空间分析复习-理论概念+案例分析
  10. 【报告分享】小红书品牌营销白皮书2021半年报-新红数据(附下载)