GD32F303 使用定时器10ms触发ADC+DMA定时采集1024个数据-10s进入DMA中断

涉及到的硬件需求:

一、硬件资源

1、使用外部设备驱动ADC——选用ADC2

ADC框架

2、在使用ADC2,查看哪个timer可以触发ADC,通过下图可以看到timer4通道0可以驱动ADC

2、在使用ADC2,看一下哪个,DMA可以搬运数据,进入用户手册的DMA章节看资源

二、程序部分

0、头文件

#ifndef __BSP_ADC_H__
#define __BSP_ADC_H__

#include "gd32f30x.h"
#include "para_flag.h"
#include "gd32f30x_timer.h"
#include "gd32f30x_dma.h"


#define LASWER_FRE_NUME		1024
#define ADC_CHANNEL_NUMER	2
//PWM
#define ADC_PWM_TMER_RCU	RCU_TIMER4
#define ADC_PWM_TMER		TIMER4
#define ADC_PWM_CH			TIMER_CH_0
//ADC
#define ADC_NUM_CH			ADC2
#define ADC_RCU				RCU_ADC2
#define ADC_EXTTRIG_CH ADC2_EXTTRIG_REGULAR_T4_CH0

void App_AdcSglCfg(wavelength_battery value);
void ADC_init(void);
uint16_t  ADC_meas(void);
 uint16_t filter_motor (uint16_t	barray[LASWER_FRE_NUME][ADC_CHANNEL_NUMER],uint8_t ifilterlen);
#endif // __SW74HC4051_H__

1、时钟函数配置

/*!
    \brief      configure the different system clocks
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void rcu_config(void)
{
    /* enable GPIOA clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA1);
    /* enable TIMER0 clock */
    rcu_periph_clock_enable(ADC_PWM_TMER_RCU);
    /* enable ADC2 clock */
    rcu_periph_clock_enable(ADC_RCU);
    /* config ADC clock */
    rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);
}

2、定时器配置

//Timer4配置初始化
void App_Timer4Cfg(void)
{
     /* TIMER0 配置:产生不同占空比的 PWM 信号: 
       TIMER0CLK = SystemCoreClock / 120 = 1MHz */
    timer_parameter_struct timer_initpara;
	timer_oc_parameter_struct timer_ocintpara;

    rcu_periph_clock_enable(ADC_PWM_TMER_RCU);	//开启定时器时钟
    timer_deinit(ADC_PWM_TMER);		//取消定时器
    /* TIMERX 配置 */
    timer_initpara.prescaler         = 11999;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;		//向上计数
    timer_initpara.period            = 100-1;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(ADC_PWM_TMER,&timer_initpara);
	
	/* CHX configuration in PWM mode0 */
	timer_channel_output_struct_para_init(&timer_ocintpara);
	timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
	timer_channel_output_config(ADC_PWM_TMER,ADC_PWM_CH,&timer_ocintpara);
	
	timer_channel_output_pulse_value_config(ADC_PWM_TMER, ADC_PWM_CH, 50);
    timer_channel_output_mode_config(ADC_PWM_TMER, ADC_PWM_CH, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(ADC_PWM_TMER, ADC_PWM_CH, TIMER_OC_SHADOW_DISABLE);
		
	/* auto-reload preload enable */
    timer_auto_reload_shadow_enable(ADC_PWM_TMER);

}

3、DMA配置

/*!
    \brief      直接存储器存取配置功能
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dma_config(void)
{
	    /* enable DMA clock */
//    rcu_periph_clock_enable(RCU_DMA);
	
    dma_parameter_struct dma_init_struct;

    /* 初始化DMA channel0 */
    dma_deinit(DMA1, DMA_CH4);
    dma_init_struct.direction    = DMA_PERIPHERAL_TO_MEMORY;			/*!< 从外设读取并写入内存 */
    dma_init_struct.memory_addr  = (uint32_t)laser_fre;					//目标地址
    dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;			/*!< 内存的下一个地址是递增地址模式 */
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;			 	/*!< 传输数据的内存大小为16位 */
    dma_init_struct.number       = LASWER_FRE_NUME*ADC_CHANNEL_NUMER;						//传输的个数
    dma_init_struct.periph_addr  = (uint32_t)(&ADC_RDATA(ADC_NUM_CH));		//源地址
    dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;			/*!< 外设的下一个地址为固定地址模式   */
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;			/*!< 外设传输数据大小为16位 */
    dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;				/*!< 超高的优先级 */
    dma_init(DMA1, DMA_CH4, &dma_init_struct);
    /* 配置DMA模式 */
    dma_circulation_enable(DMA1, DMA_CH4);
	//中断配置  
	nvic_irq_enable(DMA1_Channel3_Channel4_IRQn,0,1);
	dma_interrupt_enable(DMA1,DMA_CH4,DMA_INT_FTF);
    /* 支持DMA channel0*/
    dma_channel_enable(DMA1, DMA_CH4);
}

4、ADC配置

