实现参考STM32F7实现ADC采集(软件触发+轮询)
注意,在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 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("hellorn"); MX_ADC1_Init(); while (1) { adcx = Get_Adc_Average(ADC_CHANNEL_19, 20); //获取通道19的转换值,20次取平均 printf("adcx:%drn",adcx); delay_ms(500); } }
上一篇:STM32H7模拟量引脚分布
下一篇:J-Link V6.30h Device Selection 无法识别到STM32H743VITx芯片
推荐阅读最新更新时间:2024-11-03 09:05
设计资源 培训 开发板 精华推荐
- LTC2862AIS8-1 网络的典型应用,用于针对 5kV 浪涌、5kV EFT 和 30kV IEC ESD Plus ±360V 过压保护的 IEC 4 级保护
- LTC3630AMPDHC 4V 至 63V 输入至 -12V 输出、正负转换器的典型应用电路
- MC78M20CTG 20V可调输出稳压器的典型应用
- 使用 ROHM Semiconductor 的 BD46462 的参考设计
- EVAL-AD5445EBZ,使用 AD5445、12 位、高带宽乘法 DAC 和并行接口的评估板
- LTC3638EMSE 高效 250mA 降压型稳压器的典型应用电路
- NCP702MX33TCGEVB,NCP702 3.3V DC 至 DC 单路输出电源评估板
- #第六届立创电赛#PC性能监视器
- LT1366 的典型应用 - 双路精密轨至轨输入和输出运算放大器
- 单片机最小系统板-STM8S001J3M3