AURIX TC2XX 学习笔记(6) 通用模数转换器(VADC)

AURIX TC2XX 学习笔记(6) 通用模数转换器(VADC)

通用模数转换器(VADC)是一种高精度、高灵活性的模拟到数字转换模块,它能够将模拟信号转换为数字值,供MCU进一步处理。TC27x提供了一系列的模拟输入通道,连接到一个模拟/数字转换器簇,使用连续近似寄存器(SAR)原理,将模拟输入值(电压)转换为离散的数字值。
TC27x的通用模数转换模块(VADC)包括一组转换器块,它们可以独立地操作或通过模拟后台转换器的公共请求源进行操作。每个转换器块都配备了一个专用的输入多路复用器和专用的请求源,它们一起构建单独的组,每个组被分配给一个内核。

1. ADC kernel 硬件转换单元结构

VADC模块的系统框图如下图所示,
在这里插入图片描述
外部连接主要有以下部分:
Analog reference voltage VAREF:ADC参考电压,也是ADC的量程;
Analog reference ground VAGND:ADC参考基准地;
Analog input channels CHx:ADC模拟电压输入引脚;
Ext. multiplexer control MUX:多路复用控制器,用于控制ADC输入通道的外部多路复用器,允许选择不同的模拟信号源,一般很少使用。
内部主要有以下模块:
AD Converter:AD转换器,主要负责逐次逼近转换的实现;
Conversion Control:转换控制器,主要负责转换模式的设置,例如采样时间,ADC分辨率等;
Interrupt Generation:中断发生单元,主要用于向IR模块产生中断信号;
Result Handling:结果处理器,可以对转换结果进行一系列处理,例如数据压缩,滤波,构建FIFO结构等;
Request Control:请求控制器,主要负责处理转换请求,仲裁等;

1.1转换模式和请求源

ADC转换可以由多个请求源(2组请求源和后台请求源)进行请求,并且可以在几种转换模式中执行,请求源可以与可配置的优先级同时启用。
1.固定通道转换(单个或连续):特定通道源请求一个可选择通道的转换(一次或重复)
2.自动扫描转换(单个或连续):通道扫描源(请求源1或2)请求所有可用通道的可配置线性序列的自动扫描转换(一次或重复)
3.通道序列转换(单个或连续):排队的通道源(请求源0)请求最多8个任意可选择通道(一次或重复)的转换序列

1.2请求源控制

因为所有请求源都可以同时启用,所以仲裁器可以解析来自不同请求源的并发转换请求。每个请求源都可以由外部信号、片上信号或软件来触发。
具有较高优先级的请求可以取消运行的低优先级转换(取消-注入-重复模式),也可以在当前运行的转换之后立即(等待-启动模式)进行转换。如果未读取目标结果寄存器,则可以延迟转换(等待-读取模式)。下图为转换请求控制器模块;
在这里插入图片描述

1.3 Input Channel Selection(输入通道选择)

模拟输入多路复用器选择一个可用模拟输入(CH0-CHx1)进行转换。每个转换源转换哪些通道,在Group中设定好了,只需要请求该转换源,就可以执行对应Group中所有通道的转换。

1.4 Conversion Control(转换控制)

转换参数可以为4个输入类(2个组特定的类,2个全局类)配置,如采样持续时间或结果分辨率。每个通道都可以单独分配给其中一个输入类。

1.5 Analog/Digital Converter(模数转换器)

通过首先对所选输入端上的电压进行采样,然后产生所选的结果位数,从而将所选的输入信道转换为数字值。

1.6 Result Handling(结果处理)

每个模拟输入通道的转换结果可以被定向到16个组特定的结果寄存器和一个全局结果寄存器之一。结果寄存器可以被一组通道或单个通道使用。
等待读取模式会阻止之前的转换,从而避免了由于结果覆盖而导致的数据丢失。

1.7 Service Request Generation服务请求生成

