从HPM5361的硬件手册和参考手册,了解ADC的基本特性和配置方式。按照以下步骤进行操作:
下面开始:
1、原理图
2、用HPM SDK打开示例
3、端口
4、框架及特性
16 位模数转换器 ADC16 的主要功能和特性:
● 16 位逐次逼近型 ADC
● 最大 2MHz 采样率
● 支持单端输入
● 独立的 ADC 转换时钟
● 支持任意配置的 AD 转换分辨率
● 可配置采样周期数
● 内置 DMA 可直接把 ADC 转换结果写入内存
● 支持读取转换模式 – 读取结果寄存器直接触发转换
● 支持周期转换模式 – 内置定时器按周期进行转换 – 支持硬件阈值比较,对超出范围的转换结果报警
● 支持序列转换模式 – 可由软件或硬件触发 – 序列最长可达 16 – 支持单次转换或者连续转换 – 支持序列循环
● 支持抢占转换模式 – 可由软件或硬件触发 – 连续转换序列最长可达 4
● 支持生成各类中断
SAMPLE_CFGx [SAMPLE_CLOCK_NUMBER] 和 [SAMPLE_CLOCK_NUMBER_SHIFT] 位来设置通道的采样时间。采样时间由 SAMPLE_CLOCK_NUMBER 乘以 2 的 SAMPLE_CLOCK_NUMBER_SHIFT 次方个时钟周期组成。最短的采样时间为 1 个时钟周期。为了达到 16 位的转换精度,需要将 CONV_CFG1[CONVERT_CLOCK_NUMBER] 配置为 21,即转换时间为 21 个时钟周期。
如果用户不需要 16 位的精度,但希望更快地获得结果,可以通过缩短转换时间来实现。用户需要同时改变 CONV_CFG1[CONVERT_CLOCK_NUMBER] 和 ADC16_CONFIG1[COV_END_CNT]。COV_END_CNT = 21 - CONVERT_CLOCK_NUMBER;
1. 当 CONVERT_CLOCK_NUMBER = 21 时,ADC16 在完全的 16 位模式下工作;
1. 当 CONVERT_CLOCK_NUMBER = 14 时,ADC16 大约在 12 位模式下工作;
1. 当 CONVERT_CLOCK_NUMBER = 11 时,ADC16 大约在 10 位模式下工作;
1. 当 CONVERT_CLOCK_NUMBER = 9 时,ADC16 大约在 8 位模式下工作;
其他数值也可以工作,用户可以根据精度和速度需求自由选择。每个通道的转换时间是采样时间和转换时间的总和。
5、概述
先楫HPM5361EVK的16位ADC共支持四种采样模式,分别是读取转换模式、周期转换模式、序列转换模式和抢占转换模式。
读取转换模式:
读取转换模式可以直观地获取 ADC 某个输入通道的转换结果。这在需要尽快了解某个通道的结果,并且在此之前没有其他任务可执行的情况下非常适用。
读取 BUS_RESULTx 寄存器将触发对 ADC 输入 x 的一次转换。一旦转换完成,结果将直接返回。根据不同的 ADC 通道配置,返回转换结果的时间也会有所不同。
在 ADC 完成转换之前,它会阻塞相关的外设总线访问,而由于转换引起的阻塞时间可能会比较长。可以通过将 BUF_CFG0 [WAITDIS] 设置为 1 来关闭总线阻塞。这样,当读取 BUS_RESULTx 寄存器时,它将直接返回上一次转换的结果。当 BUS_RESULTx [VALID] 为 1 时,表示 ADC 转换已完成,此时 BUS_RESULTx 寄存器中保存了最近一次的转换结果。
周期转换模式:
周期转换模式适用于需要按计划进行转换或监测某个通道是否超过阈值的情况。
通过设置 PRD_CFGx [PRD_CNT] 和 [PRESCALE] 寄存器位,可以定义周期的长度,即 PRD_CNT 乘以 2 的 PRESCALE 次方。每个 ADC 时钟周期,计数器会减 1,当计数器计数到 0 时,转换开始,并且计数器重新加载。
需要注意的是,将 PRD_CFGx [PRD_CNT] 位清零表示关闭该输入通道的周期转换。周期转换的结果保存在 PRD_RESULTx 寄存器中,可以从中读取输入通道 x 的最近一次转换结果。值得注意的是,PRD_RESULTx 寄存器始终保存着 ADC 输入通道 x 的最近一次转换结果。PRD_RESULTx 不仅保存周期转换模式的结果,还保存其他转换模式的结果。可以通过设置 PRD_THSHD_CFGx[THSHDH] 和 PRD_THSHD_CFGx[THSHDL] 来监测输入通道 x 的转换结果。一旦转换结果超出范围(结果大于 THSHDHx 或小于 THSHDLx),将触发报警,相应的标志位 INT_STS[ADWDGx] 会被置为 1。如果启用了相应的中断使能,还会产生中断。
ADC 转换结果的检测不仅限于周期转换模式,对于所有读取模式都有效。如果设置的阈值不正确,例如将 THSHDHx 设为 0,那么每当通道转换结束时都会触发报警。如果有多个通道同时到达计时期限需要开始转换,较小序号的输入通道将先进行转换。
序列转换模式:
这种模式适用于需要连续转换某个或多个通道,并且数据量较大的情况,例如测试信噪比或等效位数(ENOB)。
可以通过依次配置 SEQ_QUE0 到 SEQ_QUE15 寄存器来指定转换序列的目标输入通道。SEQ_QUE0 [CHAN_NUM] 位域用于配置序列转换触发后的第一次转换的通道序号,SEQ_QUE1 [CHNUM] 位域配置第二次转换的通道序号,以此类推,SEQ_QUE15 [CHNUM] 位配置第16次转换的通道序号。此外,需要配置 SEQ_CFG0 [SEQ_LEN] 位来指定转换序列的长度,ADC的转换序列最长可达16个通道。序列的开始转换可以通过软件或硬件触发实现:
一旦触发,ADC将按照顺序根据 SEQ_QUE0 的配置开始转换输入通道。转换完成后,标志位 INT_STS [SEQ_CVC](转换完成)将被置为1。此时:
当ADC完成整个序列的转换(长度由 SEQ_CFG0 [SEQ_LEN] 位设置)后,标志位 INT_STS [SEQ_CMPT](序列转换完成)将被置为1。此时:
如果 SEQ_CFG0 [RESTART_EN] 位置1且 SEQ_CFG0 [CONT_EN] 位置1,ADC将自动根据 SEQ_QUEx 的配置,从 SEQ_QUE0 开始连续依次转换。
如果 SEQ_CFG0 [RESTART_EN] 位置0且 SEQ_CFG0 [CONT_EN] 位置1,ADC将在下一次软件或硬件触发后连续转换直到整个序列完成。
如果 SEQ_CFG0 [CONT_EN] 位置0,无论 SEQ_CFG0 [RESTART_EN] 位置1还是0,ADC将在下一次软件或硬件触发后重新根据 SEQ_QUEx 的配置开始转换。
如果在ADC序列转换过程中接收到新的序列转换触发信号,ADC将忽略该触发。如果是通过软件触发序列转换,INT_STS [SEQ_SW_CFLCT] 位将被置为1。如果是由 STRGI 引发的硬件触发序列转换,INT_STS [SEQ_HW_CFLCT] 位将被置为1。
ADC序列转换模式支持内置DMA,可以直接将转换结果写入用户指定的内存缓冲区。用户可以通过 SEQ_DMA_ADDR 寄存器配置目标地址,并通过 SEQ_DMA_CFG [BUF_LEN] 设置数据区域的长度,从而为ADC的序列转换结果配置一个循环缓冲区。
抢占转换模式:
ADC支持抢占转换模式,这是优先级最高的转换模式,适用于对电机控制系统中实时性要求较高的情况,需要在指定时间对指定通道进行转换。
ADC支持12组抢占转换序列,触发信号来自芯片的片上互联模块,共有12个抢占触发源。这些抢占转换序列可以通过寄存器CONFIGx进行配置。抢占转换是通过硬件触发实现的,当PTRGIxA、PTRGIxB或PTRGIxC上出现上升沿时,会触发相应的抢占序列xA、xB或xC。首先,用户需要通过CONFIGx寄存器的[TRIG_LEN]位来配置抢占转换的序列长度,最多可以设置为4,即每个触发最多可以触发一次长度为4的转换。可以通过CONFIGx寄存器配置抢占转换的转换顺序。通过配置寄存器的[CHAN0]、[CHAN1]、[CHAN2]和[CHAN3]位域,依次配置触发后的第1、2、3、4次转换的AD输入通道号码。
一旦抢占转换开始,ADC会根据[TRIG_LEN]的配置连续进行转换,完成整个抢占序列。在抢占序列的第x次转换完成后,如果CONFIGx寄存器的[INTENx]位置为1,INT_STS[TRIG_CMPT]标志位会被置为1。如果相应的中断控制位也被置为1,ADC会生成中断。在ADC抢占转换过程中,如果接收到新的抢占转换触发信号,ADC不会响应新的触发。但是,根据触发源是软件还是硬件,INT_STS[TRIG_SW_CFLICT]标志位或INT_STS[TRIG_HW_CFLICT]标志位会被置为1,表示发生了抢占转换触发冲突。如果对应的中断控制位也被置为1,ADC会产生中断报警。
如果多个不同的抢占转换同时触发,ADC会按照以下优先顺序进行响应:较小组号的抢占转换优先,例如PTRGI0A优先于PTRGI1A;同一组中,xA优先于xB,xB优先于xC,例如PTRGI0A优先于PTRGI0B。同时,INT_STS[PTCHWCFLICT]标志位会被置为1。
ADC抢占转换模式也支持内置DMA,可以直接将转换结果写入用户指定的内存缓冲区中。
6、代码
代码解释
oneshot_handler`的函数,它用于处理一次性的ADC(模数转换器)读取操作。以下是对代码的解析:
uint16_t result;
:用于存储ADC的读取结果。float var;
:用于存储转换后的电压值。adc16_get_oneshot_result(BOARD_APP_ADC16_BASE, BOARD_APP_ADC16_CH_1, &result)
:这是一个函数调用,用于从指定的ADC通道(BOARD_APP_ADC16_CH_1
)获取一次性的ADC读取结果,并存储在result
变量中。if (adc16_is_nonblocking_mode(BOARD_APP_ADC16_BASE))
:这个判断语句检查ADC是否在非阻塞模式下工作。如果是,它会再次调用adc16_get_oneshot_result
来确保获取到最新的结果。var = (result*3.3)/65535;
:这行代码将ADC的16位结果转换为实际的电压值。这里假设ADC的参考电压为3.3V,并且满量程为65535(这通常是12位ADC的情况,但这里的ADC是16位的,所以需要进行适当的调整)。printf("Oneshot Mode - %s [channel %02d] - Result: %f V\\\\n", BOARD_APP_ADC16_NAME, BOARD_APP_ADC16_CH_1, var);
:这行代码打印ADC的读取结果和对应的电压值。7、输出结果
更多回帖