elephant00 发表于 2024-11-21 15:31

GD32F103单片机 ADC的同步采样(并行和交错)

一、ADC 同步功能       GD32F103 片上集成了 12 位逐次逼近式模数转换器模块(ADC),可以采样来自于 16 个外部通道 和 2 个内部通道上的模拟信号。这 18 个 ADC 采样通道都支持多种运行模式,采样转换后,转 换结果可以按照最低有效位对齐或最高有效位对齐的方式保存在相应的数据寄存器中。      在有多个ADC模块的产品中,可以使用ADC同步模式。在ADC同步模式下,根据ADC_CTL0寄 存器中SYNCM位所选的模式,转换的启动可以是ADC0和ADC1的交替触发或同步触发。 在同步模式下,当配置由外部事件触发的转换时,ADC0必须通过软件来配置触发来,从而避 免错误的触发引起不必要的转换。此外,对于ADC0和ADC1的外部触发必须被使能。(注意:在ADC同步模式下,即使DMA不用,也要将DMA置位,ADC1的转换数据可以通过ADC0数据 寄存器读取 )。       GD32F103 ADC同步模式主要包括:独立模式、规则并行模式、规则快速交错模式和规则慢速交错模式四种。                                                    同步模式

二、独立模式       在这种模式下,每个 ADC 都独立工作,互不干扰。该模式也是应用较简单的一种。这里主要以其他三种为主进行介绍。三、规则并行模式   此模式可并行转换常规序列,外部触发来源于 ADC0 常规序列触发(由 ADC_CTL1 寄存器的 ETSRC决定),ADC1 常规序列配置为软件触发模式。 在 ADC0 或 ADC1 的转换事件结束时,即 ADC0 或 ADC1 的常规序列转换完毕,会产生一个 EOC 中断(如果某个 ADC 中断使能)。 32 位 ADC_RDATA 寄存器( 位域用于保存 ADC0 常规通道采样数据,位域用 于保存 ADC1 常规通道采样数据),32 位的 DMA 被用来将 ADC_RDATA 中的数据传送到 SRAM。 注意: 1.若两个 ADC 模块使用了相同的采样通道,应保证不在同一时间使用该通道。 2.两个 ADC 在同一时刻采样的两个通道,应该配置相同的采样时间。规则并行模式如下图所示

