[米联客-XILINX-H3_CZ08_7100] FPGA_SDK入门篇连载-04 PS-XADC实验

软件版本:VIVADO2021.1

操作系统:WIN10 64bit

硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA

实验平台:米联客-MLK-H3-CZ08-7100开发板

板卡获取平台:https://milianke.tmall.com/

登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

目录

1 概述

2系统框图

3内置XADC介绍

3.1XADC概述

1:XADC的电源

2:温度传感器

3:电源传感器

4:XADC外部采集接口

3.2XADC的寄存器

1:配置寄存器0(40h)

2:配置寄存器1(41h)

3:配置寄存器2(42h)

4:测试寄存器(43h~47h)

5:通道使能序列寄存器(48h~49h)

6:通道均值序列寄存器(4ah~4bh)

7:通道极性序列寄存器(4ch~4dh)

8:通道采样时间序列寄存器(4eh~4fh)

9:通道报警报警寄存器(50h~5fh)

3.3XADC的工作模式

1:默认工作模式

2:单通道模式

3:单次采集模式

4:自动模式

5:并行模式

6:独立模式

3.4PS访问XADC的方法

1:PS通过PS-XADC接口访问XADC

2:PS通过AXI-XADC IP访问XADC

3.5PL访问XADC的方法

4搭建SOC系统工程

4.1 Zynq IP PS部分设置

1:PS复位设置

2:设置PS GT Master接口

3:设置PL的时钟

4:ZYNQ IP设置完成后

4.2 Zynq IP PS部分设置

1:添加XADC IP

2:添加ILA IP

4.3完成SOC系统搭建

4.4校验BD工程

4.5IP地址分配

4.6导出顶层文件

4.7编译并导出平台文件

5搭建Vitis-sdk工程

5.1创建SDK Platform工程

5.2创建PS内部接口访问XADC的APP工程

5.3创建PS通过AXI-ADC IP访问XADC的APP工程

6程序分析

6.1xadcps_polled_printf_example.c程序分析

6.2xsysmon_polled_printf_example.c程序分析

7方案演示

7.1硬件准备

7.2实验结果


1 概述

XILINX FPGA或者SOC集成了一个XADC模数转换控制器,XADC中包含了2个12bit 1MSPS采样率的ADC-A和ADC-B,这两个ADC通过MUX复用开关,可以访问片上温度、片上各个功能单元的电压、以及外部模拟输入信号。

实验目的:

1:了解XADC的硬件结构

2:了解XADC的寄存器,重点了解配置寄存器以及序列寄存器

3:了解XADC的工作模式

4:了解PS如何访问XADC的方法

5:了解PL访问XADC的方法

6:搭建具有AXI-XADC IP的SOC工程

7:使用SDK自带的XADC测试程序,演示XADC的使用。

2系统框图

3内置XADC介绍

3.1XADC概述

XADC是一个集成在XILINX FPGA或者SOC中的模式转换模块,以及控制器模块。如下图所示,其中包含了2个12bit 1MSPS采样率的ADC-A和ADC-B,这两个ADC通过MUX复用开关,可以访问片上温度、片上各个功能单元的电压、以及外部模拟输入信号。

XADC包含了控制寄存器部分和状态寄存器部分,通过DRP接口可以通过FPGA或者JTAG访问。

XADC的参考电压可以使用外部基准或者使用内部的1.25V基准。如果要获得高精度的采样可以使用外部基准。

1:XADC的电源

XADC的参考电压可以使用外部基准或者使用内部的1.25V基准。如果要获得高精度的采样可以使用外部基准。

为了减少高频影响,可以选择在VCCAUX和XADC的VCCADC之间串接一个磁珠,以及在GND-XADC数字GND之间串接一个磁珠。

2:温度传感器

温度传感器使用以下公式计算温度,温度传感器的结果在状态寄存器 00h 中。

3:电源传感器

XADC 电源传感器可在 3V 输入电压下生成 FFFh 的满量程 ADC 输出代码。 此电压超出允许的比如VCCINT = 1V 生成 1/3 x 4096 = 1365 = 555h 的输出代码。 XADC 监控 VCCINT、VCCAUX 和 VCCBRAM。 测量结果分别存储在状态寄存器 01h、02h 和 06h 中。

对于ZYNQ-7000 SOC 还能监控其他额外的三个电源分别为:VCCPINT、VCCPAUX 和 VCCO_DDR。 这些测量值分别存储在状态寄存器 0Dh、0Eh 和 0Fh 中。

4:XADC外部采集接口

1:共模输入

ADC 的模拟输入使用差分采样方案来降低共模噪声信号的影响。下图显示了差分采样方案的优势,电源的噪声和地上的噪声相互抵消,从而提高采样精度。当采集外部模拟输入信号的时候,只需要把外部模拟信号接入到VP和VN.

2:单端输入解法

外部模拟信号如果是单端信号,可以通过电阻网络实现差分采样方式,如下图所示。R1 、R2通过电阻分压,把10V的电压分压到了1V,这样就在XADC的采样范围内。R5用于阻抗匹配。之后经过一个滤波器进入到ADC的采样P 和N端。

3:XADC无极性输入

当外部采集无极性的输入信号,需要对配置寄存器0设置,来选择工作于无极性模式。VN 上的共模信号可以在 0V 到 +0.5V 之间变化(相对于 GNDADC 测量)。由于差分输入范围为 0V 至 1.0V(VP 至 VN),因此 VP 上的最大信号为 1.5V。

对于12BITADC,无极性的输入范围12’0h~12’hFFF,因此0V对于于12’h0,1V对应于12’hFFF

4:XADC有极性输入

当外部采集有极性的输入信号,需要对配置寄存器0设置,来选择工作于有极性模式。有极性模式下,VP 和VN的电压必须相对于GNDADC是正电压(不能输入负电压,差分信号的正负是相对信号的共模点来说的),VP-VN的最大范围是±0.5V。下图中,VN=0.5V 因此最大的VP输入范围是±0.5V(当对于VN)

对于12BITADC,有极性的输入范围12’800~12’h7FF,因此-0.5V对于于12’h800,+0.5V对应于12’h7FF

5:差分输入

无极性输入的应用也包括采集差分信号,差分输入信号是相对于VCM对称。VCM的范围为0.25V~0.75V

3.2XADC的寄存器

可以看到以上寄存器中分状态寄存器和控制寄存器。状态寄存器比较容易理解主要是保存了ADC采集到的数值,以及ADC的当前工作状态,我们就不做分析了。

对于控制寄存器,关系到我们对XADC的工作模式、采样通道、采样时间等设置,我们重点关注下。

Name

Address

Description

Configuration register 0

40h

XADC配置寄存器0

Configuration register 1

41h

XADC配置寄存器1

Configuration register 2

42h

XADC配置寄存器2

