GD32F470之ADC0+ADC2+DMA(不中断)+多通道采集+吐槽DMA的库和C++的兼容问题

本文主要介绍了在GD32F470单片机上使用ADC0和ADC2配合DMA进行多通道采集的过程中遇到的C++兼容性问题,包括枚举类型限制及库函数的调整。详细展示了ADC和DMA的配置代码,并提到由于无缓存,数据读取需直接访问adcx_scr_data变量。
摘要由CSDN通过智能技术生成

先申明,本栏目用的都是GD32F470芯片240M,软件用的是keil,编写用的是C++(其实和C没有区别).,

吐槽的点:

1.因为我用的是C++,枚举类型是不能运算的。只能赋值。需要自己修改库函数
在这里插入图片描述
这是我自己的改的:
在这里插入图片描述
2.
GD32的 2016-08-15, V1.0.0, firmware update for GD32F4xx的库,连__cplusplus都写错,后面的新版本就没有了。

在这里插入图片描述
3.
同时如果要用C++,那么就注释掉这句。因为重复编译了。
3.0.0版本的库就没有了这一句。
在这里插入图片描述

ADC0+DMA配置代码:

IO配置:

	  rcu_periph_clock_enable(RCU_GPIOA);
		rcu_periph_clock_enable(RCU_GPIOB);
		//A5 :A
		//A4 : B
		//B1 : C
		gpio_mode_set(GPIOA,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_5|GPIO_PIN_4);
	
	
    gpio_mode_set(GPIOB,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_1);

ADC0寄存器配置:

注意:打开了扫描模式。还要打开连续模式才会一直循环采样
通道号和GPIO引脚的复用功能有关,可以查看芯片手册。
例如
在这里插入图片描述

	rcu_periph_clock_enable(RCU_ADC0);
		   /* config ADC clock */ //120M /4
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);
	
	//IO初始化
		ADC0_Io_Config_Init();
		ADC0_DMA_Config_Init();
		
	/* ADC channel length config */
    adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,ADC0_CHANNEL_NUM);
    /* ADC regular channel config */
  	adc_regular_channel_config(ADC0,0,ADC_CHANNEL_5,ADC_SAMPLETIME_28); //A
    adc_regular_channel_config(ADC0,1,ADC_CHANNEL_4,ADC_SAMPLETIME_28);//B
    adc_regular_channel_config(ADC0,2,ADC_CHANNEL_9,ADC_SAMPLETIME_28);//C

    /* ADC external trigger enable */
    adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,EXTERNAL_TRIGGER_DISABLE);
    /* ADC data alignment config */
    adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
    
    /* enable ADC interface */
    adc_enable(ADC0);
		delay_1ms(1);
    /* ADC calibration and reset calibration */
    adc_calibration_enable(ADC0);
    
    /* ADC DMA function enable */
    adc_dma_mode_enable(ADC0);
    adc_dma_request_after_last_enable(ADC0);
    /* ADC contineous function enable */
		//打开了扫描模式。还要打开连续模式才会一直循环采样
    adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE); 
		adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);
    /* ADC software trigger enable */
  //  adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);

ADC0的DMA配置(不中断):

DMA通道的对应关系可以查看手册
在这里插入图片描述

	rcu_periph_clock_enable(RCU_DMA1);
	    /* ADC_DMA_channel configuration */
    dma_single_data_parameter_struct dma_single_data_parameter_ado0;
    
    /* ADC DMA_channel configuration */
    dma_deinit(DMA1,DMA_CH0);
    
    /* initialize DMA single data mode */
    dma_single_data_parameter_ado0.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
    dma_single_data_parameter_ado0.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_single_data_parameter_ado0.memory0_addr = (uint32_t)(adc0_scr_data);
    dma_single_data_parameter_ado0.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//内存自增
    dma_single_data_parameter_ado0.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;//这位数要和你的adc_value的类型一致
    dma_single_data_parameter_ado0.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
    dma_single_data_parameter_ado0.direction = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter_ado0.number = ADC0_CONVERSION_NUM;
    dma_single_data_parameter_ado0.priority = DMA_PRIORITY_HIGH;
    dma_single_data_mode_init(DMA1,DMA_CH0,&dma_single_data_parameter_ado0);
		
		dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);
	
		#if DMA1_CH0_DONE_INT 
		nvic_irq_enable(DMA1_Channel0_IRQn, 0, 2);
		dma_interrupt_enable(DMA1,DMA_CH0,DMA_CHXCTL_FTFIE);
		#endif
    /* enable DMA channel */
    dma_channel_enable(DMA1,DMA_CH0);

