【【FPGA 之 MicroBlaze XADC 实验】】

FPGA 之 MicroBlaze XADC 实验

Vivado IP 核提供了 XADC 软核,XADC 包含两个模数转换器(ADC),一个模拟多路复用器,片上温度和片上电压传感器等。我们可以利用这个模块监测芯片温度和供电电压,也可以用来测量外部的模拟电压信号。

7 系列的 XADC IP 核包括两个 12 位的模数转换器,转换速率可以达到 1MSPS(每秒一百万次采样)。它带有片上温度和电压传感器,可以测量芯片工作时的温度和供电电压。用户可以设置报警阈值,用来检测温度过高或者供电电压异常等事件。除此之外,通过 XADC IP 核内部的模拟多路复用器,它支持最多 17路外部模拟输入信号的测量,且支持单极、双极和差分等信号类型。
XADC内部结构
在这里插入图片描述

左边红框圈 1 的,共十七组差分信号,这些端口也可接收单端信号,其中一对 VP/N_0 为专用的模拟差分输入,其他 16 对为复用的,不使用时可作为普通的管脚。最上边红框 2,表明 XADC 模块也可采集片上传感器测量到的芯片温度、供电电压等信息;右边红框圈 3,是两个 12 位的模数转换器。XADC 采集转换后的数据存储在状态寄存器的专用寄存器内,可由 FPGA 内部动态配置端口(DRP----Dynamic Reconfiguration Port)的 16 位同步读/写端口访问;ADC 的转换数据也可以由 JTAG 访问,当使用这种方式时,并不需要直接去例化 XADC 模块,因为这是一个已经存在与 FPGA JTAG 结构的专用接口,此时因为没有在设计中直接例化 XADC 模块,故 XADC IP 核工作在一种预先定义好的模式即缺省模式,此模式下 XADC IP 核专用于监视芯片上的供电电压和芯片温度。以上是对 XADC IP 核的简介。

看了一圈XADC 没太看懂 但是 不重要 因为我是复制粘贴的 只要了解 大概怎么用的就好了

实验任务 : 本章的实验任务是通过 AXI 接口读取 XADC 测量的芯片温度、供电电压等信息,并通过串口打印出来。

我们研究一下这里的系统框图
在这里插入图片描述

CPU 通过 AXI 接口直接读取 XADC 模块采集的温度和电压数据,然后通过串口打印出来。
在这里插入图片描述

下面展示Block Design
在这里插入图片描述

下面 展示 完整的在 vitis 下的 C语言代码