下列ADC事件可以向CPU或DMA发出服务请求:
1.源事件:表示相应请求源中的转换序列的完成。此事件可用于触发一个新序列的设置。
2.通道事件:表示对某个通道的转换已完成。这可以与极限检查相结合,因此只有当结果在定义的值范围内时,才会生成中断。
3.结果事件:表示相应结果寄存器中新结果数据的可用性。如果数据缩减模式是活动的,则只有在一个完全的积累序列之后才会生成事件。
一次ADC转换大概有以下4个步骤:
输入通道选择–>转换控制–>模拟/数字转化–>结果处理

2. 电气属性

2.1输入信号路径

TC27x的ADC使用由CAINSW表示的开关电容场(每个输入引脚都存在小寄生电容)。在采样阶段,CAINSW通过输入多路复用器(由理想开关和串联电阻RAIN构成)连接到选定的模拟输入CHx。
CHx开关在采样阶段时关闭,并将电容场连接到输入电压VAINx。
在这里插入图片描述
内部阻抗为REXT的模拟电压源(值VS)提供应转换的模拟输入。在采样阶段,相应的开关闭合,电容场闭合CAINSW开始充电。由于RC组合具有低通特性,要实际转换的电压VC并不立即跟随VS。模拟电压源的值REXT和所需的转换精度定义了所需的采样相位长度。
为了减少REXT的影响并过滤输入噪声,建议在ADC的模拟输入引脚处引入快速外部阻抗电容器CEXT。

2.2参考电压路径

在转换阶段,部分电容器场(由CAREFSW表示)被切换到参考输入(VAREF或CH0)或VAGND。使用CH0作为备用参考源,可以使用相同的ADC内核转换5.0 V和3.3 V的模拟输入信号。稳定和无噪声的参考和模拟电源电压支持精确的转换结果。

2.3参考电压连接

在这里插入图片描述
参考电压(VAREF和VAGND)对于模数转换器(ADC)转换出来的数字结果非常重要,因为它们决定了模拟信号的量程和零点。如果这些输入受到噪声干扰,那么转换结果的准确性就会受到影响。为了避免这种情况,建议采取一些措施来减少这些输入的噪声。
以12位的转换为例,如果电容开关(CAREFSW)设置为30pF,那么外部参考电容(CREFEXT)应该大于212×30 pF,也就是12nF。在实际应用中,选择100nF的电容器是一个不错的近似值。
至于噪声滤波电容器(CN),它的大小取决于电路板的特性。例如,100nF的电容器可能是一个合适的选择。这个值可以根据你的具体应用和电路板设计来调整,以确保最佳的噪声抑制效果。

2.4传输特性

ADC(模数转换器)的传输特性是指模拟输入电压与数字输出值之间的关系。对于一个n位的ADC,它能够将模拟输入电压转换成2的n次方个不同的数字值。这些数字值的范围是从0到2^n-1。
这个转换过程是这样的:ADC会根据参考电压的范围(由VAREF和VAGND定义)来确定输入电压的范围,并将这个范围均匀地分成2^n个部分。每个部分对应一个数字值,这个部分的大小就是量化步长或者ADC粒度(也可以叫做分辨率),也被称为最小幅值(LSB)。
由于ADC的输出是离散的,所以每个转换结果都有一个固有的不确定性,这个不确定性通常是±0.5 LSB。这意味着实际的模拟输入电压可能会在两个相邻数字值之间,但ADC只能给出其中一个值。
如果模拟输入电压低于参考电压的下限,ADC的输出会饱和在0。同样,如果模拟输入电压高于参考电压的上限,ADC的输出会饱和在2^n-1。在这两种情况下,ADC都不能准确地表示实际的电压值,这就是所谓的饱和现象。

3.通用功能配置

3.1系统寄存器

