硬汉嵌入式论坛

 找回密码
 立即注册
查看: 272|回复: 3
收起左侧

[ADC] STM32H7开启ADC1后 ADC3可以开启外部通道但VBAT\VREF\温度三通道开启失败

[复制链接]

1

主题

1

回帖

4

积分

新手上路

积分
4
发表于 2024-1-21 21:52:22 | 显示全部楼层 |阅读模式
最近在学习STM32H7的ADC,移植了教程里面的ADC+DMA双缓冲区和ADC+DMA多通道采样,发现在开启了ADC1后,ADC3只能开启外部输入通道(INP),内部通道开启时HAL_ADC_ConfigChannel(&AdcHandle3, &sConfig3)函数返回ERROR,进入调试发现在初始化外部通道的时候stm32h7xx_hal_adc.c的第2560和第2561行处的if可以进入,但初始化内部通道时缺无法进入,想知道是哪里出现了问题。
代码如下,单独使用ADC_Init和ADC_Init_help输出均正常,同时初始化会出现如上所述情况。


/**********************************************************************************************************
*        模块名称 : ADC驱动
*        文件名称 : bsp_adc.c
*        版    本 : V1.0
*        说    明 : ADC1:        定时器触发 + DMA双缓冲的实现定频采集8路ADC数据
                                                                                使用的TIM2的OC2作为ADC的外部触发源,触发速度是100KHz,即ADC的采样率也是100KHz,足以满足AT接口传感器的采集需要。
                                                                                使用DMA的半传输完成中断和传输完成中断实现数据的双缓冲更新。
*********************************************************************************************************/       
#include "bsp.h"

/* 选择ADC的时钟源,选用四个直接通到(PC0-3),才可以选择AHB,其余需要选择PLL时钟*/
//#define ADC_CLOCK_SOURCE_AHB     /* 选择AHB时钟源 */
#define ADC_CLOCK_SOURCE_PLL     /* 选择PLL时钟源 */

#if defined ( __ICCARM__ )/* 方便Cache类的API操作,做32字节对齐,选择合适的内存地址*/
#pragma location = 0x38000000
uint16_t ADCxValues[128];
uint16_t ADCValues[4];
#elif defined ( __CC_ARM )
ALIGN_32BYTES(__attribute__((section (".RAM_D3"))) uint16_t ADCxValues[128]);
ALIGN_32BYTES(__attribute__((section (".RAM_D3"))) uint16_t ADCValues[4]);
#endif
__IO uint8_t s_DmaFlag = 0;  /* 1表示进DMA半传输完成中断,2表示进入DMA传输完成中断 */
DMA_HandleTypeDef   DmaHandle = {0};       
DMA_HandleTypeDef   DMA_Handle3 = {0};
/*********************************************************************************************************
*        函 数 名: TIM2_Config
*        功能说明: 配置TIM2_OC2,用于触发ADC,当前配置的100KHz触发频率
*        形    参: 无                                                                          
*        返 回 值: 无
*********************************************************************************************************/
static void TIM2_Config(void)
{
        TIM_HandleTypeDef  htim ={0};
        TIM_OC_InitTypeDef sConfig = {0};
       
        __HAL_RCC_TIM2_CLK_ENABLE();/* 使能时钟 详细的定时器时钟说明去bsp_tim_pwm.c看*/  
  /*-----------------------------------------------------------------------
        TIM2CLK = 200MHz/(Period + 1) / (Prescaler + 1) = 200MHz / 20000 / 1 = 10KHz
        ----------------------------------------------------------------------- */  
  HAL_TIM_Base_DeInit(&htim);
   
  htim.Instance = TIM2;
        htim.Init.Period            = 19999;
        htim.Init.Prescaler         = 0;
        htim.Init.ClockDivision     = 0;
        htim.Init.CounterMode       = TIM_COUNTERMODE_UP;
        htim.Init.RepetitionCounter = 0;
        HAL_TIM_Base_Init(&htim);
   
  sConfig.OCMode     = TIM_OCMODE_PWM1;
  sConfig.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfig.Pulse = 1000;      /* 占空比50%,这里属于配置无输出的PWM */
       
  if(HAL_TIM_OC_ConfigChannel(&htim, &sConfig, TIM_CHANNEL_2) != HAL_OK){Error_Handler(__FILE__, __LINE__);}/* 配置OC1 */
  if(HAL_TIM_OC_Start(&htim, TIM_CHANNEL_2)                                                                         != HAL_OK){Error_Handler(__FILE__, __LINE__);}/* 启动OC1 */
}

