注意,在CubeMX中,void SystemClock_Config(void)
多了如下代码:
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_CKPER;
PeriphClkInitStruct.CkperClockSelection = RCC_CLKPSOURCE_HSE;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
查看HAL_RCCEx_PeriphCLKConfig
函数中关于adc的部分:
/*---------------------------- ADC configuration -------------------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
{
switch(PeriphClkInit->AdcClockSelection)
{
case RCC_ADCCLKSOURCE_PLL2: /* PLL2 is used as clock source for ADC*/
ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2),DIVIDER_P_UPDATE);
/* ADC clock source configuration done later after clock selection check */
break;
case RCC_ADCCLKSOURCE_PLL3: /* PLL3 is used as clock source for ADC*/
ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3),DIVIDER_R_UPDATE);
/* ADC clock source configuration done later after clock selection check */
break;
case RCC_ADCCLKSOURCE_CLKP:
/* HSI, HSE, or CSI oscillator is used as source of ADC clock */
/* ADC clock source configuration done later after clock selection check */
break;
default:
ret = HAL_ERROR;
break;
}
if(ret == HAL_OK)
{
/* Set the source of ADC clock*/
__HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
}
else
{
/* set overall return value */
status = ret;
}
}
而实际上我们只需要在生成HAL_ADC_MspInit
中添加一句核心的__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);//ADC外设时钟选择
就可以了。
ADC的时钟源有三个选项:
/** @defgroup RCCEx_ADC_Clock_Source RCCEx ADC Clock Source
* @{
*/
#define RCC_ADCCLKSOURCE_PLL2 ((uint32_t)0x00000000)
#define RCC_ADCCLKSOURCE_PLL3 RCC_D3CCIPR_ADCSEL_0
#define RCC_ADCCLKSOURCE_CLKP RCC_D3CCIPR_ADCSEL_1
默认将采用RCC_ADCCLKSOURCE_PLL2
,即400M的输入时钟,时钟太快,所以会导致ADC采集出来的数据不会有变化。
全部代码如下:
#include "adc.h"
#include "delay.h"
ADC_HandleTypeDef hadc1;
static void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
//获得ADC值
//ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
//返回值:转换结果
u16 Get_Adc(u32 ch)
{
ADC_ChannelConfTypeDef ADC1_ChanConf;
ADC1_ChanConf.Channel=ch; //通道
ADC1_ChanConf.Rank=ADC_REGULAR_RANK_1; //1个序列
ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_64CYCLES_5; //采样时间
ADC1_ChanConf.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC1_ChanConf.OffsetNumber=ADC_OFFSET_NONE;
ADC1_ChanConf.Offset=0;
HAL_ADC_ConfigChannel(&hadc1,&ADC1_ChanConf); //通道配置
HAL_ADC_Start(&hadc1); //开启ADC
HAL_ADC_PollForConversion(&hadc1,10); //轮询转换
return (u16)HAL_ADC_GetValue(&hadc1); //返回最近一次ADC1规则组的转换结果
}
//获取指定通道的转换值,取times次,然后平均
//times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u32 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV12;
hadc1.Init.Resolution = ADC_RESOLUTION_16B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_19;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC12_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); //ADC外设时钟选择
/**ADC1 GPIO Configuration
PA5 ------> ADC1_INP19
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC12_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA5 ------> ADC1_INP19
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
主程序代码:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "adc.h"
int main(void)
{
u16 adcx;
//Cache_Enable(); //打开L1-Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(200, 2, 2, 2); //设置时钟,400Mhz
delay_init(400); //延时初始化
uart_init(115200); //串口初始化
printf("hello\r\n");
MX_ADC1_Init();
while (1)
{
adcx = Get_Adc_Average(ADC_CHANNEL_19, 20); //获取通道19的转换值,20次取平均
printf("adcx:%d\r\n",adcx);
delay_ms(500);
}
}