时钟控制寄存器(CLC)是一个重要的硬件寄存器,它允许程序员根据应用程序的具体需求来调整模块的功能和功耗。通过配置CLC寄存器,可以对模块的时钟信号进行管理,以及控制模块对睡眠模式信号的响应。
在这里插入图片描述
DISR位(rw)——模块禁用请求位,用于模块的启用/禁用控制。此外,通过清除ANONS禁用模拟部分。
DISS位(r)——模块禁用状态位。
EDIS位(rw)——睡眠模式使能控制,用于控制模块对睡眠模式的反应。

3.2通用时钟方案与控制

TC27x的A/D转换器由系统fVADC提供全局时钟信号。从这个输入得到两个时钟信号,并分配到所有的转换器。全局配置寄存器为集群的所有转换器定义公共时钟基。这确保了应并联运行的转换器的确定性行为。
模拟转换器时钟fADCI决定转换器的性能,必须选择符合数据表中给出的规范。
在这里插入图片描述
全局配置寄存器描述略,详见数据手册!

4.生成转换请求

组的转换请求单元自主地处理转换请求的生成。三个请求源(2组特定源和后台源)可以生成模拟通道转换的请求。仲裁器解析并发请求并选择接下来要转换的通道。在触发事件发生时,请求源请求转换某个模拟输入通道或通道序列。
•软件触发器
直接激活相应的请求源。
•外部触发器
将请求源激活与外部事件同步,例如来自定时器产生PWM信号或来自端口引脚的触发脉冲。
每个请求源可以在单次或连续模式下运行:
•在单次模式下,程序转换(序列)被触发后要求一次。必须再次触发后续的转换(序列)。
•在连续模式下,程序转换(序列)在触发一次后自动重复请求。
有两种类型的请求源可用:
•队列扫描源可以为任意序列的输入通道发出转换请求。这个序列的通道号可以自由编程。这支持通道扫描源无法覆盖的特定于应用程序的转换序列。此外,还支持序列中同一通道的多个转换。排队源永久地或按规则的时间基础转换一系列输入通道。
•通道扫描源可以为输入通道的连贯序列发出转换请求。这个序列从最高启用的通道号开始,并继续向较低的通道号前进。所有可用通道可为扫描序列启用。每个通道在每个序列中转换一次。
扫描源永久地或按规则的时间基础转换一系列输入通道。例如,如果以低优先级编程,则可以在后台任务中扫描一些输入通道以更新非时间关键的信息。
队列扫描(Queued Scan)
队列扫描是一种将多个转换请求组织成队列的机制。队列扫描是一种针对单个ADC转换器的扫描模式。在这种模式下,转换请求被组织成一个队列,转换器按照队列中的顺序依次处理这些请求。这种方式适用于需要按特定顺序进行转换的场景,可以确保转换请求的执行顺序与队列中的顺序一致。在这种模式下,每个转换请求可以指定一个优先级,转换器会根据这些优先级来决定处理请求的顺序。这种模式适用于需要根据任务紧急性来动态调整转换顺序的场景。
通道扫描(Channel Scan)
通道扫描通常指的是按照一定的顺序自动遍历并转换一系列预定义的通道。在通道扫描模式下,转换器会自动按顺序处理每个通道的转换请求,无需手动干预。这种模式适用于需要连续监测多个传感器信号的场景,可以确保所有通道都能被周期性地转换。

4.1队列请求源处理

排队请求源支持任意通道的短转换序列(最多8个)(与具有已启用通道的固定转换顺序的扫描请求源相反)。程序序列存储在队列缓冲区中(基于FIFO机制)。请求的通道号通过队列输入,而队列阶段0定义接下来要转换的通道。只有在队列阶段0中存储了有效条目时,才会向请求源仲裁器发出转换请求。
如果仲裁者由于优先级更高的请求而中止由队列请求源触发的转换,则相应的转换参数将自动保存在备份阶段。这确保了中止的转换不会丢失,而是参加下一轮仲裁(在阶段0之前)。
触发和门控单元从所选的ADC外部触发门控信号产生触发事件。触发事件启动一个排队序列,可以通过软件或通过选定的硬件触发器生成。触发事件的发生由QSRx.EV位表示。当相应的转换开始或写入位QMRx.CEV时,此标志被清除。
在这里插入图片描述