/*********************************************************************************************************
*        函 数 名: bsp_InitADC
*        功能说明: 初始化ADC
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************/
void bsp_InitADC(void)
{
  ADC_HandleTypeDef   AdcHandle = {0};
        ADC_ChannelConfTypeDef   sConfig = {0};
        GPIO_InitTypeDef         GPIO_InitStruct;
       
        ADC_HandleTypeDef   AdcHandle3 = {0};
        ADC_ChannelConfTypeDef   sConfig3 = {0};

  /*1 - 配置ADC采样的时钟 ####################################### */
#if defined (ADC_CLOCK_SOURCE_PLL)
        /* 配置PLL2时钟为的72MHz,方便分频产生ADC最高时钟36MHz */
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
        PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
        PeriphClkInitStruct.PLL2.PLL2M = 25;
        PeriphClkInitStruct.PLL2.PLL2N = 504;
        PeriphClkInitStruct.PLL2.PLL2P = 7;
        PeriphClkInitStruct.PLL2.PLL2Q = 7;
        PeriphClkInitStruct.PLL2.PLL2R = 7;
        PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
        PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
        PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
        PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);  
        }
#elif defined (ADC_CLOCK_SOURCE_AHB)  /* 使用AHB时钟的话,无需配置,默认选择*/
#endif

        /*2 - 配置ADC采样使用的引脚 ################################### */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
       
        GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
       
        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
               
        /*3 - 配置DMA,选择DMA1_STREAM1 ####################################### */
        __HAL_RCC_DMA1_CLK_ENABLE();
        DmaHandle.Instance                 = DMA1_Stream1;            /* 使用的DMA1 Stream1 */
        DmaHandle.Init.Request             = DMA_REQUEST_ADC1;                    /* 请求类型采用DMA_REQUEST_ADC1 */  
        DmaHandle.Init.Direction           = DMA_PERIPH_TO_MEMORY;    /* 传输方向是从外设到存储器 */  
        DmaHandle.Init.PeriphInc           = DMA_PINC_DISABLE;        /* 外设地址自增禁止 */
        DmaHandle.Init.MemInc              = DMA_MINC_ENABLE;         /* 存储器地址自增使能 */  
        DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* 外设数据传输位宽选择半字,即16bit */     
        DmaHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD; /* 存储器数据传输位宽选择半字,即16bit */   
        DmaHandle.Init.Mode                = DMA_CIRCULAR;            /* 循环模式 */   
        DmaHandle.Init.Priority            = DMA_PRIORITY_LOW;        /* 优先级低 */  
        DmaHandle.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
        DmaHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
        DmaHandle.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
        DmaHandle.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */

        if(HAL_DMA_Init(&DmaHandle) != HAL_OK){Error_Handler(__FILE__, __LINE__);     } /* 初始化DMA */
   
  HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 2, 0);    /* 开启DMA1 Stream1的中断 */
  HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
   
        __HAL_LINKDMA(&AdcHandle, DMA_Handle, DmaHandle);/* 关联ADC句柄和DMA句柄 */

        /*4 - 配置ADC ########################################################### */
        __HAL_RCC_ADC12_CLK_ENABLE();
        AdcHandle.Instance = ADC1;
#if defined (ADC_CLOCK_SOURCE_PLL)
        AdcHandle.Init.ClockPrescaler                        = ADC_CLOCK_ASYNC_DIV2;          /* 采用PLL异步时钟,2分频,即72MHz/2 = 36MHz */
#elif defined (ADC_CLOCK_SOURCE_AHB)
        AdcHandle.Init.ClockPrescaler                        = ADC_CLOCK_SYNC_PCLK_DIV4;      /* 采用AHB同步时钟,4分频,即200MHz/4 = 50MHz */