规则并行模式规则并行模式配置代码如下:#include "adc.h"#include "systick.h"u32 reg_pal_data[4={0};void adc_set(void){        //结构体实例化        dma_parameter_struct dma_structure;        timer_parameter_struct timer_structure;        timer_oc_parameter_struct oc_structure;               //使能时钟        rcu_periph_clock_enable(RCU_GPIOA);        rcu_periph_clock_enable(RCU_ADC0);        rcu_periph_clock_enable(RCU_ADC1);        rcu_periph_clock_enable(RCU_TIMER1);        rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12);        rcu_periph_clock_enable(RCU_DMA0);                //配置GPIO        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_4);        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_5);        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_6);        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_7);                //配置ADC0        adc_mode_config(ADC_DAUL_REGULAL_PARALLEL);        adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);        adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,4);        adc_regular_channel_config(ADC0,0,ADC_CHANNEL_4,ADC_SAMPLETIME_55POINT5);        adc_regular_channel_config(ADC0,1,ADC_CHANNEL_5,ADC_SAMPLETIME_55POINT5);        adc_regular_channel_config(ADC0,2,ADC_CHANNEL_6,ADC_SAMPLETIME_55POINT5);        adc_regular_channel_config(ADC0,3,ADC_CHANNEL_7,ADC_SAMPLETIME_55POINT5);        adc_external_trigger_source_config(ADC0,ADC_REGULAR_CHANNEL,ADC0_1_EXTTRIG_REGULAR_T1_CH1);        adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,ENABLE);                //配置ADC1        adc_data_alignment_config(ADC1,ADC_DATAALIGN_RIGHT);        adc_regular_channel_config(ADC1,0,ADC_CHANNEL_7,ADC_SAMPLETIME_55POINT5);        adc_regular_channel_config(ADC1,1,ADC_CHANNEL_6,ADC_SAMPLETIME_55POINT5);        adc_regular_channel_config(ADC1,2,ADC_CHANNEL_5,ADC_SAMPLETIME_55POINT5);        adc_regular_channel_config(ADC1,3,ADC_CHANNEL_4,ADC_SAMPLETIME_55POINT5);        adc_external_trigger_source_config(ADC1,ADC_REGULAR_CHANNEL,ADC0_1_2_EXTTRIG_REGULAR_NONE);        adc_external_trigger_config(ADC1,ADC_REGULAR_CHANNEL,ENABLE);                //配置定时器1通道1触发        timer_structure.alignedmode=TIMER_COUNTER_EDGE;        timer_structure.clockdivision=TIMER_CKDIV_DIV1;        timer_structure.counterdirection=TIMER_COUNTER_UP;        timer_structure.period=10000-1;        timer_structure.prescaler=12-1;        timer_structure.repetitioncounter=0;        timer_init(TIMER1,&timer_structure);                oc_structure.ocpolarity=TIMER_OC_POLARITY_HIGH;        oc_structure.outputstate=TIMER_CCX_ENABLE;        timer_channel_output_config(TIMER1,TIMER_CH_1,&oc_structure);        timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,4000-1);        timer_channel_output_mode_config(TIMER1,TIMER_CH_1,TIMER_OC_MODE_PWM0);        timer_channel_output_shadow_config(TIMER1,TIMER_CH_1,DISABLE);                //配置DMA        dma_structure.direction=DMA_PERIPHERAL_TO_MEMORY;        dma_structure.memory_addr=(u32)reg_pal_data;        dma_structure.memory_inc=DMA_MEMORY_INCREASE_ENABLE;        dma_structure.memory_width=DMA_MEMORY_WIDTH_32BIT;        dma_structure.number=4;        dma_structure.periph_addr=ADC0+0x4c;        dma_structure.periph_inc=DMA_PERIPH_INCREASE_DISABLE;        dma_structure.periph_width=DMA_PERIPHERAL_WIDTH_32BIT;        dma_structure.priority=DMA_PRIORITY_ULTRA_HIGH;        dma_init(DMA0,DMA_CH0,&dma_structure);        dma_circulation_enable(DMA0,DMA_CH0);        dma_channel_enable(DMA0,DMA_CH0);                timer_enable(TIMER1);                //使能并校准ADC0        adc_enable(ADC0);        delay_ms(10);        adc_calibration_enable(ADC0);                //使能并校准ADC1        adc_enable(ADC1);        delay_ms(10);        adc_calibration_enable(ADC1);                //使能ADC0 DMA        adc_dma_mode_enable(ADC0);}四、规则快速交错模式快速交叉模式适用于两个 ADC 的常规序列采样同一个通道,,外部触发来源于 ADC0 常规序 列(由 ADC_CTL1 寄存器的 ETSRC决定)。当触发产生时,ADC1 立刻启动,而 ADC0 在 7 个 ADC 时钟周期后启动。 如果 ADC0 和 ADC1 的 CTN 位被置位,所选的常规序列在两个 ADC 中被不停的转换。 32 位 ADC_RDATA 寄存器(位域用于保存 ADC0 常规通道采样数据,位域用于 保存 ADC1 常规通道采样数据)。在 ADC0 产生 EOC 中断后(可通过置位 EOCIE 位),可通 过 32 位 DMA 将 ADC_RDATA 中数据传送到 SRAM。 注意:两个 ADC 模块常规通道的采样时间都应小于 7 个 ADC 时钟周期。

