GD32 ADC — ADC 不连续模式

GD32 GD32F30x_Firmware_Library V3.0.3 ADC ADC 不连续模式 示例教学

ADC — ADC 不连续模式

固件库: GD32F30x_Firmware_Library V3.0.3
芯片: GD32
源文件: GD32F30x_Firmware_Library_V3.0.3/Examples/ADC/ADC0_routine_channel_discontinuous_mode/main.c


功能简介

本示例演示 ADC 模数转换器的基本用法。ADC 将模拟电压信号转换为数字值,是读取传感器数据的关键外设。

硬件准备

  • 电位器(可调电阻)连接到 ADC 输入引脚
  • 或使用内部温度传感器(无需额外硬件)

完整代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "gd32f30x.h"
#include "systick.h"
#include <stdio.h>
#include "gd32f307c_eval.h"

void rcu_config(void);
void gpio_config(void);
void dma_config(void);
void adc_config(void);

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    /* system clocks configuration */
    rcu_config();
    /* systick configuration */
    systick_config();
    /* GPIO configuration */
    gpio_config();
    /* configure COM port */
    gd_eval_com_init(EVAL_COM0);
    /* DMA configuration */
    dma_config();
    /* ADC configuration */
    adc_config();

    while(1){
        /* delay 1s */
        delay_1ms(1000);
        printf("\r\n ***********************************\r\n");
        printf("\r\n ADC0 routine channel data 0, PA0 = %04X \r\n", adc_value[0]);
        printf("\r\n ADC0 routine channel data 1, PA1 = %04X \r\n", adc_value[1]);
        printf("\r\n ADC0 routine channel data 2, PA2 = %04X \r\n", adc_value[2]);
        printf("\r\n ADC0 routine channel data 3, PA3 = %04X \r\n", adc_value[3]);
        printf("\r\n ADC0 routine channel data 4, PA4 = %04X \r\n", adc_value[4]);
        printf("\r\n ADC0 routine channel data 5, PA5 = %04X \r\n", adc_value[5]);
        printf("\r\n ADC0 routine channel data 6, PA6 = %04X \r\n", adc_value[6]);
        printf("\r\n ADC0 routine channel data 7, PA7 = %04X \r\n", adc_value[7]);
    }
}

void rcu_config(void)
{
    /* enable GPIOA clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    /* enable ADC0 clock */
    rcu_periph_clock_enable(RCU_ADC0);
    /* enable DMA0 clock */
    rcu_periph_clock_enable(RCU_DMA0);
    /* config ADC clock */
    rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV4);
}

void gpio_config(void)
{
    /* config the GPIO as analog mode */
    gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
    /* config the GPIO as floating input mode, for EXTI */
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX,GPIO_PIN_11);
}

void dma_config(void)
{
    /* ADC_DMA_channel configuration */
    dma_parameter_struct dma_data_parameter;

    /* ADC DMA_channel configuration */
    dma_deinit(DMA0, DMA_CH0);

    /* initialize DMA single 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)(&adc_value);
    dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
    dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT;  
    dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_data_parameter.number = 8;
    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);
}

void adc_config(void)
{
    /* ADC continuous function disable */
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);
    adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);
    /* ADC trigger config */
    adc_external_trigger_source_config(ADC0, ADC_ROUTINE_CHANNEL, ADC0_1_EXTTRIG_ROUTINE_EXTI_11); 
    /* ADC data alignment config */
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    /* ADC mode config */
    adc_mode_config(ADC_MODE_FREE); 
    /* ADC channel length config */
    adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 8);

    /* ADC DMA function enable */
    adc_dma_mode_enable(ADC0);

    /* ADC routine channel config */
    adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 2, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 3, ADC_CHANNEL_3, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 4, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 5, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 6, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);
    adc_routine_channel_config(ADC0, 7, ADC_CHANNEL_7, ADC_SAMPLETIME_55POINT5);

    adc_external_trigger_config(ADC0, ADC_ROUTINE_CHANNEL, ENABLE);

    /* ADC discontinuous mode */
    adc_discontinuous_mode_config(ADC0, ADC_ROUTINE_CHANNEL, 3);

    /* enable ADC interface */
    adc_enable(ADC0);
    delay_1ms(1);
    /* ADC calibration and reset calibration */
    adc_calibration_enable(ADC0);
}

void exti_config(void)
{
    /* connect EXTI line to GPIO pin for routine sequence */
    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_11);
    /* configure EXTI line for routine sequence */
    exti_init(EXTI_11, EXTI_EVENT, EXTI_TRIG_RISING);
    exti_flag_clear(EXTI_11);
}

代码讲解

printf 输出:通过串口打印调试信息。需要先调用 uart_print_init 完成重定向。

GPIO 配置:设置引脚为输出/输入模式,选择推挽/开漏输出,配置上拉/下拉。

ADC 配置:选择采样通道、采样时间、触发方式、数据对齐方式。采样时间越长精度越高。

DMA 配置:设置源地址、目标地址、传输方向、数据宽度。DMA 搬运数据不占用 CPU。

校准:ADC 使用前必须校准,消除工艺偏差。校准期间不要操作 ADC。

实验现象

  • 串口助手打印 ADC 采样值
  • 转动电位器时数值变化
  • 温度传感器示例会显示芯片温度

注意事项

  • ADC 参考电压影响测量精度
  • 采样时间要根据信号源阻抗选择
  • 使用前务必校准(Calibration)
世界是你们
使用 Hugo 构建
主题 StackJimmy 设计