10-HAL库之ADC电压采集

 

1.简介函数

12位ADC是逐次趋近型模数转换器,有19个复用通道(可测量16个外部源,2个内部源和1个VBAT通道的信号)。A/D转换可在单次、连续、扫描或不连续采样模式下进行,采样结果存储在1个16位数据寄存器中(实际只有12位数据)。ui

规则通道:通常所使用的通道;code

注入通道:在规则通道转换时强行插入转换的通道,相似于中断。blog

ADC支持外部事件触发,包括内部定时器和外部IO。ADC输入时钟ADC_CLK由PCKL2通过分频产生,最大值是二分频54MHz,ADC容许最大值36MHz,典型值30MHz。排序

ADC的总转换时间=采样时间+12个周期.事件

ADC转换后数据存放在ADC_DR寄存器(规则转换)或JDRx中(注入转换),双重或三次模式则放在规矩寄存器ADC_CDR中。内存

ADC_DR只有一个,为32位寄存器且低16位优秀,之用于独立模式存放转换完成的数据。因为规则通道有16个,多通道转换时,须要开启DMA传输,将通道转换完成的数据传输到内存,避免被覆盖。input

电压转换:当设置ADC为12位时,12位满量程对应3.3V输入电压,而对应数字之为2^12。若转换后的数值为X,则转换前的模拟电压Y=(3.3*X)/2^12。it

2.配置步骤及相关函数io

配置步骤为:引脚配置,相关时钟使能,ADC初始化,ADC通道配置,DMA使能,启动ADC。

ADC初始化结构体:

typedef struct
{
  uint32_t ClockPrescaler;        //时钟分频系数
  uint32_t Resolution;            //分辨率
  uint32_t DataAlign;             //数据对齐模式
  uint32_t ScanConvMode;          //扫描模式
  uint32_t EOCSelection;          //转换结束标志选择
  uint32_t ContinuousConvMode;     //连续转换模式
  uint32_t NbrOfConversion;        //转换数量
  uint32_t DiscontinuousConvMode;  //由事件触发后,选择连续模式
  uint32_t NbrOfDiscConversion;    //连续模式转换通道的数量
  uint32_t ExternalTrigConv;       //外部触发事件选择
  uint32_t ExternalTrigConvEdge;
  uint32_t DMAContinuousRequests;
}ADC_InitTypeDef;

ADC通道配置结构体:

typedef struct 
{
  uint32_t Channel;       //通道选择
  uint32_t Rank;          //排序
  uint32_t SamplingTime;  //采样时间
  uint32_t Offset;        
}ADC_ChannelConfTypeDef;

此外还有众多输出控制函数:

3.配置代码

#include "adc.h"

	ADC_HandleTypeDef adc1;
	ADC_ChannelConfTypeDef adc1_chan1;

void ADC_Config(void){
	
	HAL_ADC_MspInit(&adc1);

	GPIO_InitTypeDef GPIO_InitStruct;
  __HAL_RCC_GPIOA_CLK_ENABLE();
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	//GPIO Config
	
	__HAL_RCC_ADC1_CLK_ENABLE();
	adc1.Instance=ADC1;	
	adc1.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;
	adc1.Init.Resolution=ADC_RESOLUTION_12B;
	adc1.Init.ScanConvMode=ADC_SCAN_DISABLE;
	adc1.Init.ExternalTrigConv=ADC_SOFTWARE_START;
	adc1.Init.ExternalTrigConvEdge=ADC_SOFTWARE_START;
	adc1.Init.DataAlign=ADC_DATAALIGN_LEFT;
	adc1.Init.EOCSelection=ADC_EOC_SEQ_CONV;
	adc1.Init.EOCSelection=ADC_EOC_SINGLE_CONV;
	HAL_ADC_Init(&adc1);
		
	adc1_chan1.Channel=ADC_CHANNEL_0;
	adc1_chan1.Rank=ADC_REGULAR_RANK_1;
	adc1_chan1.SamplingTime=ADC_SAMPLETIME_144CYCLES;
	adc1_chan1.Offset=0;
	HAL_ADC_ConfigChannel(&adc1,&adc1_chan1);	

	HAL_NVIC_SetPriority(ADC_IRQn,1,1);
	HAL_NVIC_EnableIRQ(ADC_IRQn);
	HAL_ADC_Start_IT(&adc1);
}
int main(void)    
{
  HAL_Init();
  Sysclk_config();
	USART1_UART_Init(19200);
	printf("USART1 CONFIG!\n");
	Basic_Tim_Config();
	printf("TIM6 CONFIG!\n");
	ADC_Config();
	printf("ADC CONFIG!\n");
	HAL_TIM_Base_Start_IT(&Basic_Tim6);//开启定时器6和更新中断
	while(1)
	{
		adc_data=(float)adc_value*(float)3.3/4096;
		printf("The input volatage is: %f\n",adc_data);
	}

}


void ADC_IRQnHandler(void)
{
	HAL_ADC_IRQHandler(&adc1);
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	adc_value=HAL_ADC_GetValue(&adc1);
}