4.2通道扫描源请求处理

VADC提供两种类型的通道扫描源:
•源1:组扫描源——该扫描源可以请求相应组的所有通道。
•源2:后台扫描源——此扫描源可以请求所有组的所有通道。
两个源以相同的方式操作,并提供相同的寄存器接口。后台源提供了更多的请求/挂起位,因为它可以请求所有组的所有通道。
如果设置了至少一个挂起位,则转换请求只会发出到请求源仲裁器。如果由于更高优先级的请求,仲裁器终止扫描请求源触发的转换,则自动设置相应的挂起位。这确保了被中止的转换不会丢失,而是会参加下一轮仲裁。

4.3请求源仲裁

请求源仲裁器定期一个接一个地轮询请求源,以查找挂起的转换请求。每个请求源被分配到仲裁轮中的某个时隙,称为仲裁时隙。仲裁槽的持续时间是用户可以通过寄存器GLOBCFG配置的。
一个仲裁轮由每个可用请求源的一个仲裁槽组成。同步源总是在最后一个时隙中进行评估,并且具有比所有其他源更高的优先级。在每轮仲裁结束时,仲裁器确定了最高优先级的转换请求。
如果在仲裁轮中开始转换,则此仲裁轮不会产生仲裁获胜者以下请求源可用:
•仲裁槽0:组排队源,任意顺序的8阶段序列;
•仲裁槽位1:组扫描源,在组内按定义顺序排列序列;
•仲裁槽2:后台扫描源,序列在定义的顺序,所有组;
•最后一个仲裁槽:同步源,来自另一个ADC内核的同步转换请求(总是在同步从设备中以最高优先级处理)。
在这里插入图片描述

5.模拟输入通道配置

对于每个模拟输入通道,可以配置一些参数来控制该通道的转换。通道控制寄存器定义以下参数:
1.通道参数:该通道的采样时间和结果的数据宽度通过输入类来定义。每个通道可以选择自己组的两个类中的一个或两个全局类中的一个。
2.参考选择:可以为大多数通道选择替代参考电压
3.结果目标:转换结果值存储在组特定的结果寄存器或全局结果寄存器中。
4.结果位置:结果值可以按左对齐或按右对齐存储。确切的位置还取决于配置的结果宽度和数据积累模式。
5. 与标准转换(限制检查)比较:每当新结果值可用时,可以生成通道事件。通道事件生成可以限制在用户可配置频带内部或之外的值。
6. 断线检测:此安全功能可以检测到模拟信号源(传感器)缺少连接。
7. 转换的同步:同步转换在多个转换器上同时执行。

5.1通道参数

可以为每个通道定义以下特征:
•结果宽度和采样时间
•生成通道事件和结果值波段(如果使用)
•定义目标寄存器和在该寄存器内的位置的结果的目标
在这里插入图片描述
在这里插入图片描述
输入类型寄存器
在这里插入图片描述
在这里插入图片描述
STCS位:标准转换采样时间控制
在这里插入图片描述
CMS位:标准转换模式(分辨率)
在这里插入图片描述

5.2转换模式

•标准转换模式:一个标准转换返回一个具有预定义分辨率的结果值。可以选择8位、10位和12位的分辨率。
•快速比较模式:在快速比较模式中,所选择的输入电压直接与存储在相应结果寄存器中的数字值进行比较。此比较操作返回一个二进制结果,指示所比较的输入电压是否高于或低于给定的参考值。这个结果可以快速生成,因此支持对边界值的监控。
•选择比较值模式:数字或模拟比较操作的值可以从多个来源中选择。单独的GxBOUND寄存器提供了由软件定义的比较值。比较值也可以从一个结果寄存器中获取,其中它可以由另一个构建引用的通道提供。