规则快速交错模式规则快速交错模式配置程序如下:#include "adc.h"#include "systick.h"u32 reg_pal_data=0;void adc_set(void){        //结构体实例化        dma_parameter_struct dma_structure;        timer_parameter_struct timer_structure;        timer_oc_parameter_struct oc_structure;               //使能时钟        rcu_periph_clock_enable(RCU_GPIOB);        rcu_periph_clock_enable(RCU_ADC0);        rcu_periph_clock_enable(RCU_ADC1);        rcu_periph_clock_enable(RCU_TIMER1);        rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12);        rcu_periph_clock_enable(RCU_DMA0);                //配置GPIO端口        gpio_init(GPIOB,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_0);        //配置模式为快速交错模式        adc_mode_config(ADC_DAUL_REGULAL_FOLLOWUP_FAST);                //配置ADC0        adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);        adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,4);        adc_regular_channel_config(ADC0,0,ADC_CHANNEL_8,ADC_SAMPLETIME_1POINT5);//小于7个采样时钟周期        adc_external_trigger_source_config(ADC0,ADC_REGULAR_CHANNEL,ADC0_1_EXTTRIG_REGULAR_T1_CH1);        adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,ENABLE);                //配置ADC1        adc_data_alignment_config(ADC1,ADC_DATAALIGN_RIGHT);        adc_regular_channel_config(ADC1,0,ADC_CHANNEL_8,ADC_SAMPLETIME_1POINT5);//小于7个采样时钟周期        adc_external_trigger_source_config(ADC1,ADC_REGULAR_CHANNEL,ADC0_1_2_EXTTRIG_REGULAR_NONE);        adc_external_trigger_config(ADC1,ADC_REGULAR_CHANNEL,ENABLE);                //配置定时器1通道1触发ADC转换        timer_structure.alignedmode=TIMER_COUNTER_EDGE;        timer_structure.clockdivision=TIMER_CKDIV_DIV1;        timer_structure.counterdirection=TIMER_COUNTER_UP;        timer_structure.period=10000-1;        timer_structure.prescaler=12-1;        timer_structure.repetitioncounter=0;        timer_init(TIMER1,&timer_structure);                oc_structure.ocpolarity=TIMER_OC_POLARITY_HIGH;        oc_structure.outputstate=TIMER_CCX_ENABLE;        timer_channel_output_config(TIMER1,TIMER_CH_1,&oc_structure);        timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,4000-1);        timer_channel_output_mode_config(TIMER1,TIMER_CH_1,TIMER_OC_MODE_PWM0);        timer_channel_output_shadow_config(TIMER1,TIMER_CH_1,DISABLE);                //配置DMA        dma_structure.direction=DMA_PERIPHERAL_TO_MEMORY;        dma_structure.memory_addr=(u32)(&reg_pal_data);        dma_structure.memory_inc=DMA_MEMORY_INCREASE_ENABLE;        dma_structure.memory_width=DMA_MEMORY_WIDTH_32BIT;        dma_structure.number=1;        dma_structure.periph_addr=ADC0+0x4c;        dma_structure.periph_inc=DMA_PERIPH_INCREASE_DISABLE;        dma_structure.periph_width=DMA_PERIPHERAL_WIDTH_32BIT;        dma_structure.priority=DMA_PRIORITY_ULTRA_HIGH;        dma_init(DMA0,DMA_CH0,&dma_structure);        dma_circulation_enable(DMA0,DMA_CH0);        dma_channel_enable(DMA0,DMA_CH0);                timer_enable(TIMER1);                //校准并使能ADC        adc_enable(ADC0);        delay_ms(10);        adc_calibration_enable(ADC0);                adc_enable(ADC1);        delay_ms(10);        adc_calibration_enable(ADC1);                //使能ADC的DMA功能        adc_dma_mode_enable(ADC0);}五、规则慢速交错模式此模式应用于两个 ADC 的常规序列(通常一个常规通道),外部触发来源于 ADC0 常规序列 (由 ADC_CTL1 寄存器的 ETSRC决定)。当触发产生时,ADC1 立刻启动,而 ADC0 在 14 个 ADC 时钟周期后启动,在 ADC0 启动后的 14 个时钟周期,ADC1 再次启动。 在这种模式下,不能使用连续转换模式,因为在这种模式下所选的常规通道在两个 ADC 中被 不停的转换。 32 位 ADC_RDATA 寄存器(位域用于保存 ADC0 常规通道采样数据,位域用于 保存 ADC1 常规通道采样数据)。在 ADC0 产生 EOC 中断后(可通过置位 EOCIE 位),可通 过 32 位 DMA 将 ADC_RDATA 中数据传送到 SRAM。注意:可允许的最大采样时间必须小于 14 个 CK_ADC 采样时钟,从而避免 ADC0 和 ADC1 在转换相同通道时出现采样时钟重叠。