//-------------------------------------------------------------------------------
//函数名:App_AdcInit
//输   入:void
//输   出:void
//功   能:ADC 模块初始化,ADCCLK =4MHz,4MHz/28 = 142.8kHz
//-----------------------------------------------------------------------------
void App_AdcInit(void)
{
	adc_deinit(ADC_NUM_CH);
	/* 开启ADC扫描模式功能 */
    adc_special_function_config(ADC_NUM_CH, ADC_SCAN_MODE, ENABLE);
	/* ADC通道数量配置 */
	adc_channel_length_config(ADC_NUM_CH,ADC_REGULAR_CHANNEL, 2);
	/* ADC常规通道配置 */
	adc_regular_channel_config(ADC_NUM_CH,0, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);
	adc_regular_channel_config(ADC_NUM_CH,1, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
//	adc_regular_channel_config(ADC_NUM_CH,2, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
	/* ADC外部触发启用 */
	adc_external_trigger_config(ADC_NUM_CH,ADC_REGULAR_CHANNEL, ENABLE);
	/* ADC外部触发源配置 */
	adc_external_trigger_source_config(ADC_NUM_CH,ADC_REGULAR_CHANNEL, ADC_EXTTRIG_CH);


	//注入组
	//	adc_channel_length_config(ADC_INSERTED_CHANNEL, 1);
	//	adc_inserted_channel_config(0, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
	//	adc_external_trigger_source_config(ADC_INSERTED_CHANNEL, ADC_EXTTRIG_INSERTED_T14_TRGO);
	//	adc_external_trigger_config(ADC_INSERTED_CHANNEL, ENABLE);

	adc_resolution_config(ADC_NUM_CH,ADC_RESOLUTION_12B);
	/* ADC数据对齐配置 */
	adc_data_alignment_config(ADC_NUM_CH,ADC_DATAALIGN_RIGHT);
	/* 启用ADC接口 */
	adc_enable(ADC_NUM_CH);
	/* ADC校准和复位校准 */
	adc_calibration_enable(ADC_NUM_CH);
	/* ADC DMA功能使能 */
	adc_dma_mode_enable(ADC_NUM_CH);
}

5、端口配置

/*
*********************************************************************************************************
*	函 数 名: void App_datacollection_PORT_init(void)
*	功能说明: 数据采集端口配置
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void App_datacollection_PORT_init(void)
{
    /*configure PA8(TIMER0 CH0) as alternate function*/
    gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_1);
	gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_0);
}

 6、ADC全部初始化

//ADC初始化
void ADC_init(void)
{
	rcu_config();
	App_datacollection_PORT_init();//端口初始化
	App_Timer4Cfg();
	dma_config();
	App_AdcInit();//模块初始化
	timer_enable(ADC_PWM_TMER);
}

7、滤波函数

//-------------------------------------------------------------------------------
//函数名:filter_bat
//输   入:time 延时循环的次数
//输   出:void
//功   能:中位值平均滤波法
//-----------------------------------------------------------------------------
uint16_t filter_bat (uint16_t  barray[LASWER_FRE_NUME][ADC_CHANNEL_NUMER],uint8_t ifilterlen)
{
	unsigned char i,j;
	uint16_t btemp = 0;
	uint16_t sum = 0;
	//用冒泡法对数组进行排序
	for (j = FILER_MID; j < ifilterlen-1+FILER_MID; ++j)
		{
		for (i = FILER_MID; i < ifilterlen-1+FILER_MID; ++i)
			{
			if (barray[i][0]>barray[i+1][0])
				{
				btemp =barray[i][0];
				barray[i][0]=barray[i+1][0];
				barray[i+1][0]=btemp;
				}
			}
		}
		//累加
		for(i = 3+FILER_MID;i< ifilterlen-3+FILER_MID;i++)
		{
			sum =sum + barray[i][0];
		}
	return (sum>>2);
}

8、DMA中断服务函数

//当传输完成足够的数据后,就关闭定时器,设置标志位,进行处理,可以在中断中处理,
void DMA1_Channel3_4_IRQHandler(void)
{
    //传输完成标志位
    if(dma_interrupt_flag_get(DMA1,DMA_CH4, DMA_INT_FLAG_FTF))
    {     
        //关闭定时器,停止继续读取数据
       timer_channel_output_mode_config(ADC_PWM_TMER, ADC_PWM_CH, TIMER_OC_MODE_HIGH);
		//清除全部标志位
        dma_interrupt_flag_clear(DMA1,DMA_CH4, DMA_INT_FLAG_G);
        //设置标志位 DMA完成了 
        Lcd_flag.battery_adc_flag = true;
    }
  
}

9、数据采集

/*
*********************************************************************************************************
*	函 数 名: ADC_meas
*	功能说明: 电池电量ADC采集
*	形     参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
uint16_t  ADC_meas(void)
{
		unsigned int j,ad_data = 0;	
		static bool adc_init_flag = false ;
		static uint16_t adc_battery_data = 0;
		//返回数据
		if (Lcd_flag.battery_adc_flag == true)
			{
				adc_battery_data =  filter_bat(laser_fre, 10);
			}
		//采集数据
		if (Lcd_flag.battery_adc_flag ==true  || adc_init_flag == false)
			{
				Lcd_flag.battery_adc_flag = false;
				adc_init_flag = true;
				timer_channel_output_mode_config(ADC_PWM_TMER, ADC_PWM_CH, TIMER_OC_MODE_PWM1);
			}
		return adc_battery_data;
}

目录

一、硬件资源

1、使用外部设备驱动ADC——选用ADC2

2、在使用ADC2,查看哪个timer可以触发ADC,通过下图可以看到timer4通道0可以驱动ADC

2、在使用ADC2,看一下哪个,DMA可以搬运数据,进入用户手册的DMA章节看资源

二、程序部分

0、头文件

1、时钟函数配置

2、定时器配置

3、DMA配置

4、ADC配置

5、端口配置

 6、ADC全部初始化

7、滤波函数

8、DMA中断服务函数

9、数据采集


  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值