5.3与标准转换进行比较(极限检查)

极限检查机构可以自动地将每个数字转换结果与上、下边值进行比较。当转换/比较的结果在用户定义的频带内或外部时,就可以生成通道事件。
在这里插入图片描述

6.转换结果处理

A/D转换器可以对转换结果数据进行一定程度的预处理,然后再存储起来供CPU或DMA通道检索。
转换结果处理包括以下功能:
•将转换结果存储到用户可配置的寄存器
•根据结果宽度进行数据对齐
•进行等待读取模式,以避免数据丢失结果事件
•数据压缩或反混叠滤波

6.1转换结果的存储

某一组的转换结果值可以存储在16个关联的组结果寄存器中之一,或者存储在通用的全局结果寄存器中。
每个结果寄存器都有一个与其关联的单独的数据有效标志(VF)。此标志表示“新的”有效数据何时存储在相应的结果寄存器中,并且可以读出。
对于标准转换,结果值可在位字段结果中提供。在快速比较模式下的转换使用位字段结果作为参考值,因此操作的结果存储在位FCR中。

6.2数据对齐

所选结果寄存器中的转换结果值的位置取决于3种配置:
•所选结果宽度(12/10/8位,由转换模式选择)
•所选结果位置(左/右对齐)
•所选数据积累模式(数据缩减)
在这里插入图片描述

6.3等待读取模式

等待读取模式可以防止由于在CPU(或DMA)读取之前的数据之前用新的转换结果覆盖结果寄存器而导致的数据丢失。

6.4结果FIFO缓冲区

结果寄存器可以用作转换结果的直接目标,也可以与同一ADC组的其他结果寄存器连接,形成结果FIFO缓冲区(先入先出缓冲机制)。结果FIFO存储了几个测量结果,可以稍后通过“放松”CPU响应时间读出。

6.5数据修改

由转换产生的数据可以在被应用程序使用之前自动修改,这就减少了卸载和/或处理转换数据所需的CPU/DMA负载。
•标准数据缩减模式(用于GxRES0 … GxRES15):在生成结果中断之前,在每个结果寄存器中累积2、3或4个结果值。这可以消除输入信号中的一些噪声。
•结果滤波模式(FIR,用于GxRES7,GxRES15):对所选结果寄存器应用具有可选系数的FIR)的转换结果。
•结果滤波模式(IIR,用于GxRES7,GxRES15):对所选结果寄存器的转换结果应用具有可选系数的一阶无限脉冲响应滤波器(IIR)。
•差异模式(适用于GxRES1 … GxRES15):从所选结果寄存器的转换结果中减去结果寄存器GxRES0的内容。

7.安全特性

可以启用多个测试特性来验证一个应用程序的模拟输入信号的有效性。这些测试功能针对信号流的不同部分:

  1. 断线检测验证从传感器到输入引脚的连接,
  2. 多路复用器诊断验证内部模拟输入多路复用器的操作,
  3. 转换器诊断验证模拟/数字转换器本身的操作。

7.1断线检测

为了测试外部模拟传感器与其输入引脚的正确连接,转换器的电容器可以在常规采样阶段之前预充电到一个可选择的值。如果与传感器的连接中断,随后的转换值将更愿意代表预充值,而不是预期的传感器结果。通过使用超出预期结果范围的预充电电压(断线检测最好使用VAGND和/或VAREF),可以区分有效测量(传感器连接)与故障(传感器分离)。

7.2信号路径测试模式