Test registers 0 to 4

43h to 47h

厂家用的测试寄存器

Sequence registers

48h to 4Fh

这些寄存器用于对功能通道序列号进行编程

Alarm registers

50h to 5Fh

这些是 XADC 警报功能的警报阈值寄存器

1:配置寄存器0(40h)

功能

描述

DI0~DI4

CH0 ~ CH4

单通道模式或外部多路复用器模式下工作时,这些位用于选择 ADC 输入通道。

DI8

ACQ

当使用单通道模式时,该位用于将连续采样模式下外部模拟输入上可用的建立时间增加6个ADCCLK 周期。通过将该位设置为逻辑 1 来增加采集时间。

DI9

EC

该位用于选择 ADC 的连续或事件驱动采样模式。 逻辑 1 将 ADC 置于事件驱动采样模式,逻辑 0 将 ADC 置于连续采样模式。

DI10

BU

该位用于单通道模式,为 ADC 模拟输入选择单极或双极工作模式。 逻辑 1 将 ADC 置于双极性模式,逻辑 0 将 ADC 置于单极性模式。

DI11

MUX

该位应设置为逻辑 1 以启用外部多路复用器模式

DI12, DI13

AVG0, AVG1

这些位用于设置在单通道和序列模式下选定通道的平均采样量。

DI15

CAVG

该位用于禁用计算校准系数的平均值。 默认情况下启用平均(逻辑 0)。 要禁用平均,将该位设置为逻辑 1。平均固定为 16 个样本。

表4-3-5-1-1 Averaging Filter Settings

设置采样倍数,通过多次采样求平均提高采样精度,但是会降低ADC的返回值速度。

AVG1~AVG0

描述

2’b00

1倍采样

2’b01

16倍采样

2’b10

64倍采样

2’b11

512倍采样

表4-3-5-1-2ADC Channel Select

XADC通过选通开关,采集不同的传感器值。

CH4~CH0 [4:0]

描述

0

片上温度传感器

1

VCCINT

2

VCCAUX

3

Vp/Vn 模拟输入

4

Vrefp 参考电源输入P

5

Vrefn 参考电源输N

6

VCCBRAM

7

无效

8

执行 XADC 校准

9-12

无效

13

VCCPINT

14

VCCPAUX

15

VCCO_DDR

16

VAUXP[0], VAUXN[0] – Auxiliary channel 0

17

VAUXP[1], VAUXN[1] – Auxiliary channel 1

18-31