慢速交错功能

tpgf 发表于 2024-12-2 11:41

在GD32F103单片机中,ADC的同步采样指的是多个ADC模块同时或以特定模式对模拟信号进行采样转换的过程

观海 发表于 2024-12-2 12:50

两个ADC在同一时刻采样的两个通道,应该配置相同的采样时间

磨砂 发表于 2024-12-2 18:40

在配置多个通道采集时,如CH2、CH1、CH5、CH7、CH11等,在扫描模式下,会对各个通道一次进行数据采样

晓伍 发表于 2024-12-2 19:59

可以通过使能TSVREN位来启用温度传感器通道和VREFINT通道

八层楼 发表于 2024-12-2 21:07

两个ADC模块使用了相同的采样通道,应保证不在同一时间使用该通道

guanjiaer 发表于 2024-12-2 22:54

在ADC同步模式下,即使DMA不用,也要将DMA置位,以便ADC1的转换数据可以通过ADC0数据寄存器读取

qiufengsd 发表于 2024-12-7 08:33

如果两个ADC模块使用了相同的采样通道,应保证不在同一时间使用该通道

robertesth 发表于 2024-12-9 10:46

在ADC同步模式下,ADC0和ADC1的转换启动可以通过外部事件触发。这要求ADC0和ADC1的外部触发必须被使能,并且ADC0必须通过软件来配置触发,以避免错误的触发引起不必要的转换。

belindagraham 发表于 2024-12-9 12:17

参考电压的精度直接影响比较结果的准确性。

ulystronglll 发表于 2024-12-9 15:25

若使用 DMA 来传输 ADC 转换数据,需正确配置 DMA 通道、数据传输方向、数据宽度、地址自增等参数,确保数据能够准确无误地从 ADC 数据寄存器传输到内存中指定的位置

AloneKaven 发表于 2024-12-10 14:11

交错采集会不会让精度变高?

vivilyly 发表于 2024-12-10 15:48

ADC的输入阻抗与信号源的输出阻抗匹配,以避免信号失真或采样不准确。

benjaminka 发表于 2024-12-12 13:50

选择合适的触发源来启动ADC转换。这可以是定时器事件、外部中断或其他内部事件。对于同步采样,通常推荐使用定时器作为触发源,因为定时器可以提供精确的时间间隔控制。

cemaj 发表于 2024-12-12 19:18

在ADC同步模式下,即使DMA不用,也要将DMA置位,以便ADC1的转换数据可以通过ADC0数据寄存器读取

rosemoore 发表于 2024-12-12 19:38

在规则并行模式下,ADC0和ADC1可以并行转换常规序列。这种模式适用于需要同时对多个通道进行转换的情况。在此模式下,需要注意两个ADC模块是否使用了相同的采样通道,并确保不在同一时间使用该通道。同时,两个ADC在同一时刻采样的两个通道,应该配置相同的采样时间。

abotomson 发表于 2024-12-12 21:58

正确配置ADC为连续转换模式或扫描模式,以便可以对多个通道进行同步采样。如果需要同时采样多个ADC通道,可能需要设置为双ADC模式(如果硬件支持),以实现真正的同步采样。

mattlincoln 发表于 2024-12-12 22:56

ADC转换的结果可以按照最低有效位对齐或最高有效位对齐的方式保存在相应的数据寄存器中

uptown 发表于 2024-12-13 21:22

GD32F103单片机的ADC支持多种同步模式,包括独立模式、规则并行模式、规则快速交错模式和规则慢速交错模式等。这些模式可以根据实际应用需求进行选择和配置。

jtracy3 发表于 2024-12-13 22:44

在进行同步采样前,需对 ADC 进行校准,以消除 ADC 模块内部的误差,提高转换精度。校准过程需按照芯片手册的要求进行操作,一般包括复位校准和自校准等步骤
页: [1] 2
查看完整版本: GD32F103单片机 ADC的同步采样(并行和交错)