可以激活其他测试结构来测试从传感器到输入引脚的信号路径,以及从输入引脚通过多路复用器到转换器的内部信号路径。
•多路复用器诊断
为了测试内部模拟输入多路复用器的正常运行,额外的上拉和/或下拉设备可以连接到通道CH1和CH2。结合一个已知的外部输入信号,该测试函数显示复用器是否将任何引脚连接到转换器输入,以及这是否是正确的引脚。
•下拉诊断
一个单一的输入通道提供了一个进一步的强下拉(RPDD),可以被激活,以验证与传感器的外部连接。
•转换器诊断
为了测试转换器本身的正常运行,可以将多个信号连接到转换器输入端。测试信号可以连接到转换器输入信号,而不是标准输入信号,也可以与标准输入信号并行。

8.外部多路复用器控制

可以通过将外部模拟多路复用器连接到输入MUX信道来增加模拟输入通道的数量。ADC可以被配置为自动控制这些外部多路复用器。具体阐述略,详见手册。

9.服务请求生成

每个A/D转换器可以激活最多4个特定于组的服务请求输出信号和最多4个共享的服务请求输出信号,以发出中断或触发DMA信道。
可以为每个服务请求输出分配多个事件。服务请求可以由三种类型的事件生成:

  1. 请求源事件:表明一个请求源已经完成了所请求的转换序列,并且应用程序软件可以启动进一步的操作。
  2. 通道事件:表示转换已完成。
  3. 结果事件:在结果寄存器中指示一个新的有效结果。

代码功能实现

手上有TC387的板子所以历程是写的TC387的,TC3xx系列的扫描源没有组扫描源了,这里注意一下就行。
ADC.c

#include "IfxEvadc_Adc.h"
#include "ADC.h"

#define CHANNELS_NUM                4                                       /* 所使用的通道数量                         */
#define GROUPS_NUM                  3                                       /* 所使用的组数(group 0, 1, 2)             */

/**********************************************************配置EVADC所需的变量******************************************/
IfxEvadc_Adc g_evadc;
IfxEvadc_Adc_Group g_evadcGroup[GROUPS_NUM];
IfxEvadc_Adc_Channel g_evadcChannel[CHANNELS_NUM];

channel g_chn[] = { {&IfxEvadc_G0CH0_AN0_IN,  (IfxEvadc_ChannelResult) 0  },  /* AN0 pin   (均值滤波)     */
                    {&IfxEvadc_G0CH5_AN5_IN,  (IfxEvadc_ChannelResult) 15 },  /* AN5 pin   (IIR滤波)     */
                    {&IfxEvadc_G1CH5_AN13_IN, (IfxEvadc_ChannelResult) 7  },  /* AN13 pin  (FIR滤波)     */
                    {&IfxEvadc_G2CH5_AN21_IN, (IfxEvadc_ChannelResult) 1  }   /* AN21 pin  (不进行滤波处理) */
};

/*****************************************************************************************************
 * @projectName:    void init_vadc(void)
 * @introduction:   初始化ADC模块
 * @parameter:      void
 * @return:         void
 * @author:         Unicorn
 * @date:           2024/9/10
 * @version:        1.0
 *****************************************************************************************************/