中断函数:

extern "C"void DMA1_Channel0_IRQHandler()
{
		if(SET == dma_interrupt_flag_get(DMA1, DMA_CH0,DMA_INT_FLAG_FTF))
		{
				dma_interrupt_flag_clear(DMA1, DMA_CH0,DMA_INT_FLAG_FTF);
				
			//	adc0_DMA_done_flag=1;
	
				//printf("132131\r\n");
		}
}

ADC2+DMA配置代码:

io配置:

 rcu_periph_clock_enable(RCU_GPIOC);	
		 rcu_periph_clock_enable(RCU_GPIOF);	
		 gpio_mode_set(GPIOF,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8);
	

		 gpio_mode_set(GPIOC,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_0);

ADC2配置:

	rcu_periph_clock_enable(RCU_ADC2);
		   /* config ADC clock */
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);
		//IO初始化
		ADC2_Io_Config_Init();
		ADC2_DMA_Config_Init();

		    /* ADC channel length config */
    adc_channel_length_config(ADC2,ADC_REGULAR_CHANNEL,ADC2_CHANNEL_NUM);
    /* ADC regular channel config */

    adc_regular_channel_config(ADC2,0,ADC_CHANNEL_10,ADC_SAMPLETIME_28);

    adc_regular_channel_config(ADC2,1,ADC_CHANNEL_9,ADC_SAMPLETIME_28);//

    adc_regular_channel_config(ADC2,2,ADC_CHANNEL_15,ADC_SAMPLETIME_28);//

    adc_regular_channel_config(ADC2,3,ADC_CHANNEL_4,ADC_SAMPLETIME_28);//

    adc_regular_channel_config(ADC2,4,ADC_CHANNEL_5,ADC_SAMPLETIME_28);//
	
		adc_regular_channel_config(ADC2,5,ADC_CHANNEL_6,ADC_SAMPLETIME_28);//

    /* ADC external trigger enable */
    adc_external_trigger_config(ADC2,ADC_REGULAR_CHANNEL,EXTERNAL_TRIGGER_DISABLE);
    /* ADC data alignment config */
    adc_data_alignment_config(ADC2,ADC_DATAALIGN_RIGHT);
		
		
		 /* ADC contineous function enable */
		//打开了扫描模式。还要打开连续模式才会一直循环采样
    adc_special_function_config(ADC2,ADC_CONTINUOUS_MODE,ENABLE); 
		adc_special_function_config(ADC2,ADC_SCAN_MODE,ENABLE);
    /* enable ADC interface */
    adc_enable(ADC2);
		delay_1ms(1);
    /* ADC calibration and reset calibration */
    adc_calibration_enable(ADC2);
    
    /* ADC DMA function enable */
    adc_dma_mode_enable(ADC2);
    adc_dma_request_after_last_enable(ADC2);//1:当 DMA=1,在每个规则转换结束时 DMA 机制产生一个 DMA 请求。

    /* ADC software trigger enable */
  //  adc_software_trigger_enable(ADC1,ADC_REGULAR_CHANNEL);

