STM32L476 DMA读取ADC1通道1,PC0的值始终为零
/***********ADC.c**************/
#include "adc.h"
#include "delay.h"
#include "usart2.h"
ADC_ChannelConfTypeDef sConfig = {0};
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
u16 uhADCxConvertedValue = 0;
#define DMA1_MODE 0 //0 DMA模式 1 普通ADC模式
void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE(); // DMA 时钟初始化
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 1); //DMA 中断初始化
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); //DMA1_Channel1_IRQn 中断配置
}
/**
* @brief 初始化ADC函数
*
* @param void
*
* @return void
*/
void ADC_Init(void)
{
//#if DMA1_MODE
///**********************************普通模式***********************************/
// hadc1.Instance = ADC1;
// hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; //2分频,ADCCLK=SYSCLK/2=64/2=32MHZ
// hadc1.Init.Resolution = ADC_RESOLUTION_12B; //12位模式
// hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
// hadc1.Init.ScanConvMode = DISABLE; //非扫描模式
// hadc1.Init.EOCSelection = DISABLE; //关闭EOC中断
// hadc1.Init.ContinuousConvMode = DISABLE; //关闭连续转换
// hadc1.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1
// hadc1.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
// hadc1.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0
// hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
// hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
// hadc1.Init.LowPowerAutoWait = DISABLE;
// hadc1.Init.DMAContinuousRequests = DISABLE;
// hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
// hadc1.Init.OversamplingMode = DISABLE;
// hadc1.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
// HAL_ADC_Init(&hadc1); //初始化
///************************************************************************************/
//#else
/***************************************DMA*********************************************/
ADC_MultiModeTypeDef multimode = {0};
// ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
u2_printf("错误1
");
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
u2_printf("错误2
");
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
u2_printf("错误3
");
}
/************************************************************************************/
//#endif
}
/**
* @brief ADC底层驱动,引脚配置,时钟使能,此函数会被HAL_ADC_Init()调用
*
* @param hadc ADC句柄
*
* @return void
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
//#if DMA1_MODE
///************************************普通模式******************************************/
// RCC_PeriphCLKInitTypeDef PeriphClkInit;
// GPIO_InitTypeDef GPIO_InitStruct;
// //选择ADC时钟源为SYSCLK(64Mhz)
// PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
// PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
// HAL_RCCEx_PeriphCLKConfig(&amperiphClkInit);
//
// __HAL_RCC_ADC_CLK_ENABLE(); //使能ADC1时钟
// __HAL_RCC_GPIOA_CLK_ENABLE();
// __HAL_RCC_GPIOC_CLK_ENABLE();
// __HAL_RCC_GPIOB_CLK_ENABLE();
// /**ADC1 GPIO Configuration
// PA4 ------> ADC1_IN9
// PA5 ------> ADC1_IN10
// PA6 ------> ADC1_IN11
// PA7 ------> ADC1_IN12
// PC4 ------> ADC1_IN13
// PC5 ------> ADC1_IN14
// PB0 ------> ADC1_IN15
// PB1 ------> ADC1_IN16
// */
// GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
// GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
// GPIO_InitStruct.Pull = GPIO_NOPULL;
// HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_0;
// GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
// GPIO_InitStruct.Pull = GPIO_NOPULL;
// HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
// GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
// GPIO_InitStruct.Pull = GPIO_NOPULL;
// HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
///************************************普通模式******************************************/
//#else
/************************************DMA模式******************************************/
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_ADC_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**ADC1 GPIO Configuration
PC0 ------> ADC1_IN1
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Request = DMA_REQUEST_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
u2_printf("错误4
");
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
/************************************DMA模式******************************************/
//#endif
}
/**
* @brief 获得ADC值
*
* @param ch 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
*
* @return u16 转换结果
*/
u16 Get_Adc(u32 ch)
{
sConfig.Channel = ch; //通道
sConfig.Rank = ADC_REGULAR_RANK_1; //第1个序列,序列1
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; //采样时间
sConfig.SingleDiff = ADC_SINGLE_ENDED; //ADC单端输入
sConfig.OffsetNumber = ADC_OFFSET_NONE; //偏移号选择
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(&hadc1, &sConfig); //通道配置
HAL_ADC_Start(&hadc1); //开启ADC
HAL_ADC_PollForConversion(&hadc1, 10); //轮询转换
return (u16)HAL_ADC_GetValue(&hadc1); //返回最近一次ADC1规则组的转换结果
}
/**
* @brief 获取指定通道的转换值,取times次,然后平均
*
* @param ch 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
* @param times 获取次数
*
* @return u16 通道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;
}
/********************ADC.H**************************/
#ifndef __ADC_H
#define __ADC_H
#include &quot;sys.h&quot;
void MX_DMA_Init(void);
void ADC_Init(void); //ADC通道初始化
u16 Get_Adc(u32 ch); //获得某个通道值
u16 Get_Adc_Average(u32 ch, u8 times); //得到某个通道给定次数采样的平均值
#endif
/*********************stm32l4xx_it.C*******************************/
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
/* USER CODE END DMA1_Channel1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc1);
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
/* USER CODE END DMA1_Channel1_IRQn 1 */
}
/*************************main函数读取部分***************************************/
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue, 1);
u2_printf(&quot;%d&quot;,uhADCxConvertedValue);
u2_printf(&quot;
&quot;); |