硬汉嵌入式论坛

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

[STM32H7] H723的ADC3 采样周期

[复制链接]

2

主题

2

回帖

8

积分

新手上路

积分
8
发表于 2024-5-23 17:16:59 | 显示全部楼层 |阅读模式
          请教一下坛主:用了723片子上的ADC3采样,ADC时钟36M, 采样SamplingTime = ADC_SAMPLETIME_2CYCLES_5,周期性采样1600个数据,那不是应该36M/(6.5+2.5)=4M,    4M/1600=2500HZ,也就是400us才对吗?可实际结果是420us。请大佬解惑。


void ADC3_Init(void)
{
        //DMA_HandleTypeDef   DMA_Handle= {0};
  ADC_ChannelConfTypeDef sConfig = {0};

        // ## - 1 - 配置ADC采样的时钟 #######################################
#if defined (ADC_CLOCK_SOURCE_PLL)
        // 配置PLL2时钟为的72MHz ,36M时12位ADC可以到4MHZ
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
        PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
        PeriphClkInitStruct.PLL2.PLL2M = 4;//16;
        PeriphClkInitStruct.PLL2.PLL2N = 18;//72;
        PeriphClkInitStruct.PLL2.PLL2P = 4;//72MHz
        PeriphClkInitStruct.PLL2.PLL2Q = 4;//2;//72MHz
        PeriphClkInitStruct.PLL2.PLL2R = 2;//72MHz
        PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
        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

  hadc3.Instance = ADC3;//指向ADC1
       
  ADCGIO_Init( &hadc3);//ADCx  GPIO配置和初始化
       
   __HAL_RCC_DMA2_CLK_ENABLE();
        DMA_Handle3.Instance                 = DMA2_Stream1;//DMA1_Stream2;            /* 使用的DMA1 Stream1 */
        DMA_Handle3.Init.Request             = DMA_REQUEST_ADC3;//DMA_REQUEST_ADC3;             /* 请求类型采用DMA_REQUEST_ADC1 */  
        DMA_Handle3.Init.Direction           = DMA_PERIPH_TO_MEMORY;    /* 传输方向是从外设到存储器 */  
        DMA_Handle3.Init.PeriphInc           = DMA_PINC_DISABLE;       //DMA_PINC_ENABLE ;// /* 外设地址自增禁止 */
        DMA_Handle3.Init.MemInc              = DMA_MINC_ENABLE;         /* 存储器地址自增使能 */  
        DMA_Handle3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;//DMA_PDATAALIGN_WORD;   /* 外设数据传输位宽选择半字,即16bit */     
        DMA_Handle3.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;//DMA_MDATAALIGN_HALFWORD;//DMA_MDATAALIGN_WORD;   /* 存储器数据传输位宽选择半字,即16bit */   
        DMA_Handle3.Init.Mode                = DMA_CIRCULAR; //DMA_NORMAL ;/* 循环模式 */   
        DMA_Handle3.Init.Priority            = DMA_PRIORITY_MEDIUM ;//DMA_PRIORITY_LOW;        /* 优先级中 */  
        DMA_Handle3.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
        //DMA_Handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
  //DMA_Handle.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
        //DMA_Handle.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */       
        /* 初始化DMA */
        if(HAL_DMA_Init(&DMA_Handle3) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);   
        }       
        //__HAL_DMA_ENABLE_IT(&DMA_Handle,DMA_IT_TC);
        /* 关联ADC句柄和DMA句柄 */
        __HAL_LINKDMA(&hadc3, DMA_Handle, DMA_Handle3);//第一个参数是外设句柄,第二个参数是外设句柄内的一个DMA句柄指针,最后一个参数是DMA句柄
        DMA_NVIC_Config(&hadc3);//DMA中断优先级配置函数
       
//ADC3配置A****************************************************************       
        HAL_ADC_DeInit(&hadc3);       
        __HAL_RCC_ADC3_CLK_ENABLE();//开启adc时钟

#if defined (ADC_CLOCK_SOURCE_PLL)//如果选择PLL时钟

hadc3.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV1;   //采用PLL异步时钟,2分频,即72MHz/2 = 36MHz
#elif defined (ADC_CLOCK_SOURCE_AHB)//如果选择AHB时钟
        hadc3.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV4; // 采用AHB同步时钟,4分频,即200MHz/4 = 50MHz
#endif         
  hadc3.Init.Resolution = ADC_RESOLUTION_12B;//ADC3最高分辨率是12位
  hadc3.Init.DataAlign = ADC3_DATAALIGN_RIGHT;//
        hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;//扫描模式;ADC_SCAN_DISABLE;//非扫描模式
  hadc3.Init.EOCSelection =ADC_EOC_SINGLE_CONV;//ADC_EOC_SEQ_CONV;//关闭EOC中断 //单通道转换结束或者序列转换结束
  hadc3.Init.LowPowerAutoWait = DISABLE;//自动低功耗关闭
  hadc3.Init.ContinuousConvMode = ENABLE; //打开连续转换;DISABLE;//不打开连续转换//
  hadc3.Init.NbrOfConversion = 5;//5个转换在规则序列中
  hadc3.Init.DiscontinuousConvMode = DISABLE;//禁止不连续采样模式这个参数;
        hadc3.Init.NbrOfDiscConversion=0;     //不连续采样通道数为0/用于设置子组的大小。
  
        hadc3.Init.ExternalTrigConv=ADC_EXTERNALTRIG_T6_TRGO;//选择T6用于触发
       
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING ;//上升沿触发FALLING//
        hadc3.Init.DMAContinuousRequests = ENABLE;//指定DMA请求是否以单次模式执行(当达到转换数量时,DMA传输停止)

        hadc3.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;//
        hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; /* DMA循环模式接收ADC转换的数据 */
        hadc3.Init.Overrun=ADC_OVR_DATA_OVERWRITTEN;//有新的数据直接覆盖掉旧数据;//ADC_OVR_DATA_PRESERVED;超时保存数据//
        hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;//配置应用于有无过度采样的最终结果的左移位。此参数的值可以为@refadcex_left_bit_shift*
        //hadc1.Init.BoostMode=ENABLE;        //BOOsT模式开,ADC时钟超过20MHz的话,使能boost
        hadc3.Init.OversamplingMode=DISABLE;//ENABLE;////过采样打开//
       
  //hadc1.Init.Oversampling.Ratio = 15;                            // 15+1倍过采样
        //hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;           // 数据右移4bit,即除以16
        //hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;   // 触发后连续完成每个通道的所有过采样转换

        //初始化ADC3
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler(__FILE__, __LINE__);
  }

       
