GD32F30x_ADC电压采集(规则并行+DMA方式)

一、工具

  1、硬件:GD32F30x系列单片机

  2、编译环境:KEIL

二、需求分析

  使用单片机的ADC多通道采集不同的电压值。因为采集的通道比较多,为了能够迅速转换每个通道这里我使用了ADC的“规则并行模式”。

  对于“规则并行模式”,官方文档是如下解释:

  同时也给出了基于16个通道的规则并行模式采样和转换图,如下图所示:

三、代码实现

  1、ADC通道引脚配置

/**
  * @brief ADC01 引脚配置
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
static void bsp_adc01_gpio_cfg(void)
{    
    /* enable GPIOA GPIOB GPIOC clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    /* enable alternate function clock */
    rcu_periph_clock_enable(RCU_AF);
    
    /* configure ADC GPIO port */ 
    gpio_init(RCU_GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_init(RCU_GPIOB, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1);
    gpio_init(RCU_GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5);    
}

 

  2、ADC功能配置,为了能够获取每个通道实时的电压值,需要打开“扫描模式”和“连续转换模式”。经过测试发现规则同步模式下是不能转换内部参考电压的

/**
  * @brief ADC01 配置
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
static void bsp_adc01_cfg(void)
{    
    /* enable ADC0 and ADC1 clock */
    rcu_periph_clock_enable(RCU_ADC0);
    rcu_periph_clock_enable(RCU_ADC1);
    /* config ADC clock */
    rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV4);
    
    /* ADC continous function enable */
    adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); 
    adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);
    adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); 
    
    /* ADC trigger config */
    adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
    adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);        
        
    /* ADC data alignment config */
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);
    
    /* ADC mode config,使用规则同步模式,ADC0是主,ADC1是从, 同时转换两个通道(同时转换的通道不能相同) */
    adc_mode_config(ADC_DAUL_REGULAL_PARALLEL); 
    
    /* ADC channel length config */
    adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 5);
    adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 5);    
    
    /* ADC regular channel config,一个通道转换时长是2.06us */
    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_regular_channel_config(ADC0, 4, ADC_CHANNEL_8, ADC_SAMPLETIME_55POINT5);
        
    adc_regular_channel_config(ADC1, 0, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5);    
    adc_regular_channel_config(ADC1, 1, ADC_CHANNEL_12, ADC_SAMPLETIME_55POINT5);
    adc_regular_channel_config(ADC1, 2, ADC_CHANNEL_14, ADC_SAMPLETIME_55POINT5);
    adc_regular_channel_config(ADC1, 3, ADC_CHANNEL_15, ADC_SAMPLETIME_55POINT5);
    adc_regular_channel_config(ADC1, 4, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5);
    
    /* ADC external trigger enable */
    adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);    
    adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);    

    /* enable ADC0 interface */
    adc_enable(ADC0);      
    delay_ms(0xFFFF);
    /* ADC0 calibration and reset calibration */
    adc_calibration_enable(ADC0);
    
    /* enable ADC1 interface */
    adc_enable(ADC1);      
    delay_ms(0xFFFF);
    /* ADC1 calibration and reset calibration */
    adc_calibration_enable(ADC1);    
    
    /* ADC DMA function enable */
    adc_dma_mode_enable(ADC0);        
    
    /* ADC0 software trigger enable */
    adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}

 

  3、ADC的DMA配置

uint32_t adc01_value[5];
/**
  * @brief ADC01 DMA配置
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
void bsp_adc01_dma_cfg(void)
{
    /* ADC_DMA_channel configuration */
    dma_parameter_struct dma_data_parameter;
    /* enable DMA0 clock */
    rcu_periph_clock_enable(RCU_DMA0); 
    /* ADC DMA_channel configuration */
    dma_deinit(DMA0, DMA_CH0);
   
    /* initialize DMA data mode */
    dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
    dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_data_parameter.memory_addr = (uint32_t)(&adc01_value);
    dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
    dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT;  
    dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_data_parameter.number = 5;        /* ADC通道数量 */
    dma_data_parameter.priority = DMA_PRIORITY_HIGH;
    dma_init(DMA0, DMA_CH0, &dma_data_parameter);
    dma_circulation_enable(DMA0, DMA_CH0);
    /* enable DMA channel */
    dma_channel_enable(DMA0, DMA_CH0);
}

 

  4、ADC初始化

/**
  * @brief ADC01 初始化
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
void bsp_adc01_init(void)
{
    bsp_adc01_gpio_cfg();
    bsp_adc01_dma_cfg();
    bsp_adc01_cfg();
}

 

  5、获取各通道ADC值

/**
  * @brief 获取测量端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_mea_adc_value(void)
{
    return (uint16_t)(adc01_value[0]&0xFFFF);
}

/**
  * @brief 获取bat端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_bat_adc_value(void)
{
    return (uint16_t)(adc01_value[1]&0xFFFF);
}

/**
  * @brief 获取校准端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_cal_adc_value(void)
{
    return (uint16_t)(adc01_value[2]&0xFFFF);
}

/**
  * @brief 获取参比端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_ref_adc_value(void)
{
    return (uint16_t)(adc01_value[3]&0xFFFF);
}

/**
  * @brief 获取-5V端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_minus_5v_adc_value(void)
{
    return (uint16_t)(adc01_value[4]&0xFFFF);
}

/**
  * @brief 获取+5V端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_pluse_5v_adc_value(void)
{
    return (uint16_t)(adc01_value[0] >> 16);;
}

/**
  * @brief 获取8.5V端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_8v5_adc_value(void)
{
    return (uint16_t)(adc01_value[1] >> 16);;
}

/**
  * @brief 获取+12V端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_pluse_12v_adc_value(void)
{
    return (uint16_t)(adc01_value[2] >> 16);;
}

/**
  * @brief 获取-12V端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-10
  */
uint16_t adc01_get_minus_12v_adc_value(void)
{
    return (uint16_t)(adc01_value[3] >> 16);;
}

/**
  * @brief 获取bat'端adc值
  * @retval none
  * @author Mr.W
  * @date 2020-11-19
  */
uint16_t adc01_get_batn_adc_value(void)
{
    return (uint16_t)(adc01_value[4] >> 16);;
}

 

#endif

posted @ 2020-11-22 16:43  不要让自己太懒  阅读(10827)  评论(9编辑  收藏  举报