STM32 HAL库ADC采样(使用内部基准电压)
当我们采用内部基准电压时,首先应了解下内部基准电压的用法,根据STM32L476参考手册我们得知:
解析:
VDDA:实际电压参考值,由上式计算得出,用来计算我们需要的采样电压值,下边会用到;
VREFINT_CAL:内部电压参考校准值,每个芯片都不一样,例如我的STM32L476则存在0x1FFF75AA—–0x1FFF75AB中,我们可以读出来:
#define VREFINT_CAL (uint16_t)(*(__I uint16_t *)(0x1FFF75AA))
在数据手册中我们可以查到校准值的存储位置,如下图:
VERFINT_DATA:ADC转换后的实际VREFINT输出值,我们可以通过ADC的通道17读出来,该值在1.2V左右:
到这里我们就可以得到实时的参考电压值VDDA,既然确定了VDDA的值,我们便可以通过下式来计算我们实际测量的电压值:
解析:
VREFINT_CAL:固定值,我的芯片读出来是0x0681(上边有读取方法);
ADCx_DATA:ADC在通道X上测量的值(右对齐);
VREF_DATA:ADC转换后的实际VREFINT输出值,我们可以通过ADC的通道17读出来,该值在1.2V左右;
FULL_SCALE:ADC输出的最大数字值。例如12位分辨率,它将是212−1=4095或8位分辨率,28−1=255。
有了以上的基础,我们便可以通过配置CubeMX来产生我们需要的代码如下图:(大家可以根据自己的需求来选择相应的通道)
配置为扫描模式,连续模式关闭,间断模式开启,间断分组为1,转换数设置为3,并配置每个RANK:
然后生成代码:
/* ### - 2 - Start calibration ############################################ */
if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
{
Error_Handler();
}
for(int i=0;i<3;i++)
{
if(HAL_ADC_Start(&hadc1) != HAL_OK)//开始转换
{
/* Start Conversation Error */
Error_Handler();
}
HAL_ADC_PollForConversion(&hadc1, 10);//等待常规组转换完成
/* Check if the continous conversion of regular channel is finished */
if ((HAL_ADC_GetState(&hadc1) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)
{
/*##-6- Get the converted value of regular channel ########################*/
V1[i] = HAL_ADC_GetValue(&hadc1);
}
}
HAL_ADC_Stop(&hadc1);
VI1[0] = 3.0*VREFINT_CAL*V1[0]/V1[2]/4095;
VI1[1] = 3.0*VREFINT_CAL*V1[1]/V1[2]/4095;
HAL_Delay(2000);
这里V1[0]、V1[1]、就是我通道6,通道7的测量值,V1[2]就是内部参考电压值,故根据:
便可以计算的出自己所需要的值。
多通道DMA方式配置:配置为扫描模式,连续模式,使能DMA连续请求,其他保持不变
生成代码:
uint32_t ADC_ConvertedValue[3];//定义数组用来接收数据
if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)//校准
{ Error_Handler();}
if (HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_ConvertedValue,3 ) != HAL_OK)//启用ADC,开始常规组的转换,并通过DMA传输结果。
{ Error_Handler();}
while(!(__HAL_DMA_GET_FLAG(&hdma_adc1,DMA_FLAG_TC1))){;}//等待DMA转换完成
__HAL_DMA_CLEAR_FLAG(&hdma_adc1,DMA_FLAG_TC1);//清楚DMA标志位
// HAL_Delay (10);
HAL_ADC_Stop_DMA(&hadc1);//停止ADC常规组转换,禁用ADC DMA传输
HAL_Delay(2000);
这里有几点需要特别注意:
在使用DMA时:1、需要先初始化DMA,再初始化ADC;
2、在CubeMX配置Data Width为WORD时,数组ADC_ConvertedValue应该定义为uint32_t,否则配置Data Width为HALF WORD时,数组ADC_ConvertedValue应该定义为uint16_t.
作者:小白小菜。