首页 > 编程知识 正文

vray灯光设置参数设置,pid调节参数设置技巧

时间:2023-05-04 01:27:20 阅读:52670 作者:960

作者邮箱:dfei55555@163.com

5 AD9361设计说明书(PS端软件部分) 5.1 AD9361 no-OS Software概述AD9361 no-OS Software是ADI公司提供的AD9361的软件部分,在CPU (即Zynq的ARM )上运行, 该程序构成AD9361的各个参数,AD9361是一个没有裸机程序)操作系统,对PL中的几个寄存器进行读写,控制发送数据源,从而实现dmac(DMA控制器) 整个程序用c语言进行。

5.2 AD9361 no-OS Software顶级目录说明ADI官网上可下载到no-OS-Software的源代码。 下载的源代码包含许多ADI收发器,其中包含AD9361的no-OS-Software文件和文件夹目录结构的目录说明

console_commandscommand.h、command.cconsole.h、console.c 12 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 ad 9361无操作系统软件源目录结构

5.3 main.c文件main.c文件是main函数所在的文件,是整个程序的入口。

main.c文件的开头是需要条件编译的头文件和宏定义。

/* * * * include files * * * * * * * * * * * * * * * * * * * * * * * * * include ' platform.h ' # ifdef console ifdef Xilinx ifdefinedxilinx _ platform|| defined Linux _ platform # include ' ADC _ core.h ' # include ' DAC _ core.h

必须添加语句才能使用ZC702。

#define XILINX_PLATFORM

要使用命令行控制AD9361,必须添加语句。

#define CONSOLE_COMMANDS

要使用ADC的数据捕获功能,必须添加语句。

#define CAPTURE_SCRIPT

接下来是命令行函数使用的变量的定义、初始化AD9361所需的参数的变量定义、AD9361的接收方和发送方过滤器的定义。

ad 9361 _ initparamdefault _ init _ param={/* identificationnumber */0,//id_no;/*参考时钟*/4000000 ul,/参考_ clk _ rate/* base configuration */0,//two _ rx _ two _ tx _ mm

//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函数流程图

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);//初始化DMAdac_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 - 1dac_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0); //Number of rows to transfer - 1dac_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请参考该文章

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。