HAL库配置ADC+DMA

一、ADC几种模式

1、扫描模式: 使用STM32CUBEMX配置了多通道后,这一项默认开启且无法设置成关闭。这个模式就是自动扫描你开启的所有通道进行转换,直至转换完。例如你开启了CH0、CH1、CH2、CH3这四个通道,启动转换后ADC会自动将这4个通道全部转换完,但是这种连续性是可以被打断的,所以就引出了间断模式。

2、连续模式: 在CUBE中选中ENABLE就是连续模式,DISABLE就是单次模式。开启连续模式后,ADC的转换不由其他控制。例如将ADC设置为了定时器的TGRO触发采样,如果开启连续模式,ADC将忽略定时器的触发采样。(连续转换模式开启后其实就是满频率的采样)。

3、间断模式: 可以将多个通道进行分组采集,例如你开启了CH0~3这4个通道,假如你设置了间断次数为4,就相当于将4个通道分成了4组,每组1个通道,那么要想采集完这4个通道就需要手动触发4次ADC采集;如果设置了间断次数为2,那么采集完4个通道就需要手动触发2次ADC采集。
 

二、配置ADC单通道采集

通过查看芯片手册,找到IO口对应的通道口

  while (1)
  {
		HAL_ADC_Start(&hadc1);     //启动ADC转换
		HAL_ADC_PollForConversion(&hadc1, 50);   //等待转换完成,50为最大等待时间,单位为ms

		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))//判断ADC转换是否完成
		{
			ADC_Value = HAL_ADC_GetValue(&hadc1);   //获取AD值

			printf("ADC1 Reading : %d \r\n",ADC_Value);
			printf("PA5 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
		}
		HAL_Delay(1000);
  }

三、轮询模式的多通道采集(同单通道)

uint32_t ADC_Get_Average(uint32_t Channel,uint8_t times)
{
	ADC_ChannelConfTypeDef sConfig;		//通道初始化
	uint32_t value_sum=0;	
	uint8_t i;
	sConfig.Channel = Channel;
	sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;		//采用周期239.5周期
	sConfig.Rank = 1;
	HAL_ADC_ConfigChannel(&hadc1,&sConfig);											
	for(i=0;i<times;i++)
	{
		HAL_ADC_Start(&hadc1);								//启动转换
		HAL_ADC_PollForConversion(&hadc1,30);				//等待转化结束
		value_sum += HAL_ADC_GetValue(&hadc1);				//求和					
		HAL_ADC_Stop(&hadc1);								//停止转换
	}
	return value_sum/times;									//返回平均值
}

  while (1)
  {
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_10 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_10,30));
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_11 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_11,30));
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_12 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_12,30));
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_13 AD:%d\r\n\r\n",ADC_Get_Average(ADC_CHANNEL_13,30));
	  HAL_Delay(200);
    /* USER CODE BEGIN 3 */
  }

四、DMA实现多通道采集

4.1 STM32Cubemx配置

(1)Data Alignment--->Right alignment                 此项选择右对齐,保持不变。

(2)Scan Conversion Mode--->Enable                 此项选择扫描模式使能,代表对15路ADC输入分别扫描,如果不使能,其将会只读取一个输入的值。

(3)Continuous Conversion Mode --->Enable        此项选择连续扫描模式,表示将连续不断的对ADC的值进行转换。如果此项不使能,将会只采集一次就会停止,直到下一次使能才继续进行一次ADC转换。

(4)Discontinuous Conversion Mode--->Disable        此项和第三项是重复的。

(5)Number of Conversion---->15                此处有多少路输入就选择多少,而且只有在此处选择数字之后下面才会出来15个不同的通道。而且此处应该是在进入ADC1中第一个需要操作的步骤,否则(2)(3)是灰色的,无法选择使能。

 (6)在出现的15个Rank中,分别配置每一路,例如Rank1配置为Channel 0,采样时间55.5Cycles; Rank2配置为Channel 1,采样时间同样为55.5Cycles。此处的注意事项是,如果你不对每一路进行检查配置,可能出现好多Rank同时采集一个Channel,从而导致AD的采集数据的错误。

4.2 采集一次

uint16_t ADC_Value[5];

HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_Value,sizeof(ADC_Value) / sizeof(ADC_Value[0]));

 while (1)
  {
    /* USER CODE END WHILE */
	  SEGGER_RTT_printf(0,"%d %d %d %d %d\r\n",ADC_Value[0],ADC_Value[1],ADC_Value[2],ADC_Value[3],ADC_Value[4]);
	  HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }

4.3 采集多次求平均值

#define FILTER_NUM 30
#define ADC_CHANNELS 5
uint16_t ADC_ConvertedValue[FILTER_NUM][ADC_CHANNELS];
uint16_t getADC_CH(uint8_t channel)
{
    uint16_t tbuf[FILTER_NUM];
    uint32_t tdat = 0;
    // 判断传入参数是否合法
    if (channel >= ADC_CHANNELS)
    {
        return 0;
    }
    for (int i = 0; i < FILTER_NUM; i++)
    {
        tbuf[i] = ADC_ConvertedValue[i][channel];
    }
    for (int i = 0; i < FILTER_NUM; i++) 
    {
        tdat += tbuf[i]; 
    }
    tdat = tdat/FILTER_NUM; 
    if (tdat < 5)
    {
        tdat = 0;
    }
    return tdat;
}

int main()
{
	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC_ConvertedValue, FILTER_NUM * ADC_CHANNELS);
	while (1)
	{
		for (int i = 0; i < ADC_CHANNELS; i++)
		{
			SEGGER_RTT_printf(0,"getADC_CH[%d] = %d\r\n", i, getADC_CH(i));
		}
		HAL_Delay(1000);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值