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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先申明,本栏目用的都是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);
					}
<think>好的,我需要帮助用户找到GD32F470ZIT6芯片使用DMA发送中断的代码示例。首先,我应该回顾一下GD32DMA配置中断处理流程。根据用户提供的引用[1],DMA必须在I2C传输开始前配置使能,传输完成后会触发中断。这可能涉及到DMA通道的配置、中断服务函数的设置以及相关寄存器的操作。 接下来,我需要确保代码示例符合GD32F4系列的标准使用方式。通常,GD32的代码结构包括初始化外设(如I2C)、配置DMA通道、设置中断优先级并启用中断,最后启动传输。用户可能需要具体的代码片段,包括DMA初始化中断处理函数。 还要注意,DMA发送中断可能涉及到传输完成中断(TC)或半传输中断(HT),但根据用户需求,应该是传输完成中断。需要确认在DMA配置中使能相应的中断标志,并在中断服务函数中处理EOT信号,如引用[1]所述。 另外,引用[2]提到用户手册的下载地址,可能需要查阅手册中的DMA章节I2C章节,确认寄存器配置是否正确。例如,DMAx_CHxCTL寄存器中的CHEN位、M2M模式、传输宽度、中断使能位等。 最后,代码示例应包括主函数中的初始化步骤、DMA配置函数、中断服务函数的实现,以及可能的回调函数处理。确保示例代码结构清晰,注释详细,方便用户理解移植到自己的项目中。</think>以下是基于GD32F470ZIT6芯片的DMA发送中断代码示例及配置说明,结合用户手册[^2]DMA配置规范[^1]: ### 一、DMA发送中断配置步骤 1. **外设时钟使能** ```c rcu_periph_clock_enable(RCU_DMAx); // 根据实际DMA通道选择 rcu_periph_clock_enable(RCU_对应的外设); // 如I2C/USART等 ``` 2. **DMA通道参数配置** ```c dma_parameter_struct dma_init_struct; dma_struct_para_init(&dma_init_struct); dma_init_struct.periph_addr = (uint32_t)&外设数据寄存器地址; // 如I2CDATA dma_init_struct.memory_addr = (uint32_t)发送缓冲区地址; dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; dma_init_struct.number = 数据长度; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.periph_width = 外设数据宽度; // DMA_PERIPHERAL_WIDTH_8BIT dma_init_struct.memory_width = 内存数据宽度; // DMA_MEMORY_WIDTH_8BIT dma_init_struct.priority = DMA_PRIORITY_LEVEL; dma_init(DMAx_CHy, &dma_init_struct); ``` 3. **中断配置** ```c dma_interrupt_enable(DMAx_CHy, DMA_INT_FTF); // 使能传输完成中断 nvic_irq_enable(DMAx_Channely_IRQn, 0, 0); // 使能NVIC中断 ``` ### 二、DMA中断服务函数模板 ```c void DMAx_Channely_IRQHandler(void) { if(dma_interrupt_flag_get(DMAx_CHy, DMA_INT_FLAG_FTF)){ dma_interrupt_flag_clear(DMAx_CHy, DMA_INT_FLAG_FTF); /* 用户处理代码 */ if(dma_transfer_number_get(DMAx_CHy) == 0){ // 传输完成处理 dma_channel_disable(DMAx_CHy); // 关闭DMA通道 } } } ``` ### 三、典型应用示例(以I2C+DMA发送为例) ```c #define TRANSFER_SIZE 128 uint8_t tx_buffer[TRANSFER_SIZE]; void i2c_dma_config(void) { /* I2C配置(略) */ /* DMA配置 */ dma_parameter_struct dma_init_struct; dma_deinit(DMA0, DMA_CH0); dma_init_struct.periph_addr = (uint32_t)&I2CDATA(I2C0); dma_init_struct.memory_addr = (uint32_t)tx_buffer; dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; dma_init_struct.number = TRANSFER_SIZE; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH0, &dma_init_struct); /* 配置DMA中断 */ dma_interrupt_enable(DMA0, DMA_CH0, DMA_INT_FTF); nvic_irq_enable(DMA0_Channel0_IRQn, 1, 0); /* 启动DMA传输 */ dma_channel_enable(DMA0, DMA_CH0); i2c_dma_enable(I2C0, I2C_DMA_ON); } ``` ### 关键配置说明: 1. **DMA触发方式**:需与外设事件对齐,如I2C的TX事件触发DMA请求[^1] 2. **中断清除时序**:必须在中断服务函数中先检查标志位再清除标志 3. **内存管理**:确保发送缓冲区在DMA传输期间保持有效 4. **错误处理**:建议添加传输错误中断处理(DMA_INT_ERR) 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值