本文将介绍如何在PS中调用Zynq内部的XADC模块进行片内温度和电源电压测量。先了解XADC的相关知识,再通过实例体会XADC的用法,学习XADC API函数的使用。
XADC介绍
XADC中文全称应该是“Xilinx模拟混合信号模块”,是FPGA中的一个硬核。在7系列FPGA中,XADC提供了DRP和JTAG接口,用于访问XADC的状态和控制寄存器。Zynq中添加了第三个接口,称作PS-XADC接口,PS通过此接口来控制XADC。使用XADC可以满足一定的模拟数据采集和设备监控需求。
XADC有组成部分有:
- 两个12位、1MSPS的ADC,每个ADC有独立的跟踪和保持放大器;支持单极、双极、查分等多种模拟信号输入类型;1ms采样率,最高支持500kHz信号带宽。
- 一个模拟多路复用器,最高支持17个外部模拟输入通道;在不需要额外封装引脚的情况下增加支持的外部通道的数量
- 片上热传感器和电压传感器
XADC可以采用片内参考电路,监测片内温度和电源电压时可以无需外部有源器件。如果要实现ADC的全12位性能,还是需要外部加一个1.25V的参考电压IC。
XADC把最近的测量结果、最大值、最小值分别存储在专用寄存器中。我们可以自定义报警阈值,当温度或电源电压超过这个值时便会发出信号。据此,我们可以在程序中控制系统断电来保护芯片。
XADC的系统模块框图如下:
Zynq设计
Vivado中建立工程,配置好Zynq的MIO电压、DDR、串口。XADC模块位于PL部分,需要使用PL中的时钟。因此配置Zynq时钟时要将FCLK_CLK0视作XADC的工作时钟,我这里设置为100MHz。
添加XADC Wizard IP核,点击上方出现的run connection automation,Vivado会自动添加其它辅助模块,并完成连线。设计整体框图如下:
自动添加了两个子模块,Processor System Reset主要负责为整个处理器系统提供复位功能,包括处理器、互联网络和外设。AXI Interconnect主要完成AXI接口间的位宽、时钟或协议的转换。一般这两个模块都是根据系统自动添加的,只要大致了解其功能即可。
SDK程序设计
配置完成后导入到SDK中。使用XADC监测Zynq内部温度和电源电压,以串口方式输出。user_xadc.h文件代码如下:
#ifndef SRC_USER_XADC_H_ #define SRC_USER_XADC_H_ #include#include "sleep.h" #include "xil_printf.h" #include "xadcps.h" //XADC设备的支持驱动程序 void XADC_Init(XAdcPs* XADCMonInst); void XADC_Printf(XAdcPs* XADCInstPtr); #endif /* SRC_USER_XADC_H_ */
user_xadc.c文件的代码如下:
main.c文件的代码如下:
#include "user_xadc.h" static XAdcPs XADCInst; //XADC int main() { XADC_Init(&XADCInst); while(1) { xil_printf("-------------XADC result-------------\r\n"); XADC_Printf(&XADCInst); sleep(5); } }
SDK Terminal中添加串口,运行程序,将看到每隔5s便打印一次Zynq内部温度和各种电压信息,包括原始数据“raw”和转换后的实际数据“real”。
相关API函数
1. XADC初始化
对XADC设备初始化操作和前面GPIO设备、中断设备、定时器设备的初始化过程一样,不再赘述。
接着使用XAdcPs_SelfTest函数对XADC设备进行自检,该函数先将XADC复位,向报警门限寄存器写一个值再读取进行比较,然后再次复位XADC。如果比较结果相同则返回XST_SUCCESS,否则返回XST_FAILURE,程序中可以根据自检函数的返回值判断XADC工作是否正常。
int XAdcPs_SelfTest(XAdcPs *InstancePtr) //函数原型
2. XADC配置
之后使用4个函数依次设置XADC的工作模式。首先用XAdcPs_SetSequencerMode函数,设置通道序列器模式,一次只能选择一个模式。各模式的宏定义在xadcps.h文件中,这里设置为“单通道”模式。
void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode)
使用XAdcPs_SetAlarmEnables函数设置是否使能报警输出,第二个参数为1表示启用,为0表示禁用。
void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask)
使用XAdcPs_SetSeqInputMode函数设置模拟输入模式,设置成功返回XST_SUCCESS,否则返回XST_FAILURE。
int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask)
使用XAdcPs_ SetSeqChEnables函数设置启用哪些通道,设置成功返回XST_SUCCESS,否则返回XST_FAILURE。各通道的宏定义在xadcps.h文件中。
int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask)
3. 数据采集与转换
使用XAdcPs_GetAdcData函数获取指定通道的ADC转换数据。设置的通道应该是0-6和13-31。通道7-9用于校准设备,无法获得与这三个通道相关的数据。
u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel)
使用两个宏定义XAdcPs_RawToVoltage和XAdcPs_RawToTemperature可以将XADC采集到的原始数据转换为电压(V)和温度(℃)。其等效的C语言函数接口为:
float XAdcPs_RawToTemperature(u32 AdcData); float XAdcPs_RawToVoltage(u32 AdcData);
总结
XADC的使用算是比较复杂,本文只是简单的使用其测量了Zynq内部的温度和电源电压。XADC也是SPI中的一个中断源,还可以采集外部信号。熟练掌握XADC的使用,不仅需要编程能力,还要对其结构和工作原理有一定了解。
---------------------