VAUXP[2:15], VAUXN[2:15] – Auxiliary channels 2 to 15(2

2:配置寄存器1(41h)

功能

描述

DI0

OT

设置1禁用温度报警。

DI1 to DI3, DI8

ALM0 ~ ALM3

这些位分别用于禁用温度、VCCINT、VCCAUX 和 VCCBRAM 的警报输出。设置1 禁用警报输出。

DI9 to DI11

ALM4 to ALM6

这些位分别用于禁用 VCCPINT、VCCPAUX 和 VCCO_DDR 的各个警报输出。 逻辑 1 禁用警报输出。

DI4 to DI7

CAL0 to CAL3

这些位支持将校准系数应用于 ADC 和片上电源传感器测量。设置1 启用校准,逻辑 0 禁用校准。

DI12 to DI15

SEQ0 to SEQ3

这些位启用通道序列器功能。

表4-3-5-2-1 Averaging Filter Settings

设置ADC的校准使能

CAL0

描述

CAL1

ADC 偏移校正使能

CAL2

ADC 偏移和增益校正使能

CAL3

电源传感器偏移校正使能

CAL4

电源传感器偏移和增益校正使能

表4-3-5-2-2 Sequencer Operation Settings

设置ADC的采样模式启动

SEQ3~SEQ0

描述

4’b0000

默认模式:

在这种工作模式下,XADC 自动监控片上传感器并将结果存储在状态寄存器中。 两个 ADC 均在此模式下进行校准,并对所有传感器16 倍采样求平均值。 XADC 在此模式下独立于任何其他控制寄存器设置运行。 XADC 还在初始上电后和 FPGA 配置期间以默认模式运行。

4’b0001

单次模式:

该模式下,对序列器中使能的通道运行一次后停止,通过写入CH4~CH0可以启动一次转换,或者设置SEQ = 4’b0011 然后再设置SEQ = 4’b0001也可以进行一次转换。

4’b0010

连续采集:

连续模式类似于单次模式, 但是,只要启用该模式,序列就会自动重新启动,每次转换完成后,自动进行下一次转换。

4’b0011

单通道模式(序列器关闭):

在此模式下,必须通过写入控制寄存器 40h 中的位位置 CH4 ~ CH0 来选择模数转换通道。 单通道模式的各种配置,例如模拟输入模式 (BU) 和建立时间 (ACQ),也必须通过写入控制寄存器 40h 来设置。 在需要监控许多通道的应用中,微处理器或其他控制器的开销可能很大。 为了自动执行此任务,提供了一个称为自动通道排序器的功能。

4’b01xx

并行采集模式

4’b10xx

独立ADC模式

4’b11xx

默认模式

3:配置寄存器2(42h)

功能

描述

DI4, DI5

PD0, PD1

XADC 的掉电位。 整个 XADC 模块可以通过设置 PD1 = PD0 = 1 永久断电。ADC B 也可以通过设置 PD1 = 1 和 PD0 = 0 永久断电。

DI8 to DI15

CD0 to CD7

这些位选择 DRP 时钟 (DCLK) 和用于 ADC 的低频 ADC 时钟 (ADCCLK) 之间的分频比(参见第 5 章,XADC 时序)。

表4-3-5-3-1 Power Down Selection

设置电源。

PD1~PD0

描述

2’b00

默认,所以 XADC模式都上电

2’b01

无效

2’b10

ADC_B关电

2’b11

XADC 关电

表4-3-5-3-2 DCLK Division Selection

ADCCLK=DCLK/ Division

CD7

CD6

CD5

CD4

CD3

CD2

CD1

CD0

Division

0

0

0

0

0

0

0

0

2

0

0

0

0

0

0

0

1

2

0

0

0

0

0

0

1

0

2

0

0

0

0

0

0

1

1

3

0

0

0

0

0

1

0

0

4

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

1

1

1

1

1

1

1

0

254

1

1

1

1

1

1

1

1

255

4:测试寄存器(43h~47h)

厂家测试用的寄存器,不用管

5:通道使能序列寄存器(48h~49h)

功能定义在“4.3.7XADC的工作模式中描述”,设置1代表使能。

6:通道均值序列寄存器(4ah~4bh)

序列号定义和寄存器48h,49h一样,设置1为使能均值采样。

7:通道极性序列寄存器(4ch~4dh)

序列号定义和寄存器48h,49h一样,设置1为使能双极性输入。

8:通道采样时间序列寄存器(4eh~4fh)

序列号定义和寄存器48h,49h一样,设置1可以延长到10个ADCCLK,只对外部输入有效。

9:通道报警报警寄存器(50h~5fh)

这些寄存器用于对内部监控通道、温度、VCCINT、VCCAUX 和 VCCBRAM 上的自动警报的警报阈值进行编程。 对于 Zynq-7000 SoC 器件,还使用这些寄存器设置 VCCPINT、VCCPAUX 和 VCCO_DDR 的警报阈值。

3.3XADC的工作模式

先给出XADC各种模式下序列器中的序列情况。

表4-3-7-1默认模式的通道序列:

序列器序号:7系列FPGA/ZYNQ-7000

ADC Channel

address

描述

1

Calibration

08h

ADC-A 和ADC-B的校准寄存器

2

VCCPINT

0dh

VCCPINT 传感器

3

VCCPAUX

0eh

VCCPAUX传感器

4

VCCO_DDR

0fh

VCCO_DDR传感器

2/5

Temp

00h

温度传感器

3/6

VCCINT

01h

VCCINT传感器

4/7

VCCAUX

02h

VCCAUX传感器

5/8

VCCBRAM

06h

VCCBRAM传感器

表4-3-7-2单次模式、单通道模式、自动模式的通道序列寄存器48h:

序列器序号:7系列FPGA/ZYNQ-7000

Bit

ADC Channel

描述

1/1

0

8

XADC 校准

无效

1

9

无效

无效

2

10

无效

无效

3

11

无效

无效

4

12

无效

-/2

5

13

VCCPINT

-/3

6

14

VCCPAUX

-/4

7

15

VCCO_DDR

-2/5

8

0

片上温度传感器

3/6

9

1

VCCINT

4/7

10

2

VCCAUX

5/8

11

3

VP,VN

6/9

12

4

VREFP

7/10

13

5

VREFN

8/11

14

6

VCCBRAM

-

15

7

无效

表4-3-7-3单次模式、单通道模式、自动模式的通道序列寄存器49h:

序列器序号:7系列FPGA/ZYNQ-7000

Bit

ADC Channel

描述

9/12

0

16

VAUXP[0], VAUXN[0] – Auxiliary channel 0

10/13

1

17

VAUXP[1], VAUXN[1] – Auxiliary channel 1

11/14

2

18

VAUXP[2], VAUXN[2] – Auxiliary channel 2

12/15

3

19

VAUXP[3], VAUXN[3] – Auxiliary channel 3

13/16

4

20

VAUXP[4], VAUXN[4] – Auxiliary channel 4

14/17

5

21

VAUXP[5], VAUXN[5] – Auxiliary channel 5

15/18

6

22

VAUXP[6], VAUXN[6] – Auxiliary channel 6

16/19

7

23

VAUXP[7], VAUXN[7] – Auxiliary channel 7

17/20

8

24

VAUXP[8], VAUXN[8] – Auxiliary channel 8

18/21

9

25

VAUXP[9], VAUXN[9] – Auxiliary channel 9

19/22

10

26

VAUXP[10], VAUXN[10] – Auxiliary channel 10

20/23

11

27

VAUXP[11], VAUXN[11] – Auxiliary channel 11

21/24

12

28

VAUXP[12], VAUXN[12] – Auxiliary channel 12

22/26

13

29

VAUXP[13], VAUXN[13] – Auxiliary channel 13

23/27

14

30

VAUXP[14], VAUXN[14] – Auxiliary channel 14

24/28

15

31

VAUXP[15], VAUXN[15] – Auxiliary channel 15

表4-3-7-4并行模式通道序列寄存器49h:

序列器序号

Bit

ADC Channel

描述

0

0

16,24

Auxiliary channel 0 和 Auxiliary channel 8

1

1

17,25

Auxiliary channel 1 和 Auxiliary channel 9

2

2

18,26

Auxiliary channel 2 和 Auxiliary channel 10

3

3

19,27

Auxiliary channel 3 和 Auxiliary channel 11

4

4

20,28

Auxiliary channel 4 和 Auxiliary channel12

5

5

21,29

Auxiliary channel 5和 Auxiliary channel 13

6

6

22,30

Auxiliary channel 6和 Auxiliary channel14

7

7

23,31

Auxiliary channel 7 和 Auxiliary channel 15

x

8

x

未定义

x

9

x

未定义

x

10

x

未定义

x

11

x

未定义

x

12

x

未定义

x

13

x

未定义

x

14

x

未定义

x

15

x

未定义

表4-3-7-5独立模式的通道序列寄存器48h:

序列器序号:7系列FPGA/ZYNQ-7000

Bit

ADC Channel

描述

x

0

8

未定义

x

1

9

未定义

x

2

10

未定义

x

3

11

未定义

x

4

12

未定义

x

5

13

未定义

x

6

14

未定义

x

7

15

未定义

x

8

0

未定义

x

9

1

未定义

x

10

2

未定义

1

11

3

VP,VN

x

12

4

未定义

x

13

5

未定义

x

14

6

未定义

x

15

7

未定义

表4-3-7-6独立模式的通道序列寄存器49h:

序列器序号

Bit

ADC Channel

描述

2

0

16

Auxiliary channel 0

3

1

17

Auxiliary channel 1

4

2

18

Auxiliary channel 2

5

3

19

Auxiliary channel 3

6

4

20

Auxiliary channel 4

7

5

21

Auxiliary channel 5

8

6

22

Auxiliary channel 6

9

7

23

Auxiliary channel 7

10

8

24

Auxiliary channel 8

11

9

25

Auxiliary channel 9

12

10

26

Auxiliary channel 10

13

11

27

Auxiliary channel 11

14

12

28

Auxiliary channel 12

15

13

29

Auxiliary channel 13

16

14

30

Auxiliary channel 14

17

15

31

Auxiliary channel 15

1:默认工作模式

通过将寄存器41h的SEQ3~SEQ0序列位设置为4’b0000 来启用。在这种工作模式下,XADC自动监控片上传感器并将结果存储在状态寄存器中。两个ADC均在此模式下进行校准,并对所有传感器应用16个样本的平均值。 XADC在此模式下独立于任何其他控制寄存器设置运行。XADC还在初始上电后和FPGA配置期间以默认模式运行。

表4-3-7-1默认模式的通道序列

2:单通道模式

通过将配置寄存器41h的SEQ3~SEQ0设置为4’b0011,必须通过写入控制寄存器 40h 中的位位置 CH4 ~ CH0 来选择模数转换通道。单通道模式的各种配置,例如模拟输入模式 (BU) 和建立时间 (ACQ),也必须通过写入控制寄存器 40h 来设置。在需要监控许多通道的应用中,微处理器或其他控制器的开销可能很大。

3:单次采集模式

该模式下,对序列器中使能的通道运行一次后停止,通过写入CH4~CH0可以启动一次转换,或者设置SEQ3~SEQ0 = 4’b0011 然后再设置配置的SEQ3~SEQ0 = 4’b0001也可以进行一次转换。

参考:

表4-3-7-2单次模式、单通道模式、自动模式的通道序列寄存器48h 

表4-3-7-3单次模式、单通道模式、自动模式的通道序列寄存器49h 

4:自动模式

通过将配置寄存器41h的SEQ3~SEQ0序列位设置为4’b0010,连续模式类似于单次模式, 但是,只要启用该模式,序列就会自动重新启动,每次转换完成后,自动进行下一次转换。

参考:

表4-3-7-2单次模式、单通道模式、自动模式的通道序列寄存器48h 

表4-3-7-3单次模式、单通道模式、自动模式的通道序列寄存器49h 

5:并行模式

并行模式下,ADC-A ADC-B同时采样,对于需要2个ADC通道同时采样的外部电路可以使用该模式。

参考:

表4-3-7-4并行模式通道序列寄存器49h 

6:独立模式

独立模式下ADC-A 和ADC-B单独工作。

参考:

表4-3-7-5独立模式的通道序列寄存器48h 

表4-3-7-5独立模式的通道序列寄存器49h

3.4PS访问XADC的方法

XADC是在PL部分,所以必须PL上电后才能工作。PS访问XADC有两种方法,一种是通过PS-XADC功能单元通过串行化的方式访问,另外一种是通过AXI总线接口,挂AXI XADC IP访问,XDAC功能单元。

1:PS通过PS-XADC接口访问XADC

PS中运行的软件可以使用devcfg 寄存器配置接口,实现对XADC的访问。DRP 命令、地址和数据在写入FIFO的同时,返回读回的数据。如下图所示:

2:PS通过AXI-XADC IP访问XADC

DRP 接口是一个并行 16 位双向接口,可以使用 AXI4-Lite 接口通过 LogiCORE IP AXI XADC PL 逻辑连接到 PL 总线主控器,以启用 PS 或 MicroBlaze 处理器来控制 XADC。 IP 内核通过每个 AXI4-Lite 读/写事务接收 16 位数据。

使用PL-AXI的接口访问AXI-DAC提供了更好的灵活性,更好的性能。

如下图所示,对于AXI-XADC IP红色框内的为XADC功能单元,其他部分为AXI-XADC IP的控制逻辑、中断逻辑和AXI-lite接口逻辑。

DRP的控制时序逻辑如下,我们了解下即可。

3.5PL访问XADC的方法

在一些场合不适合使用PS访问XADC的时候,可以通过原语调用XADC,并且获取读取传感器和外置ADC的参数。

在本demo的06_doc路径下下载了xilinx 官方提供的通过PL 访问XADC的方案,以下给出关键的代码

`timescale 1ns / 1ps
module ug480 (
    input DCLK, // Clock input for DRP
    input RESET,
    input [3:0] VAUXP, VAUXN,  // Auxiliary analog channel inputs
    input VP, VN,// Dedicated and Hardwired Analog Input Pair
    
    output reg [15:0] MEASURED_TEMP, MEASURED_VCCINT, 
    output reg [15:0] MEASURED_VCCAUX, MEASURED_VCCBRAM,
    output reg [15:0] MEASURED_AUX0, MEASURED_AUX1, 
    output reg [15:0] MEASURED_AUX2, MEASURED_AUX3,

    output wire [7:0] ALM,
    output wire [4:0]  CHANNEL,       
    output wire        OT,
    output wire        EOC,
    output wire        EOS
    );     

    wire busy;
    wire [5:0] channel;
    wire drdy;
    wire eoc;
    wire eos;
    wire i2c_sclk_in;
    wire i2c_sclk_ts;
    wire i2c_sda_in;
    wire i2c_sda_ts;
    
    
    reg [6:0] daddr;
    reg [15:0] di_drp;
    wire [15:0] do_drp;
    wire [15:0] vauxp_active;
    wire [15:0] vauxn_active;
    wire dclk_bufg;

    reg [1:0]  den_reg;
    reg [1:0]  dwe_reg;
    
    reg [7:0]   state = init_read;
    parameter       init_read       = 8'h00,
                    read_waitdrdy   = 8'h01,
                    write_waitdrdy  = 8'h03,
                    read_reg00      = 8'h04,
                    reg00_waitdrdy  = 8'h05,
                    read_reg01      = 8'h06,
                    reg01_waitdrdy  = 8'h07,
                    read_reg02      = 8'h08,
                    reg02_waitdrdy  = 8'h09,
                    read_reg06      = 8'h0a,
                    reg06_waitdrdy  = 8'h0b,
                    read_reg10      = 8'h0c,
                    reg10_waitdrdy  = 8'h0d,
                    read_reg11      = 8'h0e,
                    reg11_waitdrdy  = 8'h0f,
                    read_reg12      = 8'h10,
                    reg12_waitdrdy  = 8'h11,
                    read_reg13      = 8'h12,
                    reg13_waitdrdy  = 8'h13;
    
   BUFG i_bufg (.I(DCLK), .O(dclk_bufg));
   always @(posedge dclk_bufg)
      if (RESET) begin
         state   <= init_read;
         den_reg <= 2'h0;
         dwe_reg <= 2'h0;
         di_drp  <= 16'h0000;
      end
      else
         case (state)
         init_read : begin
            daddr <= 7'h40;
            den_reg <= 2'h2; // performing read
            if (busy == 0 ) state <= read_waitdrdy;
            end
         read_waitdrdy : 
            if (eos ==1)   begin
               di_drp <= do_drp  & 16'h03_FF; //Clearing AVG bits for Configreg0
               daddr <= 7'h40;
               den_reg <= 2'h2;
               dwe_reg <= 2'h2; // performing write
               state <= write_waitdrdy;
            end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;
               state <= state;                
            end
         write_waitdrdy : 
            if (drdy ==1) begin
               state <= read_reg00;
               end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg00 : begin
            daddr   <= 7'h00;
            den_reg <= 2'h2; // performing read
            if (eos == 1) state   <=reg00_waitdrdy;
            end
         reg00_waitdrdy : 
            if (drdy ==1)     begin
               MEASURED_TEMP <= do_drp; 
               state <=read_reg01;
               end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg01 : begin
            daddr   <= 7'h01;
            den_reg <= 2'h2; // performing read
            state   <=reg01_waitdrdy;
            end
            reg01_waitdrdy : 
           if (drdy ==1)   begin
               MEASURED_VCCINT = do_drp; 
               state <=read_reg02;
               end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg02 : begin
            daddr   <= 7'h02;
            den_reg <= 2'h2; // performing read
            state   <=reg02_waitdrdy;
            end
         reg02_waitdrdy : 
            if (drdy ==1)     begin
               MEASURED_VCCAUX <= do_drp; 
               state <=read_reg06;
               end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg06 : begin
            daddr   <= 7'h06;
            den_reg <= 2'h2; // performing read
            state   <=reg06_waitdrdy;
            end
         reg06_waitdrdy : 
            if (drdy ==1)     begin
               MEASURED_VCCBRAM <= do_drp; 
               state <= read_reg10;
            end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg10 : begin
               daddr   <= 7'h10;
               den_reg <= 2'h2; // performing read
               state   <= reg10_waitdrdy;
            end
         reg10_waitdrdy : 
            if (drdy ==1)     begin
               MEASURED_AUX0 <= do_drp; 
               state <= read_reg11;
            end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg11 : begin
            daddr   <= 7'h11;
            den_reg <= 2'h2; // performing read
            state   <= reg11_waitdrdy;
            end
         reg11_waitdrdy : 
            if (drdy ==1)     begin
               MEASURED_AUX1 <= do_drp; 
               state <= read_reg12;
               end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg12 : begin
            daddr   <= 7'h12;
            den_reg <= 2'h2; // performing read
            state   <= reg12_waitdrdy;
            end
         reg12_waitdrdy : 
            if (drdy ==1)     begin
               MEASURED_AUX2 <= do_drp; 
               state <= read_reg13;
               end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         read_reg13 : begin
            daddr   <= 7'h13;
            den_reg <= 2'h2; // performing read
            state   <= reg13_waitdrdy;
            end
         reg13_waitdrdy :
            if (drdy ==1)     begin
               MEASURED_AUX3 <= do_drp; 
               state <=read_reg00;
               daddr   <= 7'h00;
            end
            else begin
               den_reg <= { 1'b0, den_reg[1] } ;
               dwe_reg <= { 1'b0, dwe_reg[1] } ;      
               state <= state;          
            end
         default : begin
            daddr <= 7'h40;
            den_reg <= 2'h2; // performing read
            state <= init_read;
            end
         endcase

XADC #(// Initializing the XADC Control Registers
    .INIT_40(16'h9000),// averaging of 16 selected for external channels
    .INIT_41(16'h2ef0),// Continuous Seq Mode, Disable unused ALMs, Enable calibration
    .INIT_42(16'h0400),// Set DCLK divides
    .INIT_48(16'h4701),// CHSEL1 - enable Temp VCCINT, VCCAUX, VCCBRAM, and calibration
    .INIT_49(16'h000f),// CHSEL2 - enable aux analog channels 0 - 3
    .INIT_4A(16'h0000),// SEQAVG1 disabled
    .INIT_4B(16'h0000),// SEQAVG2 disabled
    .INIT_4C(16'h0000),// SEQINMODE0 
    .INIT_4D(16'h0000),// SEQINMODE1
    .INIT_4E(16'h0000),// SEQACQ0
    .INIT_4F(16'h0000),// SEQACQ1
    .INIT_50(16'hb5ed),// Temp upper alarm trigger 85�C
    .INIT_51(16'h5999),// Vccint upper alarm limit 1.05V
    .INIT_52(16'hA147),// Vccaux upper alarm limit 1.89V
    .INIT_53(16'hdddd),// OT upper alarm limit 125�C - see Thermal Management
    .INIT_54(16'ha93a),// Temp lower alarm reset 60�C
    .INIT_55(16'h5111),// Vccint lower alarm limit 0.95V
    .INIT_56(16'h91Eb),// Vccaux lower alarm limit 1.71V
    .INIT_57(16'hae4e),// OT lower alarm reset 70�C - see Thermal Management
    .INIT_58(16'h5999),// VCCBRAM upper alarm limit 1.05V
    .SIM_MONITOR_FILE("design.txt")// Analog Stimulus file for simulation
)
XADC_INST (// Connect up instance IO. See UG480 for port descriptions
    .CONVST (1'b0),// not used
    .CONVSTCLK  (1'b0), // not used
    .DADDR  (daddr),
    .DCLK   (dclk_bufg),
    .DEN    (den_reg[0]),
    .DI     (di_drp),
    .DWE    (dwe_reg[0]),
    .RESET  (RESET),
    .VAUXN  (vauxn_active ),
    .VAUXP  (vauxp_active ),
    .ALM    (ALM),
    .BUSY   (busy),
    .CHANNEL(CHANNEL),
    .DO     (do_drp),
    .DRDY   (drdy),
    .EOC    (eoc),
    .EOS    (eos),
    .JTAGBUSY   (),// not used
    .JTAGLOCKED (),// not used
    .JTAGMODIFIED   (),// not used
    .OT     (OT),
    .MUXADDR    (),// not used
    .VP     (VP),
    .VN     (VN)
);

    assign vauxp_active = {12'h000, VAUXP[3:0]};
    assign vauxn_active = {12'h000, VAUXN[3:0]};

    assign EOC = eoc;
    assign EOS = eos;

endmodule

仿真参数文件design.txt

TIME VAUXP[0] VAUXN[0] VAUXP[1] VAUXN[1] VAUXP[2] VAUXN[2] VAUXP[3] VAUXN[3] TEMP VCCINT VCCAUX VCCBRAM
00000   0.005   0.0     0.2     0.0      0.5     0.0       0.1     0.0     25   1.0     1.8     1.0    
67000   0.020   0.0     0.400   0.0      0.49    0.0       0.2     0.0     85   1.05   1.9    1.05
100000   0.049   0.0     0.600   0.0      0.51    0.0       0.5     0.0     105   0.95    1.71    0.95 
134000  0.034   0.0     0.900   0.0      0.53    0.0       0.0     0.0     0   1.00    1.8     1.0   

仿真tb文件

`timescale 1ns / 1ps
module ug480_tb;
    reg [3:0]      VAUXP, VAUXN;
    reg             RESET;
    reg             DCLK;

    wire [15:0]     MEASURED_TEMP, MEASURED_VCCINT, MEASURED_VCCAUX; 
    wire [15:0]     MEASURED_VCCBRAM, MEASURED_AUX0, MEASURED_AUX1; 
    wire [15:0]     MEASURED_AUX2, MEASURED_AUX3;
    wire [15:0]     ALM;

initial 
    begin 
                DCLK = 0;
                RESET = 0;
    end

always #(10) DCLK= ~DCLK;

    
// Instantiate the Unit Under Test (UUT)
ug480 uut (
    .VAUXP  (VAUXP),
    .VAUXN  (VAUXN),
    .RESET  (RESET),
    .ALM  (ALM),
    .DCLK   (DCLK),

    .MEASURED_TEMP    (MEASURED_TEMP), 
    .MEASURED_VCCINT  (MEASURED_VCCINT), 
    .MEASURED_VCCAUX  (MEASURED_VCCAUX),
    .MEASURED_VCCBRAM (MEASURED_VCCBRAM),
    .MEASURED_AUX0    (MEASURED_AUX0),
    .MEASURED_AUX1    (MEASURED_AUX1),
    .MEASURED_AUX2    (MEASURED_AUX2),
    .MEASURED_AUX3    (MEASURED_AUX3)
);

endmodule

4搭建SOC系统工程

详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。

4.1 Zynq IP PS部分设置

本文中的PS设置内容是新增加的配置部分,关于DDR、MIO、CPU时钟等设置请参考“01Vitis Soc开发入门”这篇文章。

1:PS复位设置

2:设置PS GT Master接口

3:设置PL的时钟

勾选FCLK_CLK0,设置为100,即PS的PLL提供本系统的时钟100MHZ。

4:ZYNQ IP设置完成后

4.2 Zynq IP PS部分设置

本文需要演示如何使用AXI-XADC,所以才需要添加这个IP,如果只是使用PS内部接口访问XADC就不需要添加这个IP

1:添加XADC IP

双击IP设置,这里设置AXI4Lite接口,访问方式为连续访问模式、复用开关,通道的选择为顺序选择,DRP时钟为100M,ADC的采样率为1MSPS等

采样模式为连续采样,采用ADC和传感器的偏移和增益校准都开启,使能均值校准。

以下设置报警的参数范围包括温度报警和电压报警

以下使能需要使用到的通道数

2:添加ILA IP

为了可以观察AXI-XADC报警时候输出的信号,添加ILA 在线逻辑分析仪IP

             

双击ILA IP设置,设置完成后如下:

4.3完成SOC系统搭建

4.4校验BD工程

4.5IP地址分配

4.6导出顶层文件

4.7编译并导出平台文件

1:生成Bit文件。

2:导出到硬件: FileàExport HardwareàInclude bitstream

3:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。

5搭建Vitis-sdk工程

创建soc_base sdk platform和APP工程,由于本实验更新了FPGA的代码,所以如果是复制之前做好的工程,需要删除soc_sdk中的全部文件,然后重新创建soc_base和APP工程。

5.1创建SDK Platform工程

创捷soc_base的过程不再重复

5.2创建PS内部接口访问XADC的APP工程

使用自带的xadcps_polled_printf_example作为测试代码

右击工程完成编译

5.3创建PS通过AXI-ADC IP访问XADC的APP工程

右击编译

6程序分析

6.1xadcps_polled_printf_example.c程序分析

如果需要设置使能序列寄存器,首先需要设置工作模式为默认模式。该程序演示了默认序列模式的使用,流程如下:

本程序代码中采用默认工作模式实现对温度传感器、电压传感器的采集,所以不需要进一步设置序列寄存器。

代码注释分析:

int XAdcPolledPrintfExample(u16 XAdcDeviceId)
{
	int Status;
	XAdcPs_Config *ConfigPtr;
	u32 TempRawData;
	u32 VccPintRawData;
	u32 VccPauxRawData;
	u32 VccPdroRawData;
	float TempData;
	float VccPintData;
	float VccPauxData;
	float MaxData;
	float MinData;
	XAdcPs *XAdcInstPtr = &XAdcInst;

	printf("\r\nEntering the XAdc Polled Example. \r\n");
	/*
	 * Initialize the XAdc driver.
	 */
	ConfigPtr = XAdcPs_LookupConfig(XAdcDeviceId);
	if (ConfigPtr == NULL) {
		return XST_FAILURE;
	}
	XAdcPs_CfgInitialize(XAdcInstPtr, ConfigPtr,
				ConfigPtr->BaseAddress);
	/*
	 * Self Test the XADC/ADC device
	 */
	Status = XAdcPs_SelfTest(XAdcInstPtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * 设置XADC配置寄存器41h,设置XADC工作于默认模式
	 */
	XAdcPs_SetSequencerMode(XAdcInstPtr, XADCPS_SEQ_MODE_SAFE);
	/*
	 * 以下读取XADC的ADC寄存器
	 */
	TempRawData = XAdcPs_GetAdcData(XAdcInstPtr, XADCPS_CH_TEMP); //读取温度传感器寄存器 
	TempData = XAdcPs_RawToTemperature(TempRawData); //计算温度
	printf("\r\nThe Current Temperature is %0d.%03d Centigrades.\r\n",(int)(TempData), XAdcFractionToInt(TempData));

	TempRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MAX_TEMP); //读取温度传感器的最大值寄存器
	MaxData = XAdcPs_RawToTemperature(TempRawData); //计算温度
	printf("The Maximum Temperature is %0d.%03d Centigrades. \r\n", (int)(MaxData), XAdcFractionToInt(MaxData));

	TempRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MIN_TEMP); //读取温度传感器的最小值寄存器
	MinData = XAdcPs_RawToTemperature(TempRawData & 0xFFF0); //计算温度
	printf("The Minimum Temperature is %0d.%03d Centigrades. \r\n", (int)(MinData), XAdcFractionToInt(MinData));

	/*
	 *读取温度(当前温度、最大温度、最小温度)
	 */
	VccPintRawData = XAdcPs_GetAdcData(XAdcInstPtr, XADCPS_CH_VCCPINT); // 读取VccPint寄存器
	VccPintData = XAdcPs_RawToVoltage(VccPintRawData); //计算电压
	printf("\r\nThe Current VCCPINT is %0d.%03d Volts. \r\n", (int)(VccPintData), XAdcFractionToInt(VccPintData));

	VccPintRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MAX_VCCPINT); //读取VccPint最大值寄存器				MaxData = XAdcPs_RawToVoltage(VccPintRawData); //计算电压
	printf("The Maximum VCCPINT is %0d.%03d Volts. \r\n", (int)(MaxData), XAdcFractionToInt(MaxData));

	VccPintRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MIN_VCCPINT); //读取VccPint最小值寄存器
	MinData = XAdcPs_RawToVoltage(VccPintRawData); //计算电压
	printf("The Minimum VCCPINT is %0d.%03d Volts. \r\n", (int)(MinData), XAdcFractionToInt(MinData));

	/*
	 *读取VCCPAUX电压(当前电压、最大电压、最小电压)
	 */
	VccPauxRawData = XAdcPs_GetAdcData(XAdcInstPtr, XADCPS_CH_VCCPAUX); //读取VccPaux寄存器
	VccPauxData = XAdcPs_RawToVoltage(VccPauxRawData); //计算电压
	printf("\r\nThe Current VCCPAUX is %0d.%03d Volts. \r\n", (int)(VccPauxData), XAdcFractionToInt(VccPauxData));

	VccPauxRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MAX_VCCPAUX); //读取VccPaux最大值寄存器
	MaxData = XAdcPs_RawToVoltage(VccPauxRawData); //计算电压
	printf("The Maximum VCCPAUX is %0d.%03d Volts. \r\n", (int)(MaxData), XAdcFractionToInt(MaxData));

	VccPauxRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MIN_VCCPAUX); //VccPaux 最小值寄存器2Dh			
	MinData = XAdcPs_RawToVoltage(VccPauxRawData); //计算电压
	printf("The Minimum VCCPAUX is %0d.%03d Volts. \r\n\r\n",(int)(MinData), XAdcFractionToInt(MinData));

	/*
	 *读取VCCPDRO电压(当前电压、最大电压、最小电压)
	 */
	VccPdroRawData = XAdcPs_GetAdcData(XAdcInstPtr, XADCPS_CH_VCCPDRO); //读取VccPdro寄存器
	VccPintData = XAdcPs_RawToVoltage(VccPdroRawData); //计算电压
	printf("\r\nThe Current VCCPDDRO is %0d.%03d Volts. \r\n", (int)(VccPintData), XAdcFractionToInt(VccPintData));

	VccPdroRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr,XADCPS_MAX_VCCPDRO); 读取VccPdro最大值寄存器
	MaxData = XAdcPs_RawToVoltage(VccPdroRawData); //计算电压
	printf("The Maximum VCCPDDRO is %0d.%03d Volts. \r\n", (int)(MaxData), XAdcFractionToInt(MaxData));

	VccPdroRawData = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MIN_VCCPDRO); //VccPDR0 最小值寄存器
							
	MinData = XAdcPs_RawToVoltage(VccPdroRawData); //计算电压
	printf("The Minimum VCCPDDRO is %0d.%03d Volts. \r\n", (int)(MinData), XAdcFractionToInt(MinData));

	printf("Exiting the XAdc Polled Example. \r\n");

	return XST_SUCCESS;
}

