GD32F130 多路ADC采样(基于DMA方式)

声明

此文档主要来源于GD32官方例程,不涉及公司内部关键代码,主要用于自己回顾。

前言

此程序是基于GD32F130F8P6,目的是运用NTC,检测9路温度,此文档仅涉及DMA配置及ADC采样值获取。

一、时钟配置

void rcu_config(void)
{
    /* enable GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	/* enable ADC clock */
    rcu_periph_clock_enable(RCU_ADC);
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA);
    /* config ADC clock */
    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
}

二、ADC初始化配置

void adc_config(void)
{
	/* gpio config */
	gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 |											
														   GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 |
														   GPIO_PIN_6 | GPIO_PIN_7 );
	
	gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
	
	/* ADC channel length config */
    adc_channel_length_config(ADC_REGULAR_CHANNEL,ADC_Num);
	
    /* ADC regular channel config */
    adc_regular_channel_config(0,ADC_CHANNEL_0,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(1,ADC_CHANNEL_1,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(2,ADC_CHANNEL_2,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(3,ADC_CHANNEL_3,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(4,ADC_CHANNEL_4,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(5,ADC_CHANNEL_5,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(6,ADC_CHANNEL_6,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(7,ADC_CHANNEL_7,ADC_SAMPLETIME_13POINT5);
	adc_regular_channel_config(8,ADC_CHANNEL_9,ADC_SAMPLETIME_13POINT5);
	
    /* ADC external trigger enable */
    adc_external_trigger_config(ADC_REGULAR_CHANNEL,ENABLE);
	
    /* ADC external trigger source config */
    adc_external_trigger_source_config(ADC_REGULAR_CHANNEL,ADC_EXTTRIG_REGULAR_SWRCST);
	
    /* ADC data alignment config */
    adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
	
	/* ADC discontinuous mode */
    adc_discontinuous_mode_config(ADC_REGULAR_CHANNEL,4);
	
    /* enable ADC interface */
    adc_enable();
	
    /* ADC calibration and reset calibration */
    adc_calibration_enable();
	
    /* ADC DMA function enable */
    adc_dma_mode_enable();
    /* ADC contineous function enable */
//    adc_special_function_config(ADC_CONTINUOUS_MODE,ENABLE);
    /* ADC software trigger enable */
//    adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
	
}

在ADC转化的过程中,需注意 adc_software_trigger_enable(ADC_REGULAR_CHANNEL)的使用,在运用到多通道ADC采样过程中,使用不当可能会出现数据错位。我的工程中是在主循环while(1)中进行触发。

三、DMA初始化

void dma_config(void)
{
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA);
	
	/* ADC_DMA_channel configuration */
    dma_deinit(DMA_CH0);
    dma_periph_address_config(DMA_CH0,(uint32_t)(&ADC_RDATA));
    dma_memory_address_config(DMA_CH0,(uint32_t)(&adc_value));
    dma_transfer_direction_config(DMA_CH0,DMA_PERIPHERAL_TO_MEMORY);
    dma_memory_width_config(DMA_CH0,DMA_MEMORY_WIDTH_16BIT);
    dma_periph_width_config(DMA_CH0,DMA_PERIPHERAL_WIDTH_16BIT);
    dma_priority_config(DMA_CH0,DMA_PRIORITY_HIGH);
    dma_transfer_number_config(DMA_CH0,ADC_Num);
    dma_periph_increase_disable(DMA_CH0);
    dma_memory_increase_enable(DMA_CH0);
    dma_circulation_enable(DMA_CH0);
    dma_channel_enable(DMA_CH0);
}

在上述配置的过程中,需要注意的是:
1、 dma_memory_address_config(DMA_CH0,(uint32_t)(&adc_value)),adc_value[]是一个用于储存DMA数据的缓冲区。
2、dma_transfer_number_config(DMA_CH0,ADC_Num);此处的ADC_Num是采样通道数量,我这里是把ADC_Num宏定义为 0x09。
需特别注意adc_value[]与ADC_Num的配合。

四、主函数处理与部分变量定义

#define AVE_NUM    8
#define ADC_Num    9
uint16_t adc_value[9];
int main(void)
{
	uint8_t i;
	static uint8_t  adc_date_realdy_flag = 0;
	static uint16_t adc_sum_count    = 0;
	static uint16_t adc_date_buffer[AVE_NUM][ADC_Num] = {0};
	static uint32_t adc_sum[ADC_Num]  = {0};
	static uint16_t adc_ave[ADC_Num] = {0};
	
	rcu_config();
    /* ADC configuration */
    adc_config();
	dma_config();
	
    while(1)
	{
		/*adc software trigger*/
		adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
		
		/* get adc value, 8 times*/
		if (adc_sum_count < 8)
		{
			/* 9 ch */
			for (i=0; i<ADC_Num; i++)
			{
				adc_date_buffer[adc_sum_count][i]  = adc_value[i];
			}
			adc_sum_count++;
		}
		else
		{
			adc_sum_count = 0;
			
			adc_date_realdy_flag = 1;
		}
		
		/* frist times get complete data after boot */
		if (adc_date_realdy_flag == 1)
		{
			for(i=0; i<ADC_Num; i++)
			{
				/* calculate sum data of ch */
				adc_sum[i] = adc_date_buffer[0][i] + adc_date_buffer[1][i] + adc_date_buffer[2][i] + adc_date_buffer[3][i] 
							+ adc_date_buffer[4][i] + adc_date_buffer[5][i] + adc_date_buffer[6][i] + adc_date_buffer[7][i];
				
				/* Calculated average*/
				adc_ave[i] = adc_sum[i] >> 3;
			}
		}
	}
}

在主函数中,DMA传输的数据存在一个二维数组中,每个通道取8次值,轮询更新。求和,再取平均值,这里建议取2的次方,在求平均值时,采用移位操作即可。但是会丢失部分精度。

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
gd32f3adc多通道采样的实现方法如下: 首先,需要在ADC初始化函数中配置多通道扫描模式。可以通过设置ADC_CTL1寄存器的SCAN位来启用多通道扫描模式。同时,还需要配置ADC_CTL1寄存器的SCHx位来选择需要采样的通道。每个SCHx位对应一个通道,可以根据需要设置多个SCHx位来选择多个通道。 其次,需要配置ADC转换序列。可以通过设置ADC_CTL1寄存器的ADC_SAMCTL位来选择转换序列的长度。例如,设置ADC_SAMCTL为ADC_SAMCTL_SAMx_1表示转换序列长度为1,即只采样一个通道;设置为ADC_SAMCTL_SAMx_2表示转换序列长度为2,即采样两个通道。 然后,在采样过程中,可以使用DMA来自动将采样数据读取到指定的数组中。可以配置DMA的通道和传输方向,将ADC数据传输到指定的数组中。 最后,在读取采样数据时,需要根据转换序列的长度来确定读取的数据个数。例如,如果转换序列长度为2,则可以通过读取两个数据来获取两个通道的采样值。 综上所述,通过配置ADC多通道扫描模式和转换序列,并使用DMA进行数据传输,可以实现gd32f3adc多通道采样。在读取数据时,需要根据转换序列的长度来确定读取的数据个数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [GD32F190 ADC多通道DMA自动接收踩坑指南](https://blog.csdn.net/shizhibuyi1234/article/details/120511411)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [【GD32F310开发板试用】ADC 规则组连续采样](https://blog.csdn.net/weixin_47569031/article/details/124177006)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值