void init_vadc(void)
{
/*******在写代码时发现TC3xx系列的ADC好像只有队列扫描源,没有通道扫描源了,查阅数据手册确实如此,TC2xx系列是有通道扫描源这个配置的,使用时注意即可*******/
    /*-----------------------------------------------初始化ADC模块-----------------------------------------------*/
    IfxEvadc_Adc_Config adcConfig;
    IfxEvadc_Adc_initModuleConfig(&adcConfig, &MODULE_EVADC);
    IfxEvadc_Adc_initModule(&g_evadc, &adcConfig);                                    /* 初始化ADC模块(默认参数)   */

    /*----------------------------------------------初始化配置ADC组-----------------------------------------------*/
    IfxEvadc_Adc_GroupConfig adcGroupConf;
    IfxEvadc_Adc_initGroupConfig(&adcGroupConf, &g_evadc);                             /* 初始化ADC组(默认参数)     */
    adcGroupConf.arbiter.requestSlotQueue0Enabled = TRUE;                              /* 使能队列源0              */
    adcGroupConf.queueRequest[0].triggerConfig.gatingMode = IfxEvadc_GatingMode_always;/* 设置为连续触发模式(无边缘检测)*/
    adcGroupConf.master = IfxEvadc_GroupId_0;                                          /* 设置组0为主要组           */
    uint8 group;
    for(group = 0; group < GROUPS_NUM; group++)                                        /* 设置所使用的组            */
    {
       adcGroupConf.groupId = (IfxEvadc_GroupId)group;                                 /* 选择所使用的组            */
       IfxEvadc_Adc_initGroup(&g_evadcGroup[group], &adcGroupConf);                    /* 注意组的ID号要对应上       */
    }

    /*-----------------------------------------------初始化配置ADC通道----------------------------------------------*/
    IfxEvadc_Adc_ChannelConfig adcChannelConf;
    uint8 chnNum;
    for(chnNum = 0; chnNum < CHANNELS_NUM; chnNum++)                                   /* 初始化使用的通道           */
    {
       IfxEvadc_Adc_initChannelConfig(&adcChannelConf, &g_evadcGroup[g_chn[chnNum].analogInput->groupId]);

       adcChannelConf.channelId = g_chn[chnNum].analogInput->channelId;                /* 设置通道ID               */
       adcChannelConf.resultRegister = g_chn[chnNum].resultRegister;                   /* 设置结果寄存器             */

       IfxEvadc_Adc_initChannel(&g_evadcChannel[chnNum], &adcChannelConf);

       /* 将通道添加到重新填充选项的队列中 */
       IfxEvadc_Adc_addToQueue(&g_evadcChannel[chnNum], IfxEvadc_RequestSource_queue0, IFXEVADC_QUEUE_REFILL);
    }
}

/*****************************************************************************************************
 * @projectName:    void ADC_Filter(void)
 * @introduction:   使用EVADC模块自带的滤波器
 * @parameter:      void
 * @return:         void
 * @author:         Unicorn
 * @date:           2024/9/10
 * @version:        1.0
 *****************************************************************************************************/
void ADC_Filter(void)
{
    /* 在为AN0生成最终结果之前,在结果寄存器中累积4个结果值 */
    EVADC_G0_RCR0.B.DMM = IfxEvadc_DataModificationMode_standardDataReduction;  /* 设置数据修改模式为 标准数据                  */
    EVADC_G0_RCR0.B.DRCTR = IfxEvadc_DataReductionControlMode_3;                /* 配置组0的结果寄存器0,累计4次转换(也就是均值滤波) */

    /* 对结果寄存器G0RES15 (AN3)应用一阶无限脉冲响应滤波器(IIR) */
    EVADC_G0_RCR15.B.DMM = IfxEvadc_DataModificationMode_resultFilteringMode;   /* 设置数据修改方式为 结果滤波模式               */
    EVADC_G0_RCR15.B.DRCTR = IfxEvadc_DataReductionControlMode_15;              /* 应用IIR滤波器(a=3, b=4) */

    /* 对结果寄存器G0RES7 (AN13)应用三阶有限脉冲响应滤波器(FIR) */
    EVADC_G1_RCR7.B.DMM = IfxEvadc_DataModificationMode_resultFilteringMode;    /* 设置数据修改方式为 结果滤波模式               */
    EVADC_G1_RCR7.B.DRCTR = IfxEvadc_DataReductionControlMode_4;                /* 应用FIR滤波器(a=1, b=0, c=2)           */
}

/*****************************************************************************************************
 * @projectName:    void Start_EVADC(void)
 * @introduction:   开始扫描源转换
 * @parameter:      void
 * @return:         void
 * @author:         Unicorn
 * @date:           2024/9/10
 * @version:        1.0
 *****************************************************************************************************/
void Start_EVADC(void)
{
    uint8 grp;
    for(grp = 0; grp < GROUPS_NUM; grp++)
    {
        /* 队列启动 */
        IfxEvadc_Adc_startQueue(&g_evadcGroup[grp], IfxEvadc_RequestSource_queue0);
    }
}

