GD32 ADC — ADC 温度 & Vref

GD32 GD32F30x_Firmware_Library V3.0.3 ADC ADC 温度 & Vref 示例教学

ADC — ADC 温度 & Vref

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


功能简介

本示例利用 MCU 内置的温度传感器,通过 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
#include "gd32f30x.h"
#include "systick.h"
#include <stdio.h>
#include "gd32f307c_eval.h"

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

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

    while(1){
        /* delay a time in milliseconds */
        delay_1ms(2000);

        /* value convert */
        temperature = (1.43 - adc_value[0]*3.3/4096) * 1000 / 4.3 + 25;
        vref_value = (adc_value[1] * 3.3 / 4096);

        /* value print */
        printf(" the temperature data is %2.0f degrees Celsius\r\n", temperature);
        printf(" the reference voltage data is %5.3fV \r\n", vref_value);
        printf(" \r\n");
    }
}

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

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       = 2;
    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 mode config */
    adc_mode_config(ADC_MODE_FREE);
    /* ADC contineous function disable */
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
    /* ADC scan mode disable */
    adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
    /* ADC data alignment config */
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);

    /* ADC channel length config */
    adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 2);
    /* ADC temperature sensor channel config */
    adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_239POINT5);
    /* ADC internal reference voltage channel config */
    adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_17, ADC_SAMPLETIME_239POINT5);

    /* ADC trigger config */
    adc_external_trigger_source_config(ADC0, ADC_ROUTINE_CHANNEL, ADC0_1_2_EXTTRIG_ROUTINE_NONE);
    adc_external_trigger_config(ADC0, ADC_ROUTINE_CHANNEL, ENABLE);

    /* ADC temperature and Vrefint enable */
    adc_tempsensor_vrefint_enable();

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

    /* ADC software trigger enable */
    adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}

代码讲解

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

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

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

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

实验现象

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

注意事项

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