Zynq-Linux移植学习笔记之59-国产ZYNQ XADC使用说明

本文详细介绍了国产ZYNQ FPGA中XADC模块的配置和应用设计。XADC不需要额外的Linux内核驱动,可通过/dev/mem直接访问。在FPGA配置中,建议开启所有通道,特别是8个外部AUX通道。XADC基地址的确定和通道转换公式是关键,应用程序中需要根据实际通道值进行转换。示例代码展示了初始化和读取温度、电压等通道数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、背景介绍

国产ZYNQ XADC位于PL部分,和进口的对应关系如下:

外部的AUX只有8个通道,最终支持8路外部监测。

2、fpga设置

XADC不需要在linux内核中添加驱动,也不需要在设备数中添加节点,只需要知道FPGA中的XADC基地址,在应用程序中通过/dev/mem方式进行读写。

FPGA中建议将所有使用到的通道全部打开,AUX通道设置为0-11

然后确认XADC的基地址

3、应用设计

应用中可以使用一套代码,需要改动的部分包括:

  • XADC基地址

  • 外部AUX通道采集的数据经过电阻分压的转换公式

转换公式一般是将读到的原始数据先除以65536 再进行转换

注意:由于和进口存在区别,程序读到的值为下图右侧XADC的通道值,硬件设计是使用下图左侧XADC的通道值。

 

硬件只提供左侧的通道采样的信息:

应用程序中换算为右侧对应的通道,获取采样值。

举例 通道9就是应用中读到的XADCPS_CH_AUX[2]

除了8个外部通道AUX外,其他通道不需要转换。

使用XADC采样前,需要对XADC进行初始化部分。

参考代码如下:

#ifndef _XADC_CORE_H
#define _XADC_CORE_H

#include "../global/xil_types.h"

#define XADC_BASE_ADDR  				0x83C30000U

#define XADCPS_CH_TEMP					0x200  /**< On Chip Temperature */
#define XADCPS_CH_VCCINT				0x204  /**< VCCINT */
#define XADCPS_CH_VCCAUX				0x208  /**< VCCAUX */
#define XADCPS_CH_VPVN					0x20c  /**< VP/VN Dedicated analog inputs */
#define XADCPS_CH_VREFP					0x210  /**< VREFP */
#define XADCPS_CH_VREFN					0x214  /**< VREFN */
#define XADCPS_CH_VBRAM					0x218  /**< On-chip VBRAM Data Reg, 7 series */

#define XADCPS_CH_SUPPLY_CALIB			0x220 /**< Supply Calib Data Reg */
#define XADCPS_CH_ADC_CALIB				0x224 /**< ADC Offset Channel Reg */
#define XADCPS_CH_GAINERR_CALIB 		0x228 /**< Gain Error Channel Reg  */

#define XADCPS_CH_VCCPINT				0x234 /**< On-chip PS VCCPINT Channel , Zynq */
#define XADCPS_CH_VCCPAUX				0x238 /**< On-chip PS VCCPAUX Channel , Zynq */
#define XADCPS_CH_VCCPMEM				0x23c /**< On-chip PS VCCPMEM Channel , Zynq */

#define XADCPS_CH_AUX_MIN				0x240 /**< Channel number for 1st Aux Channel */
#define XADCPS_CH_AUX_MAX				0x27c /**< Channel number for Last Aux channel */


enum EConvType
{
	EConvType_None,
	EConvType_Raw_to_Scale,
	EConvType_Scale_to_Raw,
	EConvType_Max
};


float conv_temperature(float input, enum EConvType conv_direction);
float conv_voltage(float input, enum EConvType conv_direction);
void xadc_initialization();

#endif

/*
 * xadc_core.c
 *
 *  Created on: 2017年9月20日
 *      Author: Administrator
 */

#define __XADC_CORE_C_

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <ctype.h>
#include <pthread.h>
#include <assert.h>

#include "xadc_core.h"
#include "../global/xil_io.h"


void xadc_initialization()
{
	Xil_Out32(XADC_BASE_ADDR+0x000, 0xA);
	Xil_Out32(XADC_BASE_ADDR+0x010, 0x1);
	Xil_Out32(XADC_BASE_ADDR+0x010, 0x0);
}

//utility functions
float conv_voltage(float input, enum EConvType conv_direction)
{
	float result=0;
	switch(conv_direction)
	{
	case EConvType_Raw_to_Scale:
		result = ((input * 3.0)/65536.0);
		break;
	default:
		break;
	}
	return result;
}


float conv_temperature(float input, enum EConvType conv_direction)
{
	float result=0;

	switch(conv_direction)
	{
	case EConvType_Raw_to_Scale:
		result = ((input / 65536.0)/0.00198421639) - 273.15;
		break;
	default:
		break;
	}
	return result;
}

//transfer float to unsigned char
unsigned char transfer(float temp)
{
	unsigned char result;
	char buff[100];
	int before,end;
	memset(buff,0,sizeof(buff));
	sprintf(buff,"%.2f",temp);
	sscanf(buff,"%d.%d",&before,&end);
	result=(before<<4)|end;
	return result;
}

