?
?
學習內容
本文首先介紹了ZYNQ的XADC的相關內容,并學習使用ZYNQ芯片中的XADC測量芯片內部的溫度電壓等參數,然后進行串口打印輸出。
開發(fā)環(huán)境
vivado 18.3&SDK,PYNQ-Z2開發(fā)板。
XADC介紹
簡介
Xilinx模擬信號轉換模塊,稱為XADC,是一個硬核。它具有JTAG和DRP接口用于訪問7系列FPGA中的XADC狀態(tài)和控制寄存器。Zynq-7000 SoC器件添加了第三個接口,即PS-XADC接口,用于PS軟件進行控制XADC。ZYNQ器件將XADC與可編程邏輯融合,解決了對模擬數據采集和監(jiān)視要求。
XADC具有兩個12位的ADC,具有獨立的跟蹤和保持放大器,模擬多路復用器(最多17個外部模擬輸入通道)以及片上散熱和片上電壓傳感器??梢詫蓚€ADC配置為同時采樣兩個外部輸入模擬通道。采樣保持放大器支持一系列模擬輸入信號類型,包括單端輸入,雙端輸入和差分輸入。模擬輸入可以支持信號帶寬在1M SPS的采樣率下為500 KHz??梢允褂猛獠磕M多路復用器來增加支持的外部通道數量,無需額外的封裝引腳。XADC可選地使用片上參考電路,從而無需外部有源元件,用于溫度和電源軌的基本片上監(jiān)控。實現12位的ADC的全部性能,建議使用外部1.25V作為參考電壓。最新的測量結果(連同最大和最小讀數)存儲在專用寄存器。用戶可以根據自己的需要進行自定義的警報閾值(例如80°C),可以自動指示溫度過高事件和不可接受的電源變化,并啟動軟件控制的系統(tǒng)掉電。
控制方式
PS端可以通過以下兩種方式之一與XADC通信:
- PS-XADC接口:PS互連上的32位APB從接口,該接口使用FIFO,并進行了串行化。
- 通過PS to PL AXI的主接口,此時要使用AXI XADC Logic IP核來控制XADC。
需要注意的是,對PS端控制ADC對性能要求較高的程序,要使用相關連接的邏輯IP連接到M_AXI_GP接口(并行數據路徑)。使用PS_XADC接口時,FIFO用于命令和讀取數據,以允許軟件快速排隊命令,而不必等待序列化,但是對于PS to PL AXI主接口訪問,數據像PL-JTAG一樣被序列化到XADC 中(串行數據路徑),相對來說速度慢得多。
系統(tǒng)框圖
PL-JTAG接口和內部PS-XADC接口不能同時使用。這些接口之間的選擇由devcfg.XADCIF_CFG [ENABLE]位控制。XADC可以進行接口選擇,即對(PL-JTAG或PS-XADC)和DRP接口之間進行仲裁選擇。下圖為XADC的系統(tǒng)框圖。
由上圖可知,XADC是通過硬邏輯實現的,并且位于PL電源域中。PS-XADC接口是PS的一部分,所以無需編程PL就可以由PS APU訪問。但是必須打開PL的電源以配置PS-XADC接口,使用PL-JTAG或DRP接口以及操作XADC。同時由圖上可以清楚看出對于PL-JTAG或PS-XADC這兩個接口經過了一個二選一選擇器,所以這兩個不能同時進行驅動。
接口說明
XADC在DRP接口與PS-XADC或PL-JTAG接口之間進行仲裁。
PS-XADC Interface: PS-XADC接口是PS中運行的軟件使用devcfg寄存器配置接口。軟件將命令寫入接口,然后將其推入命令FIFO。這些由DRP命令,地址和數據組成的32位寫入被串行化,并以回送路徑發(fā)送到XADC,該回送路徑填充了軟件讀取的返回讀取數據FIFO。
DRP Interface: DRP接口是一個并行的16位雙向接口,可以使用AXI4-Lite接口通過AXI XADC IP核連接到主機上,以使處理器能夠控制XADC。IP內核通過每個AXI4-Lite讀/寫事務接收16位數據。
PL JTAG Interface: XADC使用完整的JTAG接口擴展到DRP接口。這允許通過現有的片上JTAG基礎結構對XADC DRP進行讀/寫訪問。通過JTAG訪問DRP接口不需要實例化。邊界掃描指令(6位指令= 110111)稱為XADC_DRP,已添加到7系列FPGA中,允許通過JTAG TAP訪問DRP。所有XADC JTAG指令均為32位寬。
PS-XADC接口編程指南
本文主要使用的是PS-XADC接口對XADC進行編程控制,下面給出相關操作的編程指導步驟。
通過PS-XADC接口初始化XADC
對通道和XADC進行復位操作,并刷新FIFO,操作順序如下:
- 復位串行通訊通道。 ?先后把1和0到devcfg.XADCIF_MCTL[RESET]寄存器位中;
- 復位XADC。 把16位任意值寫入DRP地址0x03(復位寄存器)。接著寫08030000h到devcfg.XADCIF_CMDFIFO寄存器中;
- 刷新FIFO。 這里刷新FIFO沒有復位信號,而是將15個NOOP寫入到FIFO;然后等待命令FIFO清空。最后一個命令應該是NOOP(虛擬寫入),最后讀取讀取數據FIFO,直到為空。
命令準備
準備要寫入XADC寄存器的數據配置順序:本示例格式化了用于寫入XADC配置寄存器1的數據,以將XADC設置為獨立模式。
- DRP數據。將XADC設置為獨立模式的數據為8000h。
- DRP地址。XADC配置寄存器1的地址為0x41。
- 編寫命令。寫入操作的命令為0010b。在XADC配置寄存器1(0x41)中寫入8000h的命令為08418000h。
準備從XADC寄存器讀取的數據配置順序:本示例格式化了用于讀取XADC VCCPAUX狀態(tài)寄存器0x0E的數據。
- DRP數據。數據可以是用于讀取操作(0)的任何任意數據。
- DRP地址。XADC VCCPAUX狀態(tài)寄存器的地址為0x0E。
- 編寫命令。讀取操作的命令為0001b。讀取XADC VCCPAUX狀態(tài)寄存器0x0E的命令為040E0000h。
讀寫FIFO數據
向XADC寫入命令以下編程順序為寫入XADC 電壓警報上限閾值寄存器。
- 準備命令。執(zhí)行上面的命令準備的部分,寫入具有所需閾值的XADC VCCPAUX警報上限閾值寄存器(0x5A)。
- 用數據填充命令FIFO。將步驟1中格式化的數據寫入devcfg.XADCIF_CMDFIFO寄存器。
- 等待命令FIFO變空。等待,直到devcfg.XADCIF_MSTS [CFIFOE] = 1。
從XADC讀取VCCPAUX值:從XADC VCCPAUX狀態(tài)寄存器讀取當前VCCPAUX值順序如下:
- 準備命令。執(zhí)行上面的命令準備的部分,讀取XADC VCCPAUX狀態(tài)寄存器(0x0E)。
- 將數據寫入命令FIFO。將步驟1中格式化的數據寫入devcfg.XADCIF_CMDFIFO寄存器。
- 等待命令FIFO變空。等待,直到devcfg.XADCIF_MSTS [CFIFOE] = 1。
- 從讀取數據FIFO讀取偽數據。讀取devcfg.XADCIF_RDFIFO寄存器。
- 格式化數據。執(zhí)行上面的命令準備的部分,以使其不進行任何操作。
- 將數據寫入命令FIFO。將步驟5中的格式化數據寫入devcfg.XADCIF_CMDFIFO寄存器。
- 讀取讀取數據FIFO。讀取devcfg.XADCIF_RDFIFO寄存器。
中斷
配置和管理Alarm5(VCCPAUX)本示例將XADC寄存器配置為設置警報閾值,操作模式并啟用PS-XADC接口中的警報5(VCCPAUX)中斷。
- 準備命令。執(zhí)行上面的命令準備的部分,寫入XADC硬宏警報閾值寄存器(VCCPAUX Upper-0x5A和VCCPAUX具有所需閾值的低0x5E)和XADC Config_Reg1(0x41)來將XADC設置為獨立模式。
- 將命令寫入命令FIFO。將步驟1中準備的命令寫到devcfg.XADCIF_CMDFIFO寄存器。
- 在PS-XADC接口中啟用Alarm5中斷。寫devcfg.XADCIF_INT_MASK[M_ALM] = 7Eh。
- 檢查是否觸發(fā)了Alarm5。devcfg.XADCIF_INT_STS [M_ALM] = 1的輪詢。
- 清除Alarm5中斷。寫入devcfg.XADCIF_INT_STS [M_ALM] = 1。
- 禁用Alarm0中斷。寫入devcfg.XADCIF_INT_MASK [M_ALM] = 7Fh
通過PS-XADC接口的啟動順序
通過PS-XADC接口的啟動并設置各種接口參數,并包括中斷和數據傳輸的步驟如下。
- 完成初始化XADC;
- 配置PS-XADC接口:對配置寄存器進行編程。將80001114h寫入devcfg.XADCIF_CFG寄存器:使用默認的最小空閑間隙,[IGAP] = 14h(20個串行時鐘)。使用默認的XADC串行時鐘頻率為PCAP_2x時鐘頻率的1/4,[TCKRATE] = 01。使用默認的FIFO串行讀取捕獲邊沿(上升),[REDGE] = 1。使用默認的FIFO串行寫啟動邊沿(下降),[WEDGE] = 0。使用默認的讀取數據FIFO閾值級別,[DFIFOTH] = 0x0。使用默認的命令FIFO閾值級別,[CFIFOTH] = 0。啟用XADC的PS訪問。將0x1寫入devcfg.XADCIF_CFG [ENABLE]。
- 配置中斷:中斷用于管理來自XADC和操作FIFO/讀取FIFO數據;
- 數據傳輸到XADC。
系統(tǒng)框圖
根據本次工程,畫出相應的系統(tǒng)框圖,如下圖所示:
本次工程,使用了UART和XADC部分,使用XADC對芯片內部的電壓和溫度進行檢測,并用串口打印輸出。
硬件平臺搭建
因為不需要使用其他資源,可以在原來的UART測試工程下進行開發(fā)搭建,直接保存即可。新建步驟如下,首先新建工程,創(chuàng)建 block design。添加ZYNQ7 ip,根據本次工程需要對IP進行配置。勾選本次工程使用的資源。
這里只要勾選UART資源即可,取消多余資源,然后點擊OK。硬件系統(tǒng)構建完成如下:
然后我們進行generate output product 然后生成HDL封裝。這里用到了UART,是MIO引腳,所以不需要進行管腳分配,XADC測量是內部的電壓信息,并且使用的是PS_XADC接口。點擊導出硬件資源(可以不包含bit流文件,因為只用到了PS資源),接著launch SDK。
SDK軟件部分
打開SDK后,新建application project。在system.mss中可以打開相關參考文檔輔助設計。
參考給出的示例,在main.c中寫入以下代碼:
#include "xparameters.h"
#include "xadcps.h"
#include "stdio.h"
#include "xil_printf.h"
#include "sleep.h"
#define XADC_DEVICE_IDXPAR_XADCPS_0_DEVICE_ID
static XAdcPs XAdc_Inst;
u32 Temp_RawData;
//芯片溫度、最大、最小溫度
float TempData;
float TempmaxData;
float TempminData;
//內核各部分電壓值
float VccPintData;
float VccPauxData;
float VccPdroData;
float VccBramData;
void Xadc_init();
void Xadc_test();
int main(){
//初始化XADC
Xadc_init();
while(1){
Xadc_test();
sleep(2);
}
return 0;
}
void Xadc_init(){
int status;
XAdcPs_Config *ConfigPtr;
ConfigPtr = XAdcPs_LookupConfig(XADC_DEVICE_ID);
XAdcPs_CfgInitialize(&XAdc_Inst, ConfigPtr,ConfigPtr->BaseAddress);
//自測
status = XAdcPs_SelfTest(&XAdc_Inst);
if (status != XST_SUCCESS) {
xil_printf("xadc selftest failed!
");
}
//設置啟動模式
XAdcPs_SetSequencerMode(&XAdc_Inst, XADCPS_SEQ_MODE_SAFE);
}
void Xadc_test(){
Temp_RawData = XAdcPs_GetAdcData(&XAdc_Inst, XADCPS_CH_TEMP);
TempData = XAdcPs_RawToTemperature(Temp_RawData);
Temp_RawData = XAdcPs_GetMinMaxMeasurement(&XAdc_Inst, XADCPS_MAX_TEMP);
TempmaxData = XAdcPs_RawToTemperature(Temp_RawData);
Temp_RawData = XAdcPs_GetMinMaxMeasurement(&XAdc_Inst, XADCPS_MIN_TEMP);
TempminData = XAdcPs_RawToTemperature(Temp_RawData);
Temp_RawData = XAdcPs_GetAdcData(&XAdc_Inst, XADCPS_CH_VCCPINT);
VccPintData = XAdcPs_RawToVoltage(Temp_RawData);
Temp_RawData = XAdcPs_GetAdcData(&XAdc_Inst, XADCPS_CH_VCCPAUX);
VccPauxData = XAdcPs_RawToVoltage(Temp_RawData);
Temp_RawData = XAdcPs_GetAdcData(&XAdc_Inst, XADCPS_CH_VCCPDRO);
VccPdroData = XAdcPs_RawToVoltage(Temp_RawData);
Temp_RawData = XAdcPs_GetAdcData(&XAdc_Inst, XADCPS_CH_VBRAM);
VccBramData = XAdcPs_RawToVoltage(Temp_RawData);
printf("============================
");
printf("Current Temperature:%0.4fC
",TempData);
printf("Maximum Temperature:%0.4fC
",TempmaxData);
printf("Minimum Temperature:%0.4fC
",TempminData);
printf(" VccPSint:%0.4fV
",VccPintData);
printf(" VccPSaux:%0.4fV
",VccPauxData);
printf(" VccPSdro:%0.4fV
",VccPdroData);
printf(" VccPSBram:%0.4fV
",VccBramData);
printf("============================
");
}
整體代碼比較簡單,主要還是使用相關的函數進行開發(fā)設計,這里打印了相關溫度和電壓信息。
運行效果
在SDK的串口終端中正確顯示各個參數信息。
Reference
- UG585
- 正點原子開發(fā)視頻教程
審核編輯 :李倩
?
評論
查看更多