/*****************************************************************************************************
 * @projectName:    uint16 Read_EVADCValue(uint8 channel)
 * @introduction:   读取ADC结果
 * @parameter:      void
 * @return:         ADC通道结果值
 * @author:         Unicorn
 * @date:           2024/9/10
 * @version:        1.0
 *****************************************************************************************************/
uint16 Read_EVADCValue(uint8 channel)
{
    Ifx_EVADC_G_RES conversionResult;                                           /* 存储转换结果变量                         */
    conversionResult.U = 0;                                                     /* 初始化结果值为0                         */

    while(conversionResult.B.VF != 1 || conversionResult.B.DRC != 0)
    {
        conversionResult = IfxEvadc_Adc_getResult(&g_evadcChannel[channel]);
    }

    return conversionResult.B.RESULT;
}

/*****************************************************************************************************
 * @projectName:    void init_EVADC(void)
 * @introduction:   初始化ADC,可选择是否滤波处理
 * @parameter:      void
 * @return:         void
 * @author:         Unicorn
 * @date:           2024/9/10
 * @version:        1.0
 *****************************************************************************************************/
void init_EVADC(void)
{
    init_vadc();         /*初始化ADC模块   */
    ADC_Filter();        /*ADC滤波       */
    Start_EVADC();       /*启动转换       */
}

ADC.h

#ifndef APP_ADC_H_
#define APP_ADC_H_

#include "Ifx_Types.h"
#include "IfxEvadc_Adc.h"

#define AN0                 0   
#define AN5                 1   
#define AN13                2   
#define AN21                3   

#define DIV_FACTOR_AVRG     4   
#define DIV_FACTOR_FIR      3   
#define DIV_FACTOR_IIR      4   

/* 结构体变量来存储所选通道及其分配的结果寄存器 */
typedef struct
{
    IfxEvadc_Vadcg_In *analogInput;
    IfxEvadc_ChannelResult resultRegister;
} channel;

void init_EVADC(void);
uint16 Read_EVADCValue(uint8 channel);

#endif /* APP_ADC_H_ */

main.c

#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "OLED_IIC.h"
#include "OLED_Data.h"
#include "ADC.h"

IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;


uint16 AD1 = 0;
uint16 AD2 = 0;
uint16 AD3 = 0;
uint16 AD4 = 0;

void core0_main(void)
{
    IfxCpu_enableInterrupts();
    
    /* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
     * Enable the watchdogs and service them periodically if it is required
     */
    IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
    IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
    
    /* Wait for CPU sync event */
    IfxCpu_emitEvent(&g_cpuSyncEvent);
    IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
    
    OLED_Init();
    init_EVADC();
    
    while(1)
    {
        AD1=Read_EVADCValue(AN0) / DIV_FACTOR_AVRG;
        AD2=Read_EVADCValue(AN5) / DIV_FACTOR_IIR;
        AD3=Read_EVADCValue(AN13)/ DIV_FACTOR_FIR;
        AD4=Read_EVADCValue(AN21);
/*******************************注意!如果使用了滤波,转化后的结果要记得除以增益系数***************************/
        OLED_ShowString(0, 0,  "AD1 = ", OLED_8X16);
        OLED_ShowString(0, 16, "AD2 = ", OLED_8X16);
        OLED_ShowString(0, 32, "AD3 = ", OLED_8X16);
        OLED_ShowString(0, 48, "AD4 = ", OLED_8X16);

        OLED_ShowNum(50,0,  AD1, 4, OLED_8X16);
        OLED_ShowNum(50,16, AD2, 4, OLED_8X16);
        OLED_ShowNum(50,32, AD3, 4, OLED_8X16);
        OLED_ShowNum(50,48, AD4, 4, OLED_8X16);
        OLED_Update();
    }
}

效果如下

请添加图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值