打印

ADC0_ADC1_ADC2_所有的ADC工作在常规并行模式DMA传送数据

[复制链接]
398|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
guozq980|  楼主 | 2023-12-16 15:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 guozq980 于 2023-12-16 16:16 编辑

GD32F470 ADC0_ADC1_ADC2_所有的ADC工作在常规并行模式,DMA传送数据,怎么每隔一段时间数据就错位了?

#include "bsp_timer.h"

#define EPS_ADC_ALL_ROUTINE_PARALLEL

#define ADC0_CONVERT_COUNT                        6
#define ADC1_CONVERT_COUNT                        6
#define ADC2_CONVERT_COUNT                        6

uint16_t adc_convert_value[ADC0_CONVERT_COUNT + ADC1_CONVERT_COUNT + ADC2_CONVERT_COUNT];

static void rcu_config(void)
{
        // enable GPIOC clock
        rcu_periph_clock_enable(RCU_DMA1);
        
        rcu_periph_clock_enable(RCU_ADC0);
        rcu_periph_clock_enable(RCU_ADC1);
        rcu_periph_clock_enable(RCU_ADC2);
        
        //adc_clock_config(ADC_ADCCK_PCLK2_DIV4);        // ADC CLK 120MHz / 4 = 30MHz
        adc_clock_config(ADC_ADCCK_HCLK_DIV6);                // ADC CLK 240MHz / 6 = 40MHz
        
        rcu_periph_clock_enable(RCU_GPIOA);
        rcu_periph_clock_enable(RCU_GPIOB);
        rcu_periph_clock_enable(RCU_GPIOC);
}

static void gpio_config(void)
{
    // config the GPIO as analog mode
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);        
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
        
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);        
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_5);
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_7);
        
    gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);        
    gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
        
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);        
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_5);
}

#ifndef EPS_ADC_ALL_ROUTINE_PARALLEL
static void adc0_dma_config(void)
{
    // ADC_DMA_channel configuration
    dma_single_data_parameter_struct dma_single_data_parameter;

    // ADC DMA_channel configuration
    dma_deinit(DMA1, DMA_CH0);

    // initialize DMA single data mode
    dma_single_data_parameter.periph_addr         = (uint32_t)(&ADC_RDATA(ADC0));
    dma_single_data_parameter.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;        
    dma_single_data_parameter.memory_addr         = (uint32_t)(&adc_convert_value[0]);
    dma_single_data_parameter.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
        
    dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
    dma_single_data_parameter.direction           = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter.number              = ADC0_CONVERT_COUNT;
    dma_single_data_parameter.priority            = DMA_PRIORITY_HIGH;
        
    dma_single_data_mode_init(DMA1, DMA_CH0, &dma_single_data_parameter);
        
    dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);

    // enable DMA circulation mode
    dma_circulation_enable(DMA1, DMA_CH0);

        nvic_irq_enable(DMA1_Channel0_IRQn, 0, 4);
        
        dma_flag_clear(DMA1, DMA_CH0, DMA_FLAG_FTF | DMA_FLAG_HTF);
        
        dma_interrupt_enable(DMA1, DMA_CH0, DMA_CHXCTL_FTFIE);               
               
    // enable DMA channel
    dma_channel_enable(DMA1, DMA_CH0);        
}

static void adc1_dma_config(void)
{
    // ADC_DMA_channel configuration
    dma_single_data_parameter_struct dma_single_data_parameter;

    // ADC DMA_channel configuration
    dma_deinit(DMA1, DMA_CH2);

    // initialize DMA single data mode
    dma_single_data_parameter.periph_addr         = (uint32_t)(&ADC_RDATA(ADC1));
    dma_single_data_parameter.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;        
    dma_single_data_parameter.memory_addr         = (uint32_t)(&adc_convert_value[6]);
    dma_single_data_parameter.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
        
    dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
    dma_single_data_parameter.direction           = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter.number              = ADC0_CONVERT_COUNT;
    dma_single_data_parameter.priority            = DMA_PRIORITY_HIGH;
        
    dma_single_data_mode_init(DMA1, DMA_CH2, &dma_single_data_parameter);
        
    dma_channel_subperipheral_select(DMA1, DMA_CH2, DMA_SUBPERI1);

    // enable DMA circulation mode
    dma_circulation_enable(DMA1, DMA_CH2);

        nvic_irq_enable(DMA1_Channel2_IRQn, 0, 4);
        
        dma_flag_clear(DMA1, DMA_CH2, DMA_FLAG_FTF | DMA_FLAG_HTF);
        
        dma_interrupt_enable(DMA1, DMA_CH2, DMA_CHXCTL_FTFIE);               
               
    // enable DMA channel
    dma_channel_enable(DMA1, DMA_CH2);        
}

