立创梁山派GD32F450ZGT6--使用DMA实现多通道ADC采集

这次调试有些久,缺乏的知识很多,最重要的是ADC的引脚配置为浮空之后,如果没有接入东西,其读取的ADC值是不确定的,所以在测试的时候,一定要把对应的电压接入ADC引脚,测量的值才是准确的。

上代码。

adc.c

#include "adc.h"

/***********************
采样次数  30
ADC通道    4
***********************/
uint16_t gt_adc_val[30][4];  //DMA缓冲区
              
// ADC Init
void ADC_DMA_Init(void)
{
    /* DMA初始化功能结构体定义 */
    dma_single_data_parameter_struct dma_single_data_parameter;
	
	/* 使能GPIOC组时钟 */
    rcu_periph_clock_enable(RCU_GPIOC);		
	
	/* 使能ADC0时钟 */
    rcu_periph_clock_enable(RCU_ADC0);		
  
	/* 使能DMA1时钟 */
	rcu_periph_clock_enable(RCU_DMA1);

	/*	配置ADC时钟	*/ 
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);	
	
	/*	配置PC1 PC2 PC3 PC4 为浮空模拟输入模式	*/
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1); // PC1 : ADC012_IN11 
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2); // PC2 : ADC012_IN12 
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3); // PC3 : ADC012_IN13 
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4); // PC4 : ADC012_IN14 

	/*	配置ADC为独立模式	*/
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
	
    /*	使能连续转换模式	*/
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
	 
    /*	使能扫描模式	*/
    adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
   
	/*	数据右对齐	*/        
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    
    /*	ADC0设置为规则组  一共使用2个通道		*/  
    adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 4);
		
    /*	ADC规则通道配置:ADC0的通道11,12,13,14的扫描顺序分别为0,1,2,3;采样时间:15个周期		*/  
	/*	DMA开启之后 gt_adc_val[x][0] = PC1的数据   gt_adc_val[x][3] = PC4的数据  x的范围0-29 */
    adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_11, ADC_SAMPLETIME_15);//PC1
    adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_12, ADC_SAMPLETIME_15);//PC2
	adc_regular_channel_config(ADC0, 2, ADC_CHANNEL_13, ADC_SAMPLETIME_15);//PC3
	adc_regular_channel_config(ADC0, 3, ADC_CHANNEL_14, ADC_SAMPLETIME_15);//PC4

	/*	ADC0设置为12位分辨率		*/  
	adc_resolution_config(ADC0, ADC_RESOLUTION_12B); 
	
	/*	ADC外部触发禁用, 即只能使用软件触发		*/  
    adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
    
    /*	使能规则组通道每转换完成一个就发送一次DMA请求		*/  
    adc_dma_request_after_last_enable(ADC0);  
    
	/*	使能DMA请求		*/  
	adc_dma_mode_enable(ADC0);
    
	/*	使能DMA		*/  	
	adc_enable(ADC0);
    
	/*	等待ADC稳定		*/  
	delay_1ms(1);
    
	/*	开启ADC自校准		*/
    adc_calibration_enable(ADC0); 

    /*	清除 DMA通道0 之前配置 	*/
    dma_deinit(DMA1, DMA_CH0);
   
	/*	DMA初始化配置 	*/
	dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));		//设置DMA传输的外设地址为ADC0基地址
	dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;			//关闭外设地址自增
	dma_single_data_parameter.memory0_addr = (uint32_t)(gt_adc_val);				//设置DMA传输的内存地址为 gt_adc_val数组
	dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;			//开启内存地址自增(因为不止一个通道)
	dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;	//传输的数据位 为 16位
	dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;							//DMA传输方向为 外设往内存
	dma_single_data_parameter.number = 4*30;																//传输的数据长度为:4个通道 * 每个通道采集30次
	dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;									//设置高优先级
	dma_single_data_mode_init(DMA1, DMA_CH0, &dma_single_data_parameter);		//将配置保存至DMA1的通道0
	
	/*	DMA通道外设选择		*/
	/*	数据手册的195页根据PERIEN[2:0]值确定第三个参数,例是100 则为DMA_SUBPERI4  	例是010 则为DMA_SUBPERI2 	*/
	/*	我们是ADC0功能,PERIEN[2:0]值为000,故为DMA_SUBPERI0		*/
	dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);

	/*	使能DMA1通道0循环模式		*/
	dma_circulation_enable(DMA1, DMA_CH0);

	/*	启动DMA1的通道0功能		*/
	dma_channel_enable(DMA1, DMA_CH0); 
	
	/*	开启软件触发ADC转换		*/
	adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); 
}