DMA配置(不中断):

	 /* ADC_DMA_channel configuration */
    dma_single_data_parameter_struct dma_single_data_parameter_ado1;
     rcu_periph_clock_enable(RCU_DMA1);
    /* ADC DMA_channel configuration */
    dma_deinit(DMA1,DMA_CH1);
    
    /* initialize DMA single data mode */
    dma_single_data_parameter_ado1.periph_addr = (uint32_t)(&ADC_RDATA(ADC2));
    dma_single_data_parameter_ado1.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_single_data_parameter_ado1.memory0_addr = (uint32_t)(adc2_scr_data);
    dma_single_data_parameter_ado1.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//内存自增
    dma_single_data_parameter_ado1.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;//这位数要和你的adc_value的类型一致
    dma_single_data_parameter_ado1.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
    dma_single_data_parameter_ado1.direction = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter_ado1.number = ADC2_CONVERSION_NUM;
    dma_single_data_parameter_ado1.priority = DMA_PRIORITY_HIGH;
    dma_single_data_mode_init(DMA1,DMA_CH1,&dma_single_data_parameter_ado1);
		
		//用这个来选择外设
		dma_channel_subperipheral_select(DMA1, DMA_CH1, DMA_SUBPERI2);
	
		#if  DMA1_CH1_DONE_INT 
			nvic_irq_enable(DMA1_Channel1_IRQn, 0, 2);
			dma_interrupt_enable(DMA1,DMA_CH1,DMA_CHXCTL_FTFIE);
		#endif
    /* enable DMA channel */
    dma_channel_enable(DMA1,DMA_CH1);

中断函数:


extern "C"void DMA1_Channel1_IRQHandler()
{
		if(SET == dma_interrupt_flag_get(DMA1, DMA_CH1,DMA_INT_FLAG_FTF))
		{
				dma_interrupt_flag_clear(DMA1, DMA_CH1,DMA_INT_FLAG_FTF);
				
			//	adc2_DMA_done_flag=1;
	
				//printf("132131\r\n");
		}
}

结束:

由于没有cache,所以需要取数据的时候就直接读取adcx_scr_data就好就好了。
adcx_scr_data就是adc0_scr_data和adc2_scr_data

if(dma_flag_get(DMA1,DMA_CH1,DMA_INTF_FTFIF))
			{
		
					dma_flag_clear(DMA1,DMA_CH1,DMA_INTC_FTFIFC);
					}
GD32F470通道ADC正负电压采样代码可以参考以下步骤: 1. 配置ADC模块,包括时钟、采样时间等; 2. 配置ADC通道,选择采样的通道和采样模式(单次/连续); 3. 配置ADC触发源(软件/硬件触发); 4. 开启ADC; 5. 等待ADC采样完成; 6. 读取ADC采样结果,并进行转换。 下面是一个简单的示例代码,可以参考: ```c #include "gd32f4xx.h" void adc_config(void) { /* 使能 ADC 时钟 */ rcu_periph_clock_enable(RCU_ADC0); /* 配置 ADC 时钟分频和工作模式 */ adc_clock_config(ADC_ADCCK_PCLK2_DIV8, ADC_MODE_FREE); /* 配置 ADC 采样时间 */ adc_sample_time_config(ADC0, ADC_CHANNEL_0, ADC_SAMPLETIME_15); /* 配置 ADC 通道 */ adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_15); /* 配置 ADC 触发源为软件触发 */ adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC_EXTERNAL_TRIGGER_SOURCE_SOFTWARE); /* 配置 ADC 工作模式为单次转换模式 */ adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE); adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE); adc_special_function_config(ADC0, ADC_DISCONTINUOUS_MODE, DISABLE); /* 使能 ADC */ adc_enable(ADC0); } uint16_t adc_sample(void) { /* 开始 ADC 转换 */ adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); /* 等待转换完成 */ while (SET != adc_flag_get(ADC0, ADC_FLAG_EOC)); /* 读取采样结果 */ return adc_regular_data_read(ADC0); } int main(void) { /* 初始化 GPIO 和 ADC */ // ... /* 配置 ADC */ adc_config(); while (1) { /* 进行采样 */ uint16_t result = adc_sample(); /* 转换采样结果 */ float voltage = (float)result * 3.3 / 4096; /* 处理采样结果 */ // ... } } ``` 相关问题: 1. GD32F470支持哪些ADC采样模式? 2. 如何配置GD32F470ADC通道? 3. 如何使用硬件触发进行ADC转换?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值