static void adc2_dma_config(void)
{
    // ADC_DMA_channel configuration
    dma_single_data_parameter_struct dma_single_data_parameter;

    // ADC DMA_channel configuration
    dma_deinit(DMA1, DMA_CH1);

    // initialize DMA single data mode
    dma_single_data_parameter.periph_addr         = (uint32_t)(&ADC_RDATA(ADC2));
    dma_single_data_parameter.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;        
    dma_single_data_parameter.memory_addr         = (uint32_t)(&adc_convert_value[12]);
    dma_single_data_parameter.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
        
    dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
    dma_single_data_parameter.direction           = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter.number              = ADC0_CONVERT_COUNT;
    dma_single_data_parameter.priority            = DMA_PRIORITY_HIGH;
        
    dma_single_data_mode_init(DMA1, DMA_CH1, &dma_single_data_parameter);
        
    dma_channel_subperipheral_select(DMA1, DMA_CH1, DMA_SUBPERI2);

    // enable DMA circulation mode
    dma_circulation_enable(DMA1, DMA_CH1);

        nvic_irq_enable(DMA1_Channel1_IRQn, 0, 4);
        
        dma_flag_clear(DMA1, DMA_CH1, DMA_FLAG_FTF | DMA_FLAG_HTF);
        
        dma_interrupt_enable(DMA1, DMA_CH1, DMA_CHXCTL_FTFIE);               
               
    // enable DMA channel
    dma_channel_enable(DMA1, DMA_CH1);        
}

#else
void dma_adc_sync_config(void)
{
    // ADC_DMA_channel configuration
    dma_single_data_parameter_struct dma_single_data_parameter;

    // ADC DMA_channel configuration
    dma_deinit(DMA1, DMA_CH0);

    // initialize DMA single data mode
    dma_single_data_parameter.periph_addr         = (uint32_t)(&ADC_SYNCDATA);
    dma_single_data_parameter.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;        
    dma_single_data_parameter.memory_addr         = (uint32_t)(adc_convert_value);
    dma_single_data_parameter.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
        
    dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
        dma_single_data_parameter.direction           = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter.circular_mode       = DMA_CIRCULAR_MODE_ENABLE;
        
    dma_single_data_parameter.number              = (ADC0_CONVERT_COUNT + ADC1_CONVERT_COUNT + ADC2_CONVERT_COUNT);
    dma_single_data_parameter.priority            = DMA_PRIORITY_HIGH;
        
    dma_single_data_mode_init(DMA1, DMA_CH0, &dma_single_data_parameter);
        
    dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);

        nvic_irq_enable(DMA1_Channel0_IRQn, 0, 4);        
        dma_flag_clear(DMA1, DMA_CH0, DMA_FLAG_FTF | DMA_FLAG_HTF);        
        dma_interrupt_enable(DMA1, DMA_CH0, DMA_CHXCTL_FTFIE);               
               
    // enable DMA channel
    dma_channel_enable(DMA1, DMA_CH0);        
}
#endif

void adc0_config(void)
{
        // ADC contineous function disable
        adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);

        // ADC scan mode enable
        adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);

        // ADC data alignment config
        adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);

        adc_resolution_config(ADC0,ADC_RESOLUTION_12B);

        // ADC channel length config
        adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, ADC0_CONVERT_COUNT);

        // ADC routine channel config
        adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_10, ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_9,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC0, 2, ADC_CHANNEL_14, ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC0, 3, ADC_CHANNEL_15, ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC0, 4, ADC_CHANNEL_16, ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC0, 5, ADC_CHANNEL_17, ADC_SAMPLETIME_56);
        
        // ADC trigger config
        adc_external_trigger_source_config(ADC0, ADC_ROUTINE_CHANNEL, ADC_EXTTRIG_ROUTINE_T1_CH3);
        adc_external_trigger_config(ADC0, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_RISING);
        
#ifndef EPS_ADC_ALL_ROUTINE_PARALLEL
        adc_dma_request_after_last_enable(ADC0);
        adc_dma_mode_enable(ADC0);
#endif

        // enable ADC interface
        adc_enable(ADC0);

        // wait for ADC stability
        delay_1ms(1);

        // ADC calibration and reset calibration
        adc_calibration_enable(ADC0);
}

