STM32CubeMx采集多路ADC

转载于https://blog.csdn.net/qq_24815615/article/details/70227385
原文地址https://www.eemaker.com/stm32cubemxadc.html

单片机为:STM32F103RCT6
软件:STM32CubeMX,MDK

功能:不使用DMA,不使用中断,读取ADC1内部温度传感器及内部参照电压VREFINT的值

描述:温度传感器和通道ADC1_IN16相连接,内部参照电压VREFINT和ADC1_IN17相连接。可以按注入或规则通道对这两个内部通道进行转换。注意: 温度传感器和VREFINT只能出现在主ADC1中。
内部温度传感器温度计算公式:
温度C = (V25 - Vsence)/Avg_Slope + 25
V25 = Vsence在25°C时的数值,典型值为1.43V
Avg_Slope = 温度与VSENSE曲线的平均斜率(单位为mV/ °C 或 μV/ °C),典型值为4.3mv/C
Vsence为读取内部温度传感器的AD值3.3/4096
所以最终公式为:
C = (1.43 - tempadc
3.3/4096)*1000/4.3 + 25;

ADC采集的几个概念:
扫描模式(想采集多通道必须开启):是一次对所选中的通道进行转换,比如开了ch0,ch1,ch4,ch5。ch0转换完以后就会自动转换通道1,4,5直到转换完。但是这种连续性并不是不能被打断。这就引入了间断模式。

间断模式:可以说是对扫描模式的一种补充。它可以把0,1,4,5这四个通道进行分组。可以分成0,1一组,4,5一组。也可以每个通道配置为一组。这样每一组转换之前都需要先触发一次。

单次模式和连续模式:这两中模式的概念是相对应的。这里的单次模式并不是指一个通道。假如你同时开了ch0,ch1,ch4,ch5这四个通道。单次模式转换模式下会把这四个通道采集一边就停止了。而连续模式就是这四个通道转换完以后再循环过来再从ch0开始。

规则组和注入组:规则通道相当于你正常运行的程序,而注入通道就相当于中断。即注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。

下面配置CubeMx来生成程序:
1,选择ADC1的通道
在这里插入图片描述2,配置ADC1的参数
在这里插入图片描述 经过测试,要想用非dma和非中断模式只有这样配置可以正确进行多通道转换:扫描模式+单次转换模式+间断转换模式(每个间断组一个通道)。

分析配置成这样的模式,扫描模式是在配置为多个通道必须打开的,stm32cubeMX上也默认好了,只能enable。单次转换模式是我不需要不停的去采集每个通道值,而是把2个通道采集完以后就让它停止。这里间断配置是关键,间断模式可以让扫描的2个通道进行分成2个组,stm32cubeMX参数里面number of Discontinous Conversions是配置间断组每个组有几个通道的,这里必须配置为1(否则在获取ad值得时候只能读取到每个间断组最后一个通道)。

生成mdk工程代码。初始化ADC代码如下:

ADC_HandleTypeDef hadc1;

/* ADC1 init function */
void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;
	
    /**Common config 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = ENABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  
    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  
    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}

这时候还没有完成,只是实现了ADC的初始化,需要采集这2个通道值得函数还要自己写。下面就采集这2个通道的函数:

uint8_t Get_Adc_Val(uint16_t *V, uint16_t *T)
{
	uint16_t adc[2];
	uint8_t i;

	for(i=0; i<2; i++)
	{
		HAL_ADC_Start(&hadc1);
		if(HAL_ADC_PollForConversion(&hadc1, 1000) == HAL_OK)
		{
			adc[i] = HAL_ADC_GetValue(&hadc1);
		}		
	}
	HAL_ADC_Stop(&hadc1);
	
	*V = adc[0];
	*T = adc[1];
    return 0;
}

调用hal库接口函数也需要注意,HAL_ADC_Start一定要放在for里面,即每一个通道都要触发。2个通道都采集完了,再去调用HAL_ADC_Stop(&hadc1); 结束本次ADC采集。

最后说下,这个是针对stm32F103系列的芯片,其他型号的配置可能略有不同,大体思路一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值