#endif
        AdcHandle.Init.Resolution                            = ADC_RESOLUTION_16B;                            /* 16位分辨率 */
        AdcHandle.Init.ScanConvMode                          = ADC_SCAN_ENABLE;                              /* 禁止扫描,因为仅开了一个通道 *///开俩通道,扫描
        AdcHandle.Init.EOCSelection                          = ADC_EOC_SINGLE_CONV;                           /* EOC转换结束标志 */
        AdcHandle.Init.LowPowerAutoWait                      = DISABLE;                                       /* 禁止低功耗自动延迟特性 */
        AdcHandle.Init.ContinuousConvMode                    = DISABLE;                                      /* 禁止自动转换,采用的定时器触发转换 */
        AdcHandle.Init.NbrOfConversion                       = 8;                                             /* 使用了1个转换通道 *///8个
        AdcHandle.Init.DiscontinuousConvMode                = DISABLE;                                       /* 禁止不连续模式 */
        AdcHandle.Init.NbrOfDiscConversion                   = 1;                                             /* 禁止不连续模式后,此参数忽略,此位是用来配置不连续子组中通道数 */
        AdcHandle.Init.ExternalTrigConv                      = ADC_EXTERNALTRIG_T2_CC2;          /* 定时器2的CC2触发 */
        AdcHandle.Init.ExternalTrigConvEdge                  = ADC_EXTERNALTRIGCONVEDGE_RISING;  /* 上升沿触发 */
        AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;         /* DMA循环模式接收ADC转换的数据 */
        AdcHandle.Init.BoostMode                = ENABLE;                                  /* ADC时钟超过20MHz的话,使能boost */
        AdcHandle.Init.Overrun                  = ADC_OVR_DATA_OVERWRITTEN;                /* ADC转换溢出的话,覆盖ADC的数据寄存器 */
        AdcHandle.Init.OversamplingMode         = DISABLE;                                 /* 禁止过采样 */

        if(HAL_ADC_Init(&AdcHandle) != HAL_OK){Error_Handler(__FILE__, __LINE__);} /* 初始化ADC */
        if(HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK){Error_Handler(__FILE__, __LINE__);}        /* 校准ADC,采用偏移校准 */
  
        /* 配置ADC通道 采样时间=采样周期+8.5个时钟周期,选择最大的64.5+8.5=73*/
        sConfig.Channel      = ADC_CHANNEL_10;                      /* 配置使用的ADC通道 */
        sConfig.Rank         = ADC_REGULAR_RANK_1;                  /* 采样序列里的第1个 */
        sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5;     /* 采样周期 */
        sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */
        sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */

        if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
  //
        sConfig.Channel = ADC_CHANNEL_16;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
        //
        sConfig.Channel = ADC_CHANNEL_15;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
        //
        sConfig.Channel = ADC_CHANNEL_18;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
        //
        sConfig.Channel = ADC_CHANNEL_19;
  sConfig.Rank = ADC_REGULAR_RANK_5;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
        //
        sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_6;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
        //
        sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_7;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
        //
        sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_REGULAR_RANK_8;
  if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){Error_Handler(__FILE__, __LINE__);}
       
        /* ## - 5 - 配置ADC的定时器触发 ####################################### */
        TIM2_Config();
  
        /* ## - 6 - 启动ADC的DMA方式传输 ####################################### */
        if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)ADCxValues, 128) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
}

/*
*********************************************************************************************************
*        函 数 名: bsp_InitADC
*        功能说明: 初始化ADC,采用DMA方式进行多通道采样,采集了PC0, Vbat/4, VrefInt和温度
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitADC_help(void)
{
        ADC_HandleTypeDef   AdcHandle3 = {0};
        ADC_ChannelConfTypeDef   sConfig3 = {0};
        GPIO_InitTypeDef          GPIO_InitStruct;

  /* ## - 1 - 配置ADC采样的时钟 ####################################### */
#if defined (ADC_CLOCK_SOURCE_PLL)
        /* 配置PLL2时钟为的72MHz,方便分频产生ADC最高时钟36MHz */
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
        PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
        PeriphClkInitStruct.PLL2.PLL2M = 25;
        PeriphClkInitStruct.PLL2.PLL2N = 504;
        PeriphClkInitStruct.PLL2.PLL2P = 7;
        PeriphClkInitStruct.PLL2.PLL2Q = 7;
        PeriphClkInitStruct.PLL2.PLL2R = 7;
        PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
        PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
        PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
        PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);  
        }
#elif defined (ADC_CLOCK_SOURCE_AHB)
  
  /* 使用AHB时钟的话,无需配置,默认选择*/
  