#include "xsysmon.h"
#include "xparameters.h"
#include "xstatus.h"
#include "stdio.h"
#include "sleep.h"
//XADC ID
#define SYSMON_DEVICE_ID XPAR_SYSMON_0_DEVICE_ID
static XSysMon SysMonInst; //XADC 驱动实例
int SysMonFractionToInt(float FloatNum);
int main(void){
XSysMon_Config *ConfigPtr;
u32 TempRawData; //温度 原始数据
u32 VccAuxRawData; //辅助电压 原始数据
u32 VccIntRawData; //内核电压 原始数据
u32 VccBRAMdata; //BRAM 电压 原始数据
float TempData; //温度
float VccAuxData; //辅助电压
float VccIntData; //内核电压
float VBRAM; //BRAM 电压
float MaxData; //最大值
float MinData; //最小值
//初始化 XADC 器件
ConfigPtr = XSysMon_LookupConfig(SYSMON_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
XSysMon_CfgInitialize(&SysMonInst, ConfigPtr, ConfigPtr->BaseAddress);
//默认安全模式
XSysMon_SetSequencerMode(&SysMonInst, XSM_SEQ_MODE_SAFE);
//使能的相应的通道
XSysMon_SetSeqChEnables(&SysMonInst,XSM_SEQ_CH_TEMP| //温度
XSM_SEQ_CH_VCCINT | //内核电压
XSM_SEQ_CH_VCCAUX| //辅助电压
XSM_SEQ_CH_VBRAM //BRAM 电压
);
//设置为循环模式
XSysMon_SetSequencerMode(&SysMonInst,XSM_SEQ_MODE_CONTINPASS);
while(1){
//读取温度
TempRawData = XSysMon_GetAdcData(&SysMonInst, XSM_CH_TEMP);
TempData = XSysMon_RawToTemperature(TempRawData);
xil_printf("\r\nThe Current Temperature is %0d.%03d Centigrades.\r\n",
(int)(TempData), SysMonFractionToInt(TempData));
//读取最大温度
TempRawData = XSysMon_GetMinMaxMeasurement(&SysMonInst, XSM_MAX_TEMP);
MaxData = XSysMon_RawToTemperature(TempRawData);
xil_printf("The Maximum Temperature is %0d.%03d Centigrades. \r\n",
(int)(MaxData), SysMonFractionToInt(MaxData));
//读取最小温度
TempRawData = XSysMon_GetMinMaxMeasurement(&SysMonInst, XSM_MIN_TEMP);
MinData = XSysMon_RawToTemperature(TempRawData);
xil_printf("The Minimum Temperature is %0d.%03d Centigrades. \r\n",
(int)(MinData), SysMonFractionToInt(MinData));
//读取核心电压
VccIntRawData = XSysMon_GetAdcData(&SysMonInst, XSM_CH_VCCINT);
VccIntData = XSysMon_RawToVoltage(VccIntRawData);
xil_printf("The Current VCCINT is %0d.%03d Volts. \r\n",
(int)(VccIntData), SysMonFractionToInt(VccIntData));
//读取辅助器电
VccAuxRawData = XSysMon_GetAdcData(&SysMonInst,XSM_CH_VCCAUX );
VccAuxData = XSysMon_RawToVoltage(VccAuxRawData);
xil_printf("The Current VCCAUX is %0d.%03d Volts. \r\n",
(int)(VccAuxData), SysMonFractionToInt(VccAuxData));
//读取 BRAM 电压
VccBRAMdata = XSysMon_GetAdcData(&SysMonInst,XSM_CH_VCCAUX );
VBRAM = XSysMon_RawToVoltage(VccBRAMdata);
xil_printf("The Current VBRAM is %0d.%03d Volts. \r\n",
(int)(VBRAM), SysMonFractionToInt(VBRAM));
sleep(1);
}
return 0;
}
int SysMonFractionToInt(float FloatNum)
{
float Temp;
Temp = FloatNum;
if (FloatNum < 0) {
Temp = -(FloatNum);
}
//将浮点数线束部分扩大 1000 倍,以便打印
return( ((int)((Temp -(float)((int)Temp)) * (1000.0f))));
}

下面对C语言代码进行细致的分析
我从完整的c语言开始分析 希望能有所感悟

就当是我们自己在做这个东西
按照惯例 写下我们的头文件
在这里插入图片描述

#include "xparameters.h"
#include "stdio.h"

这是给我们印象最深的两项了
对此我们先搁置 一下
处理下面的事项
在这里插入图片描述

下一步按照惯例设定 XDC的ID 序号 来自 xparameters
在这里插入图片描述

然后我们想我们使用xdc 添加一个xdc驱动实例
它前缀设置了static 静态变量的形式
XSysMon 来自 一个新的.h 文件 头文件内记得加入
在这里插入图片描述

这个结构体的意思是

typedef struct {
XSysMon_Config Config;    /< XSysMon_Config of current device */u32  IsReady;        /< Device is initialized and ready  */
u32  Mask;        /**< Store the previously written value
in CONVST register */
} XSysMon;

驱动程序的实例数据。用户需要分配一个变量
*用于系统中的每个系统监视器/ADC设备。指向的指针
*然后将这种类型的变量传递给驱动程序API函数。
*/

下面一句话是声明函数 我们不看 进入主函数
在这里插入图片描述

我们会发现 其实 这个 XSysMon_Config 是来自于 XSysMon.h的 是 上面显示的结构体的一部分

typedef struct {
u16  DeviceId;        /< Unique ID of device */UINTPTR  BaseAddress;    /< Device base address */
int  IncludeInterrupt;     /< Supports Interrupt driven mode */u8   IpType;        /< 1 - System Management */
/**< 0 - XADC/System Monoitor */
} XSysMon_Config;

接下来进行初始化
在这里插入图片描述

其实真正的初始化是 第35行的这句话
但是我们看看30行这句话
XSysMon_LookupConfig 这个函数 后面带有ID 就是先查找这个XDC ID是否存在 然后它下面马上跟了一句 不存在return 什么 就是这样

OK 我们接下来看35行的函数
XSysMon_CfgInitialize 从名字上我们就可以看出是初始化XDC的意思 具体分析下 用到了什么参数
我们索引进去会得到这样的原函数

int XSysMon_CfgInitialize(XSysMon *InstancePtr, XSysMon_Config *ConfigPtr,UINTPTR EffectiveAddr)

InstancePtr is a pointer to the XSysMon instance. 第一句是指向实例的指针
就是我们在上面定义的 驱动示例
下一句是ConfigPtr指向XSysMon设备配置结构。 指向了我们在主函数定义的结构体
第三句指的是 设备的基地址 正好来自于我们的上一个结构体中的内容

初始化完毕之后 我们设定进入安全模式
在这里插入图片描述

大概懂了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值