关键的几个函数功能说明:

XAdcPs_SetSequencerMode函数会设置XADC的配置寄存器41h中的工作模式SEQ3~SEQ0为默认工作模式

XAdcPs_GetAdcData函数读取XADC状态寄存器中的当前值

XAdcPs_GetMinMaxMeasurement函数读取XADC最大值或者最小值

6.2xsysmon_polled_printf_example.c程序分析

如果需要设置序列寄存器,首先需要设置序列模式为默认模式,之后再设置其他的采样时间序列寄存器、均值序列寄存器、有无极性序列寄存器、使能通道选择序列寄存器、配置寄存器中配置ADC分频时钟、配置寄存器中设置校准使能,最后再次设置工作模式为连续采集模式。

本程序代码中需要对温度、VCCINT、VCCAUX、外部通道AUX0以及AXU15采集。外部通道的AUX0需要设置为有极性模式、ADC采用16倍均值采样、使能校准功能,采用连续采集模式。ADC工作时钟为系统时钟的32分频。

代码注释分析:

int SysMonPolledPrintfExample(u16 SysMonDeviceId)
{
	int Status;
	XSysMon_Config *ConfigPtr;
	u32 TempRawData;
	u32 VccAuxRawData;
	u32 VccIntRawData;
	float TempData;
	float VccAuxData;
	float VccIntData;
	float MaxData;
	float MinData;
	XSysMon *SysMonInstPtr = &SysMonInst;

	printf("\r\nEntering the SysMon Polled Example. \r\n");

	/*
	 * Initialize the SysMon driver.
	 */
	ConfigPtr = XSysMon_LookupConfig(SysMonDeviceId);
	if (ConfigPtr == NULL) {
		return XST_FAILURE;
	}
	XSysMon_CfgInitialize(SysMonInstPtr, ConfigPtr,
				ConfigPtr->BaseAddress);

	/*
	 * Self Test the System Monitor/ADC device
	 */
	Status = XSysMon_SelfTest(SysMonInstPtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * 设置XADC控制寄存器1通道的序列模式是默认模式
	 */
	XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_SAFE);


	/*
	 * 设置XADC控制寄存器1所有的报警为0.
	 */
	XSysMon_SetAlarmEnables(SysMonInstPtr, 0x0);


	/*
	 * XADC控制寄存器0采用16倍采样
	 * 
	 */
	XSysMon_SetAvg(SysMonInstPtr, XSM_AVG_16_SAMPLES);

	/*
	 * Setup the Sequence register for 1st Auxiliary channel
	 * Setting is:
	 *	- Add acquisition time by 6 ADCCLK cycles.
	 *	- Bipolar Mode
	 *
	 * Setup the Sequence register for 16th Auxiliary channel
	 * Setting is:
	 *	- Add acquisition time by 6 ADCCLK cycles.
	 *	- Unipolar Mode
	 */
	Status = XSysMon_SetSeqInputMode(SysMonInstPtr, XSM_SEQ_CH_AUX00); //设置外部通道0为有极性通道,默认其他通道都是无极性
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	Status = XSysMon_SetSeqAcqTime(SysMonInstPtr, XSM_SEQ_CH_AUX15 | XSM_SEQ_CH_AUX00);//设置外部通道0和外部通道15的采样时间,6个ADCCLK(根据技术手册说明这里最大是10个ADCCLK,至于为什么是6个ADCCLK,我还是有疑问) 
						
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Enable the averaging on the following channels in the Sequencer
	 * registers:
	 * 	- On-chip Temperature, VCCINT/VCCAUX  supply sensors
	 * 	- 1st/16th Auxiliary Channels
	  *	- Calibration Channel
	 */
	Status =  XSysMon_SetSeqAvgEnables(SysMonInstPtr, //使能均值序列寄存器的通道
XSM_SEQ_CH_TEMP   | //使能温度传感器的均值采样功能  
						XSM_SEQ_CH_VCCINT | //使能VCCIN传感器的均值采样功能
						XSM_SEQ_CH_VCCAUX | //使能VCCAUX传感器的均值采样功能
						XSM_SEQ_CH_AUX00  | //使能VUX00外部通道的均值采样功能
						XSM_SEQ_CH_AUX15  | //使能VUX15外部通道的均值采样功能
						XSM_SEQ_CH_CALIB);  //使能校准传感器的均值采样功能
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Enable the following channels in the Sequencer registers:
	 * 	- On-chip Temperature, VCCINT/VCCAUX supply sensors
	 * 	- 1st/16th Auxiliary Channel
	 *	- Calibration Channel
	 */
	Status =  XSysMon_SetSeqChEnables(SysMonInstPtr, //使能传感器的序列通道位
XSM_SEQ_CH_TEMP   | //使能序列寄存器的温度传感器采样通道
						XSM_SEQ_CH_VCCINT | //使能序列寄存器的VCCINT传感器采样通道
						XSM_SEQ_CH_VCCAUX | //使能序列寄存器的VCCAUX传感器采样通道
						XSM_SEQ_CH_AUX00  | //使能序列寄存器的外部VCCAUX00采样通道
						XSM_SEQ_CH_AUX15  | //使能序列寄存器的外部VCCAUX15采样通道
						XSM_SEQ_CH_CALIB);  //使能序列寄存器的校准通道
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Set the ADCCLK frequency equal to 1/32 of System clock for the System
	 * Monitor/ADC in the Configuration Register 2.
	 */
	XSysMon_SetAdcClkDivisor(SysMonInstPtr, 32); //设置ADC时钟分频

	/*
	 * Set the Calibration enables.
	 */
	XSysMon_SetCalibEnables(SysMonInstPtr, //校准使能
				XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK |
				XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK);

	/*
	 * 设置配置寄存器连续采样
	 */
	XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_CONTINPASS); 

	/*
	 * 等待采集完成
	 */
	XSysMon_GetStatus(SysMonInstPtr); /* Clear the old status */
	while ((XSysMon_GetStatus(SysMonInstPtr) & XSM_SR_EOS_MASK) !=
			XSM_SR_EOS_MASK); 

	/*
	 * 读取温度(当前温度、最大温度、最小温度)
	 */
	TempRawData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_TEMP); //读取温度状态寄存器
	TempData = XSysMon_RawToTemperature(TempRawData); //计算温度
	printf("\r\nThe Current Temperature is %0d.%03d Centigrades.\r\n", (int)(TempData), SysMonFractionToInt(TempData));


	TempRawData = XSysMon_GetMinMaxMeasurement(SysMonInstPtr, XSM_MAX_TEMP); //读取温度传感器的最大值寄存器
	MaxData = XSysMon_RawToTemperature(TempRawData); //计算温度
	printf("The Maximum Temperature is %0d.%03d Centigrades. \r\n", (int)(MaxData), SysMonFractionToInt(MaxData));

	TempRawData = XSysMon_GetMinMaxMeasurement(SysMonInstPtr, XSM_MIN_TEMP); //读取温度传感器的最小值寄存器
	MinData = XSysMon_RawToTemperature(TempRawData); //计算温度
	printf("The Minimum Temperature is %0d.%03d Centigrades. \r\n", (int)(MinData), SysMonFractionToInt(MinData));

	/*
	 *读取VCCINT电压(当前电压、最大电压、最小电压)
	 */
	VccIntRawData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_VCCINT); //读取VCCINT状态寄存器
	VccIntData = XSysMon_RawToVoltage(VccIntRawData); //计算电压
	printf("\r\nThe Current VCCINT is %0d.%03d Volts. \r\n", (int)(VccIntData), SysMonFractionToInt(VccIntData));

	VccIntRawData = XSysMon_GetMinMaxMeasurement(SysMonInstPtr, XSM_MAX_VCCINT); //读取VCCINT最大值寄存器
	MaxData = XSysMon_RawToVoltage(VccIntRawData); //计算电压
	printf("The Maximum VCCINT is %0d.%03d Volts. \r\n", (int)(MaxData), SysMonFractionToInt(MaxData));

	VccIntRawData = XSysMon_GetMinMaxMeasurement(SysMonInstPtr, XSM_MIN_VCCINT); //读取VCCINT最小值寄存器
	MinData = XSysMon_RawToVoltage(VccIntRawData); //计算电压
	printf("The Minimum VCCINT is %0d.%03d Volts. \r\n", (int)(MinData), SysMonFractionToInt(MinData));

	/*
	 *读取VCCAUX电压(当前电压、最大电压、最小电压)
	 */
	VccAuxRawData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_VCCAUX); //读取VCCAUX寄存器 
	VccAuxData = XSysMon_RawToVoltage(VccAuxRawData); //计算电压
	printf("\r\nThe Current VCCAUX is %0d.%03d Volts. \r\n", (int)(VccAuxData), SysMonFractionToInt(VccAuxData));

	VccAuxRawData = XSysMon_GetMinMaxMeasurement(SysMonInstPtr, XSM_MAX_VCCAUX); //读取VCCAUX最大值状态寄存器
	MaxData = XSysMon_RawToVoltage(VccAuxRawData); //计算电压
	printf("The Maximum VCCAUX is %0d.%03d Volts. \r\n", (int)(MaxData), SysMonFractionToInt(MaxData));

	VccAuxRawData = XSysMon_GetMinMaxMeasurement(SysMonInstPtr, XSM_MIN_VCCAUX); //读取最大值最小值状态寄存器			
	MinData = XSysMon_RawToVoltage(VccAuxRawData); //计算电压
	printf("The Minimum VCCAUX is %0d.%03d Volts. \r\n\r\n", (int)(MinData), SysMonFractionToInt(MinData));

	printf("Exiting the SysMon Polled Example. \r\n");

	return XST_SUCCESS;
}

