GD32L23X ADC+DMA读取多通道电压软触发附代码

ADC +DMA采样配置

D32L23x系列芯片上集成了一个12位连续近似模数转换器模块(ADC)。
是一种采用逐次逼近方式的模拟数字转换器。
可以从16个外部通道和4个内部通道的模拟信号进行采样。
20个ADC采样通道均支持多种操作模式。
经过采样和转换后,转换结果可以根据最小有效位对齐或最显著位对齐存储在相应的数据寄存器中。
ADC的位数是12位,参考电压为3.3V,那么其数字值变化1对应的模拟信号电压变化为3.3V/(2^12)≈0.8mV
采用一个ADC三个通道+DMA对其进行采样,经过测试有较为稳定的数据
ADC一般需要配置的内容包括:

  1. IO配置(时钟,模拟输入)
  2. ADC参数配置(模式-扫描模式,连续模式;触发方式;通道配置-规则组or注入组;ADC校正)
  3. 中断和DMA(使能)配置
    【注】ADC的规则组和注入组的区别可简单理解为:规则组是周期执行的程序,注入组是中断程序

ADC 全部初始化,这里采用PA 1和6,PB1 作为电压读取通道

具体对应的通道需要去看datasheet, 如PA1如下
在这里插入图片描述

void ADC_Init(void)
{
    // GPIO configure
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1 | GPIO_PIN_6);
    gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
    // ADC configure
    adc_configure();
    // DMA configure
    dma_adc_configure();
}

配置ADC

可编程采样时间计算

对于12位分辨率,总采样和转换时间为“采样时间+12.5”CK_ADC周期。例如: CK_ADC = 16MHz,采样时间为2.5个周期,总转换时间为“2.5+12.5”CK_ADC周期,(2.5+12.5)/16MHZ即0.9375us。
在本项目中:APB2为16Mhz
8分频
转换时间 = (1/2M)*(55.5+12.5)=34us

自校准功能

ADC带有一个前置校准功能。在校准期间,ADC计算一个校准系数,这个系数是应用于ADC内部的,它直到ADC下次掉电才无效。在校准期间,应用不能使用ADC,必须等到校准完成。在校准期间CLB位会一直保持1,直到校准完成,该位由硬件清0。 当ADC运行条件改变(例如,VDDA、VREF+以及温度等)或第一次开始A/D转换,建议执行一次校准操作

static void adc_configure(void)
{
    // 16M/8=2Mhz  ADC MAX CLOCK = 16Mhz
    rcu_periph_clock_enable(RCU_ADC);
    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV8);
    // ADC configure
    adc_deinit();
    adc_special_function_config(ADC_SCAN_MODE, ENABLE);
    adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
    adc_resolution_config(ADC_RESOLUTION_12B);
    adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
    adc_channel_length_config(ADC_REGULAR_CHANNEL, 3);
    adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
    adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
    // PA1 - AD1 change time = (1/2M)*(55.5+12.5)=34us
    adc_regular_channel_config(0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
    // PB1 - AD9
    adc_regular_channel_config(1, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5);
    // PA6 - AD6
    adc_regular_channel_config(2, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);
    // adc enable
    adc_enable();
    adc_calibration_enable();
    adc_dma_mode_enable();
    adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
}

配置DMA

static void dma_adc_configure(void)
{
    // DMA configure
    dma_parameter_struct dma_init_struct;
    rcu_periph_clock_enable(RCU_DMA);
    dma_deinit(DMA_CH0);
    dma_init_struct.request = DMA_REQUEST_ADC;
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.number = 3;
    dma_init_struct.periph_addr = (uint32_t) & (ADC_RDATA);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
    dma_init_struct.memory_addr = (uint32_t)(&adc_datainfo.sampling_data);
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init(DMA_CH0, &dma_init_struct);
    // dma enable
    dma_circulation_enable(DMA_CH0);
    dma_channel_enable(DMA_CH0);
}

ADC轮询读取

static uint16_t get_adc_ch(uint8_t i)
{
    uint16_t value = 0;
    // software enable
    adc_software_trigger_enable(ADC_REGULAR_CHANNEL);

    value = adc_datainfo.sampling_data[i];
    adc_flag_clear(ADC_FLAG_STRC);

    return value;
}

一些GD的ADC+DMA的坑

一定要配置为scan 和 continue 模式

    adc_special_function_config(ADC_SCAN_MODE, ENABLE);
    adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);

配置规则通道之后需要不断地进行软件触发,才能收到数据,有些教程仅在初始化的时候触发一次,会导致只读到一次数据

adc_software_trigger_enable(ADC_REGULAR_CHANNEL);

3个ADC通道对应的GPIO需要去手册好好看看

    // PA1 - AD1 change time = (1/2M)*(55.5+12.5)=34us
    adc_regular_channel_config(0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
    // PB1 - AD9
    adc_regular_channel_config(1, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5);
    // PA6 - AD6
    adc_regular_channel_config(2, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);

最好配置为circular模式,循环DMA读取。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值