void printadc()
{
	float raw_data=0;
	float true_data=0;

	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_TEMP);
	//printf("XADCPS_CH_TEMP is %f\n",raw_data);
	true_data=conv_temperature(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_TEMP TRUE DATA is %.2fCent\n",true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCINT);
	//printf("XADCPS_CH_VCCINT is %f\n",raw_data);
	true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_VCCINT TRUE DATA is %.2fV\n",true_data);

	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCAUX);
	//printf("XADCPS_CH_VCCAUX is %f\n",raw_data);
	true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_VCCAUX TRUE DATA is %.2fV\n",true_data);

	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VBRAM);
	//printf("XADCPS_CH_VBRAM is %f\n",raw_data);
	true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_VBRAM TRUE DATA is %.2fV\n",true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCPINT);
	//printf("XADCPS_CH_VCCPINT is %f\n",raw_data);
	true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_VCCPINT TRUE DATA is %.2fV\n",true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCPAUX);
	//printf("XADCPS_CH_VCCPAUX is %f\n",raw_data);
	true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_VCCPAUX TRUE DATA is %.2fV\n",true_data);

	raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCPMEM);
	//printf("XADCPS_CH_VCCPMEM is %f\n",raw_data);
	true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
	printf("XADCPS_CH_VCCPMEM TRUE DATA is %.2fV\n",true_data);


	printf("\n****************AUX DATA****************** \n");

	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN));
	true_data=(raw_data/65536.0)*2.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 1V2 is %.2fV\n",0,true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+1*4));
	true_data=(raw_data/65536.0)*2.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 1V2 is %.2fV\n",1,true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+2*4));
	true_data=raw_data/65536.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 1V0 is %.2fV\n",2,true_data);



	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+3*4));
	true_data=raw_data/65536.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 1V5 is %.2fV\n",2,true_data);



	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+4*4));
	true_data=(raw_data/65536.0*3.0)/2.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 3V3 is %.2fV\n",4,true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+8*4));
	true_data=(raw_data/65536.0*3.0)/2.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 3V3 is %.2fV\n",8,true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+10*4));
	true_data=(raw_data/65536.0*3.0)/2.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 1V2 is %.2fV\n",10,true_data);


	raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+11*4));
	true_data=(raw_data/65536.0)*2.0;  //换算公式
	printf("XADCPS_CH_AUX[%d] 2V5 is %.2fV\n",11,true_data);


	printf("\n************************************** \n");
	printf("\n************************************** \n");
	printf("\n************************************** \n");

}

int main()
{
	xadc_initialization();
	printadc();
	return 0;
}

### 回答1: "Zynq-Linux移植学习笔记"是一篇关于在Zynq SoC平台上移植Linux操作系统的学习笔记。该笔记主要介绍了如何在Zynq平台上搭建交叉编译环境、编译内核、制作根文件系统以及启动Linux系统等方面的知识。通过学习这篇笔记,读者可以了解到如何将Linux操作系统移植Zynq平台上,并且可以通过实践来深入理解相关的知识和技 ### 回答2: Zynq Linux移植是搭建Zynq硬件平台和在该平台上运行Linux系统的过程。它包括了硬件的设计和软件的开发,这有助于实现在Zynq平台上开发Linux应用程序的目标。 首先,进行Zynq Linux移植前需要研究设备的结构和硬件构造。zynq硬件平台包含两个主要组成部分:PS和PL。PS负责处理器系统和外设的管理和控制,PL则是可编程逻辑,支持FPGA逻辑的定制化,同时也支持外设的实现。在移植时,需要设计PS的硬件架构和软件驱动程序,同时也需要配置PL。一般情况下,需要进行如(Xilinx SDK)和(Petalinux)等的软件开发环境安装和配置。 接下来,进行Linux系统的移植。这部分工作需要了解Linux内核的结构、功能和特性,然后根据硬件架构,对Linux系统进行调整和定制,构建出适合硬件平台的Linux系统。这个过程需要进行的工作包括:解编译适合SOC的内核、制定设备树、调整内核参数等。 最后,这些工作完成后,就可以在Zynq平台上编译和运行Linux应用程序了。开发者可以尝试通过开发板上的GPIO、I2C、SPI或UART等接口,学习Linux的设备驱动程序、网络编程、文件系统管理等知识点。可逐步学习如何掌握Linux的shell、打包工具、交叉编译工具等。 总结来说,Zynq Linux移植工作是基础的硬件构造、嵌入式软件和Linux知识的综合应用,需要开发者有至少三方面的技能。需要熟练编写硬件设计,熟练掌握Linux内核编程以及Linux系统软件的维护和管理。这些技能的应用能力对于移植Zynq平台Linux系统和应用程序的开发工程师来说是非常必要的。 ### 回答3: 随着嵌入式系统的广泛应用,zynq-linux移植成为了嵌入式开发的一个重要研究课题。zynq-linux移植涉及到许多方面的知识,在学习过程中需要注意以下几点: 一、zynq-linux移植前需要了解的基础知识 在开始进行zynq-linux移植之前,需要对Linux系统、ARM技术、FPGA开发、C语言等基础知识有一定的了解。同时需要熟悉zynq系列的基本架构和应用场景。 二、zynq-linux移植必要的步骤 zynq-linux移植的过程主要分为以下几个步骤:首先是确定硬件平台和环境搭建;其次是进行内核编译和配置;然后是uboot编译和烧录;最后是Linux文件系统的制作和烧录。在整个移植过程中,需要注意各个步骤的顺序和详细操作,确保每一步都正确完成。 三、zynq-linux移植中可能会遇到的问题 在zynq-linux移植过程中,可能会遇到各种问题,例如硬件平台的兼容性、内核配置的错误、uboot烧录问题、文件系统制作出错等。在遇到这些问题时,需要耐心地进行排查和解决,同时也可以借助搜索引擎和社区的技术支持。 四、zynq-linux移植之后的应用与拓展 zynq-linux移植成功之后,可以将其应用于各种嵌入式系统中,例如网络设备、智能家居、工业控制等领域。同时,还可以进行拓展和优化,例如添加各种驱动程序、优化系统性能等。 总之,在进行zynq-linux移植的学习和实践中,需要认真学习基础知识,仔细操作每个步骤,及时排查并解决问题,并在成功移植之后持续进行应用与拓展。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值