关键的几个函数功能说明:

XSysMon_SetSequencerMode函数会设置XADC的配置寄存器41h中的工作模式SEQ3~SEQ0为默认工作模式,设置默认模式后才能对其他的序列寄存器以及配置寄存器的相应使能位或者功能参数进行重新设置

XSysMon_SetAlarmEnables函数用于设置XADC配置寄存器41h的报警使能位

XSysMon_SetAvg设置配置XADC寄存器42h中的均值采样倍数

XSysMon_SetSeqInputMode设置极性序列寄存器相关通道是否为有极性输入,或者无极性输入(默认)

XSysMon_SetSeqAcqTime设置采样时间序列寄存器相关通道的采样时间的增加

XSysMon_SetSeqAvgEnables 设置均值采样序列寄存器的相关通道使能

XSysMon_SetSeqChEnables 设置序列寄存器的相关通道使能,这个设置是能后,才能启用序列寄存器功能

XSysMon_SetAdcClkDivisor 设置ADC相对于系统时钟的分频系数

XSysMon_SetCalibEnables 设置使能校准功能

XSysMon_SetSequencerMode 重新设置工作模式,本程序中设置为连续工作模式,并且启动XADC工作于连续模式下

XSysMon_GetStatus 读取状态寄存器以确认采集转换是否完成

XSysMon_GetAdcData函数读取XADC状态寄存器中的当前值

XSysMon_GetMinMaxMeasurement t函数读取XADC最大值或者最小值

7方案演示

7.1硬件准备

本实验需要用到 JTAG 下载器、USB 转串口外设,另外需要核心板上的 2P 模式开关设置到 JTAG 模式,即 ON ON(注意新版本的 MLK_H3_CZ08-7100-MZ7100FC),支持 JTAG 模式,对于老版本的核心板,JTAG 调试的时候 一定要拔掉 TF 卡,并且设置模式开关为 OFF OFF)

7.2实验结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值