#endif

        /* ## - 2 - 配置ADC采样使用的时钟 ####################################### */
        __HAL_RCC_GPIOC_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  
        /* ## - 3 - 配置ADC采样使用的时钟 ####################################### */
        __HAL_RCC_DMA1_CLK_ENABLE();
        DMA_Handle3.Instance                 = DMA1_Stream0;            /* 使用的DMA1 Stream1 */
        DMA_Handle3.Init.Request             = DMA_REQUEST_ADC3;             /* 请求类型采用DMA_REQUEST_ADC3 */  
        DMA_Handle3.Init.Direction           = DMA_PERIPH_TO_MEMORY;    /* 传输方向是从存储器到外设 */  
        DMA_Handle3.Init.PeriphInc           = DMA_PINC_DISABLE;        /* 外设地址自增禁止 */
        DMA_Handle3.Init.MemInc              = DMA_MINC_ENABLE;         /* 存储器地址自增使能 */  
        DMA_Handle3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;   /* 外设数据传输位宽选择半字,即16bit */     
        DMA_Handle3.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;   /* 存储器数据传输位宽选择半字,即16bit */   
        DMA_Handle3.Init.Mode                = DMA_CIRCULAR;            /* 循环模式 */   
        DMA_Handle3.Init.Priority            = DMA_PRIORITY_LOW;        /* 优先级低 */  
        DMA_Handle3.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
        DMA_Handle3.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
        DMA_Handle3.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
        DMA_Handle3.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */

        /* 初始化DMA */
        if(HAL_DMA_Init(&DMA_Handle3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);     
        }
   
        /* 关联ADC句柄和DMA句柄 */
        __HAL_LINKDMA(&AdcHandle3, DMA_Handle, DMA_Handle3);
       
   
        /* ## - 4 - 配置ADC ########################################################### */
        __HAL_RCC_ADC3_CLK_ENABLE();
        AdcHandle3.Instance = ADC3;

#if defined (ADC_CLOCK_SOURCE_PLL)
        AdcHandle3.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV8;          /* 采用PLL异步时钟,8分频,即72MHz/8 = 36MHz */
#elif defined (ADC_CLOCK_SOURCE_AHB)
        AdcHandle3.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV4;      /* 采用AHB同步时钟,4分频,即200MHz/4 = 50MHz */