//对DMA保存的数据进行平均值计算后输出
//传入参数:CHx 第几个扫描的数据 
//         根据前面的配置得知:PC1为0 PC2为1 PC3为2 PC4为3
//返回数据:对应扫描的ADC值
unsigned int Get_Adc_Dma_Value(char CHx)
{
	unsigned char i = 0;
	unsigned int AdcValue = 0;
    
    /* 因为采集30次,故循环30次 */
	for(i=0;i<30;i++)
	{
        /*    累加    */
		AdcValue+=gt_adc_val[i][CHx];
	}
    /* 求平均值 */
	AdcValue=AdcValue/30;
    
	return AdcValue;
}

adc.h

#ifndef _ADC_h_
#define _ADC_h_

#include "gd32f4xx.h"
#include "usart0.h"
#include "stdio.h"
#include "systick.h"


extern uint16_t gt_adc_val[30][4];  //DMA缓冲区

/************************

//之前的单路采集
void ADC_Init(void);
unsigned int Get_ADC_Value(void);

**************************/
void ADC_DMA_Init(void);
unsigned int Get_Adc_Dma_Value(char CHx);

#endif

主函数

#include "gd32f4xx.h"
#include "systick.h"
#include "usart0.h"
#include "stdio.h"
#include "adc.h"

int main(void)
{
	unsigned char temp_buff[200]; 
	unsigned int  show_buff[4];
	
	nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
	systick_config();																	 //系统滴答定时器   定时1MS
	USART1_Init();
	ADC_DMA_Init();         
	USART0_send_String((unsigned char *)"--开始--");
  while(1)  
	{        
		/*	获取数据		*/
		show_buff[0] = Get_Adc_Dma_Value(0);	//根据扫描顺序得知数组[0] = PC1的数据
		show_buff[1] = Get_Adc_Dma_Value(1);	//根据扫描顺序得知数组[1] = PC2的数据
		show_buff[2] = Get_Adc_Dma_Value(2);	//根据扫描顺序得知数组[2] = PC3的数据
		show_buff[3] = Get_Adc_Dma_Value(3);	//根据扫描顺序得知数组[3] = PC4的数据
		
		/*	串口显示数据		*/
		sprintf((char *)temp_buff, "PC1=%d\r\nPC2=%d\r\nPC3=%d\r\nPC4=%d\r\n",\
			show_buff[0], show_buff[1], show_buff[2], show_buff[3]);					
		USART0_send_String(temp_buff);
		
		/*	串口显示刷新太快,加个延时    */
		delay_1ms(1000);
	}    
}

实际效果

对PC1和PC3接入3.3V,因为ADC是12位的,所以最大采集数为4096,实际采集也接近了4096。

对PC2和PC4接入GND,实际采集也接近0。

注意!引脚不能浮空进行采集!不然数据是不确定的!

 

 代码链接:

链接:https://pan.baidu.com/s/15G_t-jW82Ms6FLD_fTCBqw?pwd=1234
提取码:1234
 

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: 您好,使用立创EDA画STM32F103C8T6,您可以按照以下步骤进行操作: 1. 打开立创EDA软件,选择新建工程,选择STM32F103C8T6芯片型号。 2. 在工程中添加所需的元件,例如晶振、电容、电阻等。 3. 连接元件,按照STM32F103C8T6的引脚图进行连接。 4. 进行电路图的布局和连线,确保电路图的正确性。 5. 进行PCB布局,将电路图转换为PCB布局图。 6. 进行PCB连线,确保PCB布局的正确性。 7. 导出Gerber文件,进行PCB制板。 以上是使用立创EDA画STM32F103C8T6的基本步骤,希望对您有所帮助。 ### 回答2: 首先,立创EDA是一款非常实用的电路设计软件,它为STM32F103C8T6这样的单片机设计提供了非常好的支持。使用立创EDA画STM32F103C8T6,需要进行以下步骤: 1. 在电路设计中,要根据STM32F103C8T6的规格书进行针脚的连接。首先,在立创EDA的元器件库中找到STM32F103C8T6,把它拖动到电路图中。这样,STM32F103C8T6就会以缩略图的形式呈现在电路图中。 2. 在STM32F103C8T6上添加必要的外围电路元件,如晶振、稳压器、电容和推挽电阻等。需要注意的是,在添加外围电路元件时,要了解ESTM32F103C8T6芯片的规格书和参考设计。 3. 连接所有元器件和导线。连接时一定要根据芯片规格书和参考设计,以确保电路工作的可靠性。在连接时可以使用EDA自带的自动走线功能,也可以手动连接导线。 4. 进行电路仿真。在完成电路设计后,使用立创EDA自带的仿真功能进行仿真。仿真可模拟器件在电路工作正常时的性能和特性,以便及时发现问题并解决。针对STM32F103C8T6的电路设计可以进行信号仿真和电源仿真。 5. 导出PCB图。当电路设计及其仿真都通过后,可以将电路图导出到PCB绘图软件中进行PCB设计。在完成PCB设计后,再次进行电路仿真以验证PCB设计的正确性。 总而言之,使用立创EDA对STM32F103C8T6进行电路设计,需要对芯片的规格书和参考设计有非常清晰的理解,并严格按照规格书和参考设计进行设计和仿真。同时,要熟练掌握立创EDA的使用方法,以便快速高效地完成电路设计任务。 ### 回答3: 立创EDA是一款非常实用的电路设计软件,可以帮助工程师快速完成各种电路设计和仿真工作,其中也包括了对STM32F103C8T6芯片的支持,下面我们就来讲一下如何使用立创EDA画STM32F103C8T6。 首先,我们需要先下载和安装立创EDA软件。安装完成后,我们需要导入STM32F103C8T6芯片的库文件,以便在设计中使用。在立创EDA的菜单栏中找到“元器件库管理”选项,然后选择STM32F1系列芯片库文件进行导入。 导入完成后,在立创EDA的主界面上方,可以看到“元器件库”按钮,点击后会弹出库文件列表,选择我们导入的STM32F1系列芯片库就可以看到其中包含了STM32F103C8T6芯片。 在设计中,需要用到的元器件可以通过拖动和放置的方式添加进电路图中。对于STM32F103C8T6芯片,我们需要先添加其封装为LQFP48或LQFP64的芯片元件,随后根据需要选择添加其他外围元器件,例如晶振、电容、电阻等等。 添加完元器件后,我们需要进行电路连接,将各个元器件之间的引脚进行连线,建立电路图的逻辑关系。可以通过直接拖动线条的方式或者使用连接工具进行连线。 完成电路连接后,我们需要进行仿真操作,检查电路图的正确性和性能。立创EDA内置了丰富的仿真工具,可以直接在软件中进行电路的测试和调试。使用仿真工具时,需要先进行仿真设置,定义仿真的参数、时钟频率等等。 最后,完成电路设计后,我们需要将其导出为PCB文件,并进行布线、元器件放置和生成制板文件等步骤,最终完成整个电路的设计和制造。 以上就是使用立创EDA画STM32F103C8T6的基本步骤,需要注意的是,需要参考官方文档和芯片资料手册,了解STM32F103C8T6芯片的规格和特性,才能保证电路设计的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老怪.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值