void adc1_config(void)
{
        // ADC contineous function disable
        adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, DISABLE);

        // ADC scan mode enable
        adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);

        // ADC data alignment config
        adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);

        adc_resolution_config(ADC1,ADC_RESOLUTION_12B);

        // ADC channel length config
        adc_channel_length_config(ADC1, ADC_ROUTINE_CHANNEL, ADC1_CONVERT_COUNT);

        adc_routine_channel_config(ADC1, 0, ADC_CHANNEL_11, ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC1, 1, ADC_CHANNEL_4,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC1, 2, ADC_CHANNEL_5,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC1, 3, ADC_CHANNEL_6,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC1, 4, ADC_CHANNEL_7,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC1, 5, ADC_CHANNEL_8,  ADC_SAMPLETIME_56);
        
#ifndef EPS_ADC_ALL_ROUTINE_PARALLEL
        // ADC trigger config
        adc_external_trigger_source_config(ADC1, ADC_ROUTINE_CHANNEL, ADC_EXTTRIG_ROUTINE_T1_CH3);
        adc_external_trigger_config(ADC1, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_RISING);

        adc_dma_request_after_last_enable(ADC1);
        adc_dma_mode_enable(ADC1);
#else
        adc_external_trigger_config(ADC1, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_DISABLE);        
#endif

        // enable ADC interface
        adc_enable(ADC1);

        // wait for ADC stability
        delay_1ms(1);

        // ADC calibration and reset calibration
        adc_calibration_enable(ADC1);
}

void adc2_config(void)
{
        // ADC contineous function disable
        adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, DISABLE);

        // ADC scan mode enable
        adc_special_function_config(ADC2, ADC_SCAN_MODE, ENABLE);

        // ADC data alignment config
        adc_data_alignment_config(ADC2, ADC_DATAALIGN_RIGHT);

        adc_resolution_config(ADC2,ADC_RESOLUTION_12B);

        // ADC channel length config
        adc_channel_length_config(ADC2, ADC_ROUTINE_CHANNEL, ADC2_CONVERT_COUNT);

        adc_routine_channel_config(ADC2, 0, ADC_CHANNEL_12, ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC2, 1, ADC_CHANNEL_13,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC2, 2, ADC_CHANNEL_0,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC2, 3, ADC_CHANNEL_1,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC2, 4, ADC_CHANNEL_2,  ADC_SAMPLETIME_56);
        adc_routine_channel_config(ADC2, 5, ADC_CHANNEL_3,  ADC_SAMPLETIME_56);
        
#ifndef EPS_ADC_ALL_ROUTINE_PARALLEL
        // ADC trigger config
        adc_external_trigger_source_config(ADC2, ADC_ROUTINE_CHANNEL, ADC_EXTTRIG_ROUTINE_T1_CH3);
        adc_external_trigger_config(ADC2, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_RISING);

        adc_dma_request_after_last_enable(ADC2);
        adc_dma_mode_enable(ADC2);
#else
        adc_external_trigger_config(ADC2, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
#endif

        // enable ADC interface
        adc_enable(ADC2);

        // wait for ADC stability
        delay_1ms(1);

        // ADC calibration and reset calibration
        adc_calibration_enable(ADC2);
}

void adc_config(void)
{
        rcu_config();        
        gpio_config();        
        
        // ADC mode config
#ifndef EPS_ADC_ALL_ROUTINE_PARALLEL
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);        // ADC_ALL_ROUTINE_PARALLEL
        
        adc0_dma_config();
        adc1_dma_config();
        adc2_dma_config();
#else
    adc_sync_mode_config(ADC_ALL_ROUTINE_PARALLEL);                // 所有ADC工作在常规并行模式
        adc_sync_dma_config(ADC_SYNC_DMA_MODE0);
    adc_sync_dma_request_after_last_enable();
        
        dma_adc_sync_config();
#endif
               
        // ADC Vbat channel enable
        adc_channel_16_to_18(ADC_VBAT_CHANNEL_SWITCH, ENABLE);

        // ADC temperature and Vref enable
        adc_channel_16_to_18(ADC_TEMP_VREF_CHANNEL_SWITCH, ENABLE);
        
        adc0_config();
        adc1_config();               
        adc2_config();
}

Screenshot 2023-12-16 152431.png (143.03 KB )

Screenshot 2023-12-16 152431.png

Screenshot 2023-12-16 152353.png (82.96 KB )

Screenshot 2023-12-16 152353.png

使用特权

评论回复
沙发
guozq980|  楼主 | 2023-12-16 15:34 | 只看该作者
图中黄、兰、绿是三个通道的测量值,每30个周波就错位一次

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

4

帖子

0

粉丝