#endif
       
        AdcHandle3.Init.Resolution            = ADC_RESOLUTION_16B;        /* 16位分辨率 */
        AdcHandle3.Init.ScanConvMode          = ADC_SCAN_ENABLE;           /* 禁止扫描,因为仅开了一个通道 */
        AdcHandle3.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;       /* EOC转换结束标志 */
        AdcHandle3.Init.LowPowerAutoWait      = DISABLE;                   /* 禁止低功耗自动延迟特性 */
        AdcHandle3.Init.ContinuousConvMode    = ENABLE;                    /* 禁止自动转换,采用的软件触发 */
        AdcHandle3.Init.NbrOfConversion       = 4;                         /* 使用了4个转换通道 */
        AdcHandle3.Init.DiscontinuousConvMode = DISABLE;                   /* 禁止不连续模式 */
        AdcHandle3.Init.NbrOfDiscConversion   = 1;                         /* 禁止不连续模式后,此参数忽略,此位是用来配置不连续子组中通道数 */
        AdcHandle3.Init.ExternalTrigConv      = ADC_SOFTWARE_START;        /* 采用软件触发 */
        AdcHandle3.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_RISING;    /* 采用软件触发的话,此位忽略 */
        AdcHandle3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; /* DMA循环模式接收ADC转换的数据 */
        AdcHandle3.Init.BoostMode             = DISABLE;                            /* ADC时钟低于20MHz的话,可以禁止boost */
        AdcHandle3.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;                /* ADC转换溢出的话,覆盖ADC的数据寄存器 */
        AdcHandle3.Init.OversamplingMode      = DISABLE;                            /* 禁止过采样 */

    /* 初始化ADC */
        if (HAL_ADC_Init(&AdcHandle3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
  
  
        /* 校准ADC,采用偏移校准 */
        if (HAL_ADCEx_Calibration_Start(&AdcHandle3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
  
        /* 配置ADC通道,序列1,采样PC0引脚 */
        /*
                采用PLL2时钟的话,ADCCLK = 72MHz / 8 = 9MHz
            ADC采样速度,即转换时间 = 采样时间 + 逐次逼近时间
                                    = 810.5 + 8.5(16bit)
                                    = 820个ADC时钟周期
            那么转换速度就是9MHz / 820 = 10975Hz
        */
        sConfig3.Channel      = ADC_CHANNEL_0;              /* 配置使用的ADC通道 */
        sConfig3.Rank         = ADC_REGULAR_RANK_1;          /* 采样序列里的第1个 */
        sConfig3.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
        sConfig3.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig3.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */
        sConfig3.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig3.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig3.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
       
        if (HAL_ADC_ConfigChannel(&AdcHandle3, &sConfig3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
       
        /* 配置ADC通道,序列2,采样Vbat/4 */
        sConfig3.Channel      = ADC_CHANNEL_17;       /* 配置使用的ADC通道 */
        sConfig3.Rank         = ADC_REGULAR_RANK_2;          /* 采样序列里的第1个 */
        sConfig3.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
        sConfig3.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig3.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */
        sConfig3.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig3.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig3.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
       
        if (HAL_ADC_ConfigChannel(&AdcHandle3, &sConfig3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
  
        /* 配置ADC通道,序列3,采样VrefInt */
        sConfig3.Channel      = ADC_CHANNEL_VREFINT;         /* 配置使用的ADC通道 */
        sConfig3.Rank         = ADC_REGULAR_RANK_3;          /* 采样序列里的第1个 */
        sConfig3.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
        sConfig3.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig3.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */
        sConfig3.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig3.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig3.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
       
        if (HAL_ADC_ConfigChannel(&AdcHandle3, &sConfig3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
       
        /* 配置ADC通道,序列4,采样温度 */
        sConfig3.Channel      = ADC_CHANNEL_TEMPSENSOR;      /* 配置使用的ADC通道 */
        sConfig3.Rank         = ADC_REGULAR_RANK_4;          /* 采样序列里的第1个 */
        sConfig3.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
        sConfig3.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig3.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */
        sConfig3.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig3.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig3.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
                                 
        if (HAL_ADC_ConfigChannel(&AdcHandle3, &sConfig3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }       

        /* ## - 6 - 启动ADC的DMA方式传输 ####################################### */
        if (HAL_ADC_Start_DMA(&AdcHandle3, (uint32_t *)ADCValues, 4) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
}
/*
*********************************************************************************************************
*        函 数 名: DMA1_Stream1_IRQHandler
*        功能说明: DMA1 Stream1中断服务程序
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void DMA1_Stream1_IRQHandler(void)
{
        if((DMA1->LISR & DMA_FLAG_TCIF1_5) != RESET)        /* 传输完成中断 */
        {
        HC574_TogglePin(GPIO_PIN_23);
                /*
                   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
                   2、进入传输完成中断,当前DMA正在使用缓冲区的前半部分,用户可以操作后半部分。
                */
                SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADCxValues[64]), 128);
                s_DmaFlag = 2;
                DMA1->LIFCR = DMA_FLAG_TCIF1_5;                /* 清除标志 */
        }
        if((DMA1->LISR & DMA_FLAG_HTIF1_5) != RESET)        /* 半传输完成中断 */
        {
                /*
                   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
                   2、进入半传输完成中断,当前DMA正在使用缓冲区的后半部分,用户可以操作前半部分。
                */
                SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADCxValues[0]), 128);
                s_DmaFlag = 1;
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_HTIF1_5;
        }

        /* 传输错误中断 */
        if((DMA1->LISR & DMA_FLAG_TEIF1_5) != RESET)
        {
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_TEIF1_5;
        }

        /* 直接模式错误中断 */
        if((DMA1->LISR & DMA_FLAG_DMEIF1_5) != RESET)
        {
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_DMEIF1_5;
        }
}

/*
*********************************************************************************************************
*        函 数 名: bsp_GetAdcValues
*        功能说明: 获取ADC的数据并打印
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_GetAdcValues(void)
{
        uint32_t values1,values2,values3,values4,values5,values6,values7,values8;
        float  temp1,temp2,temp3,temp4,temp5,temp6,temp7,temp8;
       
        /* 当前DMA操作是后半个缓冲,读取前半个缓冲的前4个数值求平均 */
        if(s_DmaFlag == 1)
        {
                DISABLE_INT();
                s_DmaFlag = 0;
                //values1 = (ADCxValues[0] + ADCxValues[3] + ADCxValues[7] + ADCxValues[11])/4;
                //values2 = (ADCxValues[1] + ADCxValues[4] + ADCxValues[8] + ADCxValues[12])/4;
                //values3 = (ADCxValues[2] + ADCxValues[5] + ADCxValues[9] + ADCxValues[13])/4;
                //values4 = (ADCxValues[3] + ADCxValues[6] + ADCxValues[10] + ADCxValues[14])/4;
                values1 = ADCxValues[0];
                values2 = ADCxValues[1];
                values3 = ADCxValues[2];
                values4 = ADCxValues[3];
                values5 = ADCxValues[4];
                values6 = ADCxValues[5];
                values7 = ADCxValues[6];
                values8 = ADCxValues[7];
        /* 当前DMA操作是后前个缓冲,读取后半个缓冲的前4个数值求平均 */
        ENABLE_INT();
        }
        else if(s_DmaFlag == 2)
        {
                DISABLE_INT();
                s_DmaFlag = 0;
                values1 = ADCxValues[64];
                values2 = ADCxValues[65];
                values3 = ADCxValues[66];
                values4 = ADCxValues[67];
                values5 = ADCxValues[68];
                values6 = ADCxValues[69];
                values7 = ADCxValues[70];
                values8 = ADCxValues[71];
                //values1 = (ADCxValues[64] + ADCxValues[68] + ADCxValues[72] + ADCxValues[76])/4;
                //values2 = (ADCxValues[65] + ADCxValues[69] + ADCxValues[73] + ADCxValues[77])/4;
                //values3 = (ADCxValues[66] + ADCxValues[70] + ADCxValues[74] + ADCxValues[78])/4;
                //values4 = (ADCxValues[67] + ADCxValues[71] + ADCxValues[75] + ADCxValues[79])/4;
                ENABLE_INT();
        }
       
        /* 打印读出的串口值 */
        temp1 = values1 *3.3 / 65536;
        temp2 = values2 *3.3 / 65536;
        temp3 = values3 *3.3 / 65536;
        temp4 = values4 *3.3 / 65536;
        temp5 = values5 *3.3 / 65536;
        temp6 = values6 *3.3 / 65536;
        temp7 = values7 *3.3 / 65536;
        temp8 = values8 *3.3 / 65536;
        printf("ADCxValues1 = %d, %5.3f\r\n", values1, temp1);
        printf("ADCxValues2 = %d, %5.3f\r\n", values2, temp2);
        printf("ADCxValues3 = %d, %5.3f\r\n", values3, temp3);
        printf("ADCxValues4 = %d, %5.3f\r\n", values4, temp4);
        printf("ADCxValues5 = %d, %5.3f\r\n", values5, temp5);
        printf("ADCxValues6 = %d, %5.3f\r\n", values6, temp6);
        printf("ADCxValues7 = %d, %5.3f\r\n", values7, temp7);
        printf("ADCxValues8 = %d, %5.3f\r\n", values8, temp8);
        printf("\n\n");
}

void bsp_GetAdcValues_help(void)
{
    float AdcValues[5];
    uint16_t TS_CAL1;
    uint16_t TS_CAL2;
   
    /*
       使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍
    */
    SCB_InvalidateDCache_by_Addr((uint32_t *)ADCValues,  sizeof(ADCValues));
    AdcValues[0] = ADCValues[0] * 3.3 / 65536;
    AdcValues[1] = ADCValues[1] * 3.3 / 65536;
    AdcValues[2] = ADCValues[2] * 3.3 / 65536;     

    /* 根据参考手册给的公式计算温度值 */
    TS_CAL1 = *(__IO uint16_t *)(0x1FF1E820);
    TS_CAL2 = *(__IO uint16_t *)(0x1FF1E840);
   
    AdcValues[3] = (110.0 - 30.0) * (ADCValues[3] - TS_CAL1)/ (TS_CAL2 - TS_CAL1) + 30;  
   
    printf("PC0 = %5.3fV, Vbat/4 = %5.3fV, VrefInt = %5.3fV, TempSensor = %5.3f℃\r\n",
            AdcValues[0],  AdcValues[1], AdcValues[2], AdcValues[3]);

}



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2024-1-22 00:29:34 | 显示全部楼层
单步调试进入函数HAL_ADC_ConfigChanne里面看下那步出错了。+
回复

使用道具 举报

1

主题

1

回帖

4

积分

新手上路

积分
4
 楼主| 发表于 2024-1-22 15:50:14 | 显示全部楼层
2561行的(ADC_ANY_OTHER_ENABLED(hadc) == RESET)错误,导致那个if直接跳到了2594行的else里面去,在初始化其他通道的时候没有出现这样的问题
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2024-1-23 08:01:01 | 显示全部楼层
zyffff 发表于 2024-1-22 15:50
2561行的(ADC_ANY_OTHER_ENABLED(hadc) == RESET)错误,导致那个if直接跳到了2594行的else里面去,在初始化 ...

不行的话,升级到最新的HAL库试试。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 14:41 , Processed in 0.162586 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表