// 校准ADC1,采用线性校准  ADC_CALIB_OFFSET_LINEARITY//ADC_CALIB_OFFSET
        if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
       
        //配置ADC通道,序列1
  sConfig.Channel = ADC_CHANNEL_0;//
  sConfig.Rank = ADC_REGULAR_RANK_1;//常规转换的排序
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;  //C_SAMPLETIME_8CYCLES_5;////要为选定通道设置的采样时间值
  sConfig.SingleDiff = ADC_SINGLE_ENDED;//选择单端输入或差分输入
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//选择偏移量数,
  sConfig.Offset = 0;///* 无偏移的情况下,此参数忽略 */
        sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig.OffsetSignedSaturation = DISABLE;// 禁止有符号饱和
  //sConfig.OffsetSign = ADC3_OFFSET_SIGN_NEGATIVE;
       
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler(__FILE__, __LINE__);
  }       
                        //配置ADC3  序列2  
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_2;
        sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;  //C_SAMPLETIME_8CYCLES_5;////要为选定通道设置的采样时间值
        sConfig.SingleDiff = ADC_SINGLE_ENDED;//选择单端输入或差分输入
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//选择偏移量数,
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler(__FILE__, __LINE__);
  }       
        //配置ADC3  序列3  
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_3;  
        sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;  //C_SAMPLETIME_8CYCLES_5;////要为选定通道设置的采样时间值
  sConfig.SingleDiff = ADC_SINGLE_ENDED;//选择单端输入或差分输入
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//选择偏移量数,  
        if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler(__FILE__, __LINE__);
  }       
                        //配置ADC3  序列4   
  sConfig.Channel = ADC_CHANNEL_3;//                        
  sConfig.Rank = ADC_REGULAR_RANK_4;
        sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;  //C_SAMPLETIME_8CYCLES_5;////要为选定通道设置的采样时间值
  sConfig.SingleDiff = ADC_SINGLE_ENDED;//选择单端输入或差分输入
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//选择偏移量数,
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler(__FILE__, __LINE__);
  }       
                        //配置ADC3  序列5  
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_5;  
        sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;  //C_SAMPLETIME_8CYCLES_5;////要为选定通道设置的采样时间值
  sConfig.SingleDiff = ADC_SINGLE_ENDED;//选择单端输入或差分输入
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//选择偏移量数,
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler(__FILE__, __LINE__);
  }       

        // ## - 6 - 启动ADC的DMA方式传输 #######################################
       
        if(HAL_ADC_Start_DMA(&hadc3, (uint32_t *)ADC3Values, (sizeof(ADC3Values)/sizeof(ADC3Values[0]))) != HAL_OK)//单个模式
        {
                Error_Handler(__FILE__, __LINE__);
        }       
}


回复

使用道具 举报

2

主题

2

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2024-5-23 18:03:12 | 显示全部楼层
SMP = 000: 2.5 ADC clock cycles
• SMP = 001: 6.5 ADC clock cycles
• SMP = 010: 12.5 ADC clock cycles
• SMP = 011: 24.5 ADC clock cycles
• SMP = 100: 47.5 ADC clock cycles
• SMP = 101: 92.5 ADC clock cycles
• SMP = 110: 247.5 ADC clock cycles
• SMP = 111: 640.5 ADC clock cycles
The total conversion time is calculated as follows:
TCONV = Sampling time + 12.5 ADC clock cycles
Example:
With Fadc_ker_ck = 30 MHz and a sampling time of 2.5 ADC clock cycles:
TCONV = (2.5 + 12.5) ADC clock cycles = 15 ADC clock cycles = 500 ns                           
已知道答案了
回复

使用道具 举报

2

主题

2

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2024-5-23 18:04:12 | 显示全部楼层
SMP = 000: 2.5 ADC clock cycles
• SMP = 001: 6.5 ADC clock cycles
• SMP = 010: 12.5 ADC clock cycles
• SMP = 011: 24.5 ADC clock cycles
• SMP = 100: 47.5 ADC clock cycles
• SMP = 101: 92.5 ADC clock cycles
• SMP = 110: 247.5 ADC clock cycles
• SMP = 111: 640.5 ADC clock cycles
The total conversion time is calculated as follows:
TCONV = Sampling time + 12.5 ADC clock cycles
Example:
With Fadc_ker_ck = 30 MHz and a sampling time of 2.5 ADC clock cycles:
TCONV = (2.5 + 12.5) ADC clock cycles = 15 ADC clock cycles = 500 ns
已找到问题
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-15 00:10 , Processed in 0.037358 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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