硬汉嵌入式论坛

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

[HAL学习笔记] HAL库ADC源文件stm32h7xx_hal_adc.c学习笔记(2018-09-03 V1.0)

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106826
QQ
发表于 2018-9-3 12:47:11 | 显示全部楼层 |阅读模式
说明:
ADC的API注意事项比较多,几乎每个函数都有个注意事项,使用时要特别注意。


==============================================================================
                                                                  ##### ADC规格特性  #####
==============================================================================  

1、16位,14位,12位,10位,8位分辨率配置。
2、规则通道转换完毕可以产生中断。3、单次和连续转换模式。
4、多通道扫描
5、数据对齐格式
6、编程采样时间
7、外部触发(定时器或EXTI)
8、支持DMA
9、双通道快速交替采样之间的延迟时间配置
10、ADC偏移值配置
11、ADC支持校准。
12、ADC支持规则通道转换额注入通道转换
13、ADC供电范围:1.62 V to 3.6 V
14、ADC输入电压范围:Vref- (连接到 Vssa) to Vref+ (连接到外部参考电压)。


==============================================================================
                                                                  ##### ADC驱动如何使用  #####
==============================================================================  
1、有两个需要设置(这个问题待看手册了确认)
(1)ADC核心时钟
(2)ADC转换时钟
两种时钟源可供选择,可以选择AHB时钟,也可以选择来自系统时钟,PLL2或者PLL3的时钟。
比如使用PLL2:
RCC_PeriphClkInitTypeDef   RCC_PeriphClkInit;
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection    = RCC_ADCCLKSOURCE_PLL2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);


2、ADC的时钟源和时钟分频通过函数HAL_ADC_Init()的参数ClockPrescaler可配置。

3、ADC引脚配置:
__HAL_RCC_GPIOx_CLK_ENABLE()
HAL_GPIO_Init()

4、配置ADC中断
(1)函数HAL_NVIC_EnableIRQ(ADCx_IRQn)
(2)函数ADCx_IRQHandler()调用HAL_ADC_IRQHandler()

5、配置ADC的DMA
(1)使用函数配置DMA的相关参数HAL_DMA_Init()
(2)使能DMA中断 HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
(3)中断函数里面调用DMAx_Channelx_IRQHandler()

6、规则通道相关的三个配置函数
HAL_ADC_Init()
HAL_ADC_ConfigChannel()
HAL_ADC_AnalogWDGConfig()

7、ADC的自动校准配置函数
HAL_ADCEx_Calibration_Start()

8、ADC数值获取
(1)查询方式
HAL_ADC_Start()
HAL_ADC_PollForConversion()
HAL_ADC_GetValue()
HAL_ADC_Stop()

(2)中断方式
HAL_ADC_Start_IT()
HAL_ADC_ConvCpltCallback()
HAL_ADC_GetValue()
HAL_ADC_Stop_IT()

(3)DMA方式
HAL_ADC_Start_DMA()
HAL_ADC_ConvCpltCallback() 和 HAL_ADC_ConvHalfCpltCallback()
HAL_ADC_Stop_DMA()

9、回调函数
HAL_ADC_ErrorCallback()
HAL_ADC_LevelOutOfWindowCallback() (callback of analog watchdog)
HAL_ADC_ConvCpltCallback()
HAL_ADC_ConvHalfCpltCallback

10、复位ADC
(1)复位ADC外设
__HAL_RCC_ADCx_FORCE_RESET(), __HAL_RCC_ADCx_RELEASE_RESET()

(2)函数可以复位相关引脚设计HAL_ADC_MspDeInit()。函数 __HAL_RCC_ADC_CLK_DISABLE();  用于关闭ADC

(3)函数 __HAL_RCC_GPIOx_CLK_DISABLE()用于禁止ADC的IO

(4)函数HAL_NVIC_DisableIRQ(ADCx_IRQn)用于禁止ADC中断

(5)函数HAL_NVIC_DisableIRQ(DMAx_Channelx_IRQn)用于禁止ADC的DMA中断


源文件开头的等待时间配置:

  1. /* Delay to wait before setting ADEN once ADCAL has been reset
  2.    must be at least 4 ADC clock cycles.
  3.    Assuming lowest ADC clock (350 KHz according to DS), this
  4.    4 ADC clock cycles duration is equal to
  5.    4 / 350,000 = 0.011 ms.
  6.    ADC_ENABLE_TIMEOUT set to 2 is a margin large enough to ensure
  7.    the 4 ADC clock cycles have elapsed while waiting for ADRDY
  8.    to become 1 */
  9.   #define ADC_ENABLE_TIMEOUT              ((uint32_t)  2)    /*!< ADC enable time-out value  */
  10.   #define ADC_DISABLE_TIMEOUT             ((uint32_t)  2)    /*!< ADC disable time-out value */

  11. /* Timeout to wait for current conversion on going to be completed.           */
  12. /* Timeout fixed to worst case, for 1 channel.                                */
  13. /*   - maximum sampling time (830.5 adc_clk)                                  */
  14. /*   - ADC resolution (Tsar 16 bits= 16.5 adc_clk)                            */
  15. /*   - ADC clock with prescaler 256                                           */
  16. /*     823 * 256 = 210688 clock cycles max                                    */
  17. /* Unit: cycles of CPU clock.                                                 */
  18. #define ADC_CONVERSION_TIME_MAX_CPU_CYCLES ((uint32_t) 210688)  /*!< ADC conversion completion time-out value */
复制代码


1、函数HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc)
(1)调用此函数前优先把采用的使用AHB或者PLL2/PLL3配置好
(2)为了可以运行状态时随时配置,函数形参中状态的配置不要再使用HAL_ADC_STATE_RESET,这个复位状态仅需要在上电后调用一次HAL_ADC_MspInit就可以了,后续更新不需要再调用这个。
而用户要修改MSP配置,就必须在调用HAL_ADC_Init前调用 HAL_ADC_DeInit()。
(3)ADC1,ADC2和ADC3都是用此函数配置。
(4)如果更新ADC1,ADC2和ADC3的公共寄存器,需要关闭了所有ADC时才能更新。如果没有的话,函数并不会报告错误。在大家动态更新ADC配置时,容易出现这种情况。

2、函数HAL_ADC_DeInit
(1)切记,所有ADC都是用的同1个时钟,禁止时钟将复位所有ADC
(2)函数默认会设置DEEPPWD模式,降低功耗,函数是否设置此功能待考证。

3、函数
__weak void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)和__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)

4、函数HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
(1)启动ADC,查询方式。(2)使能了multimode
        a、如果ADC在从机模式,那么ADC将被使能,但是转换还没有开启
        b、如果ADC在主机模式,那么ADC将被使能,且转换也已经开启。

5、函数HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc)
(1)禁能ADC外设,停止ADC转换
(2)如果注入通道也在使用中,要优先调用函数HAL_ADCEx_InjectedStop

6、函数HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
(1)根据AUTDLY位的状态来检测和清除EOC或者EOS,而使用EOC还是EOS是由参数hadc->Init.EOCSelection决定的
(2)如果选择的EOC,不可以在DMA配置方式下调用此函数,因为DMA读取ADC的DR寄存器会立即复位EOC,判断时间太短,不靠谱。

7、函数HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout)
(1)如果检测的某个标志位被设置,将被清除,除了ADC_FLAG_OVR。实际上,只有hadc->Init.Overrun设置为ADC_OVR_DATA_OVERWRITTEN,标志ADC_FLAG_OVR才会被清除
        否则,只要OVR被清除,ADC的DR数据寄存器就会被新的转换数据覆盖。
(2)接收到数据后,用户可以调用函数__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR)清除OVR标志。

8、函数HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)
(1)启动ADC转换,中断方式
(2)使能的三个中断:EOC (end of conversion), EOS (end of sequence),  OVR overrun,这三个中断都有对应的回调函数。
(3)是个使能了multimode,函数必须先以从机模式调用,然后以主控模式调用
        a、如果ADC在从机模式,那么ADC将被使能,但是转换还没有开启
        b、如果ADC在主机模式,那么ADC将被使能,且转换也已经开启。
(4)为了保证获取所有转换后,合理的复用所有中断,需要调用函数AL_ADC_Stop_IT()来确保已经停止ADC中断方式。
(5)默认情况下函数HAL_ADC_Start_IT不会使能EOS中断,如果用户要使用,需要依次调用函数__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP)和__HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOSMP)。

9、函数HAL_ADC_Stop_IT
停止ADC转换,关闭中断,关闭ADC外设。

10、函数HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
(1)启动ADC转换,DMA方式
(2)使能的DMA中断,overrun (if applicable), DMA half transfer, DMA transfer complete,每个中断都有回调函数。
(3)此函数是用于单ADC,而多ADC是调用函数HAL_ADCEx_MultiModeStart_DMA

11、函数HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc)
(1)停止ADC转换,关闭DMA传输,关闭ADC外设。
(2)禁止ADC外设会停止潜在的注入通道转换,因此,如果注入通道在使用中,需要调用函数HAL_ADCEx_InjectedStop
(3)单ADC的停止函数是HAL_ADC_Stop_DMA,多ADC的是HAL_ADCEx_MultiModeStop_DMA

12、函数uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)
(1)读取ADC的DR寄存器,自动清除EOC
(2)此函数不会清除EOS,需要清除EOS,在函数HAL_ADC_IRQHandler()和HAL_ADC_PollForConversion()里面已经实现,或者调用函数_HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_EOS)

13、函数void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
中断服务程序所调用

14、回调函数
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)

函数HAL_ADC_ErrorCallback使用要注意:为防止ADC DMA中的overrun错误,需要调用函数HAL_ADC_Stop_DMA复位配置,然后根据需要调用函数HAL_ADC_Start_DMA,此函数也会清除overrun标志

15、函数HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
(1)使用ADC的内部测量通道 Vbat/VrefInt/TempSensor,可以通过函数HAL_ADC_DeInit设置
(2)支持运行时更新ADC的参数

16、函数HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef* hadc, ADC_AnalogWDGConfTypeDef* AnalogWDGConfig)
(1)支持运行时更新ADC参数
(2)支持运行时修改ADC的阀值,修改后的值在下一次ADC EOC时才起作用。
(3)考虑到由于总线获得而造成的寄存器写入延迟,这可能会导致新设置阈值的有效时间不确定。

17、获取ADC状态和ADC错误信息
uint32_t HAL_ADC_GetState(ADC_HandleTypeDef* hadc)
uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc)

18、函数HAL_StatusTypeDef ADC_ConversionStop(ADC_HandleTypeDef* hadc, uint32_t ConversionGroup)
停止ADC转换

19、函数HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef* hadc)
使用此函数的条件是ADC处于禁止状态,稳压器已经启动(在函数HAL_ADC_Init里面已经设置完毕)

20、函数HAL_StatusTypeDef ADC_Disable(ADC_HandleTypeDef* hadc)
使用此函数的条件是ADC转换已经停止

21、函数void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
DMA传输完成回调函数

22、函数void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
DMA的半传输中断

23、函数void ADC_DMAError(DMA_HandleTypeDef *hdma)
DMA错误回调函数



结构体参数中断说明:

  1. /* Includes ------------------------------------------------------------------*/
  2. #include "stm32h7xx_hal_def.h"

  3. /** @addtogroup STM32H7xx_HAL_Driver
  4.   * @{
  5.   */

  6. /** @addtogroup ADC
  7.   * @{
  8.   */

  9. /* Exported types ------------------------------------------------------------*/
  10. /** @defgroup ADC_Exported_Types ADC Exported Types
  11.   * @{
  12.   */

  13. /**
  14.   * @brief  ADC Regular Conversion Oversampling structure definition
  15.   */
  16. typedef struct
  17. {
  18.   uint32_t Ratio;                         /*!< Configures the oversampling ratio. */


  19.   uint32_t RightBitShift;                 /*!< Configures the division coefficient for the Oversampler.
  20.                                                This parameter can be a value of @ref ADCEx_Right_Bit_Shift */

  21.   uint32_t TriggeredMode;                 /*!< Selects the regular triggered oversampling mode.
  22.                                                This parameter can be a value of @ref ADCEx_Triggered_Oversampling_Mode */

  23.   uint32_t OversamplingStopReset;         /*!< Selects the regular oversampling mode.
  24.                                                The oversampling is either temporary stopped or reset upon an injected
  25.                                                sequence interruption.
  26.                                                If oversampling is enabled on both regular and injected groups, this parameter
  27.                                                is discarded and forced to setting "ADC_REGOVERSAMPLING_RESUMED_MODE"
  28.                                                (the oversampling buffer is zeroed during injection sequence).
  29.                                                This parameter can be a value of @ref ADCEx_Regular_Oversampling_Mode */
  30. }ADC_OversamplingTypeDef;

  31. /**
  32.   * @brief  Structure definition of ADC instance and ADC group regular.
  33.   * @note   Parameters of this structure are shared within 2 scopes:
  34.   *          - Scope entire ADC (affects ADC groups regular and injected): ClockPrescaler, Resolution, DataAlign,
  35.   *            ScanConvMode, EOCSelection, LowPowerAutoWait.
  36.   *          - Scope ADC group regular: ContinuousConvMode, NbrOfConversion, DiscontinuousConvMode, NbrOfDiscConversion,
  37.   *            ExternalTrigConv, ExternalTrigConvEdge, DMAContinuousRequests, Overrun, OversamplingMode, Oversampling.
  38.   * @note   The setting of these parameters by function HAL_ADC_Init() is conditioned to ADC state.
  39.   *         ADC state can be either:
  40.   *          - For all parameters: ADC disabled
  41.   *          - For all parameters except 'LowPowerAutoWait', 'DMAContinuousRequests' and 'Oversampling': ADC enabled without conversion on going on group regular.
  42.   *          - For parameters 'LowPowerAutoWait' and 'DMAContinuousRequests': ADC enabled without conversion on going on groups regular and injected.
  43.   *         If ADC is not in the appropriate state to modify some parameters, these parameters setting is bypassed
  44.   *         without error reporting (as it can be the expected behavior in case of intended action to update another parameter
  45.   *         (which fulfills the ADC state condition) on the fly).
  46.   */
  47. typedef struct
  48. {
  49.   uint32_t ClockPrescaler;        /*!< Select ADC clock source (synchronous clock derived from APB clock or asynchronous clock derived from System/PLL2/PLL3 clocks) and clock prescaler.

  50.                                        This parameter can be a value of @ref ADC_ClockPrescaler.
  51.                                        Note: The clock is common for all the ADCs.
  52.                                        Note: In case of usage of channels on injected group, ADC frequency should be lower than AHB clock frequency /4 for resolution 16, 14, 12 or 10 bits,
  53.                                              AHB clock frequency /3 for resolution 8 bits.
  54.                                        Note: In case of synchronous clock mode based on HCLK/1, the configuration must be enabled only
  55.                                              if the system clock has a 50% duty clock cycle (APB prescaler configured inside RCC
  56.                                              must be bypassed and PCLK clock must have 50% duty cycle). Refer to reference manual for details.
  57.                                        Note: In case of usage of the ADC dedicated PLL clock, it must be preliminarily enabled at RCC top level.
  58.                                        Note: This parameter can be modified only if all ADCs are disabled. */

  59.   uint32_t Resolution;            /*!< Configure the ADC resolution.
  60.                                        This parameter can be a value of @ref ADC_Resolution */

  61.   uint32_t ScanConvMode;          /*!< Configure the sequencer of ADC groups regular and injected.
  62.                                        This parameter can be associated to parameter 'DiscontinuousConvMode' to have main sequence subdivided in successive parts.
  63.                                        If disabled: Conversion is performed in single mode (one channel converted, the one defined in rank 1).
  64.                                                     Parameters 'NbrOfConversion' and 'InjectedNbrOfConversion' are discarded (equivalent to set to 1).
  65.                                        If enabled:  Conversions are performed in sequence mode (multiple ranks defined by 'NbrOfConversion' or 'InjectedNbrOfConversion' and rank of each channel in sequencer).
  66.                                                     Scan direction is upward: from rank 1 to rank 'n'.
  67.                                        This parameter can be a value of @ref ADC_Scan_mode */

  68.   uint32_t EOCSelection;          /*!< Specify which EOC (End Of Conversion) flag is used for conversion by polling and interruption: end of unitary conversion or end of sequence conversions.
  69.                                        This parameter can be a value of @ref ADC_EOCSelection. */

  70.   FunctionalState LowPowerAutoWait;      /*!< Select the dynamic low power Auto Delay: new conversion start only when the previous
  71.                                        conversion (for ADC group regular) or previous sequence (for ADC group injected) has been retrieved by user software,
  72.                                        using function HAL_ADC_GetValue() or HAL_ADCEx_InjectedGetValue().
  73.                                        This feature automatically adapts the frequency of ADC conversions triggers to the speed of the system that reads the data. Moreover, this avoids risk of overrun
  74.                                        for low frequency applications.
  75.                                        This parameter can be set to ENABLE or DISABLE.
  76.                                        Note: Do not use with interruption or DMA (HAL_ADC_Start_IT(), HAL_ADC_Start_DMA()) since they clear immediately the EOC flag
  77.                                              to free the IRQ vector sequencer.
  78.                                              Do use with polling: 1. Start conversion with HAL_ADC_Start(), 2. Later on, when ADC conversion data is needed:
  79.                                              use HAL_ADC_PollForConversion() to ensure that conversion is completed and HAL_ADC_GetValue() to retrieve conversion result and trig another conversion start.
  80.                                              (in case of usage of ADC group injected, use the equivalent functions HAL_ADCExInjected_Start(), HAL_ADCEx_InjectedGetValue(), ...). */

  81.   FunctionalState ContinuousConvMode;    /*!< Specify whether the conversion is performed in single mode (one conversion) or continuous mode for ADC group regular,
  82.                                        after the first ADC conversion start trigger occurred (software start or external trigger).
  83.                                        This parameter can be set to ENABLE or DISABLE. */

  84.   uint32_t NbrOfConversion;       /*!< Specify the number of ranks that will be converted within the regular group sequencer.
  85.                                        To use the regular group sequencer and convert several ranks, parameter 'ScanConvMode' must be enabled.
  86.                                        This parameter must be a number between Min_Data = 1 and Max_Data = 16.
  87.                                        Note: This parameter must be modified when no conversion is on going on regular group (ADC disabled, or ADC enabled without
  88.                                        continuous mode or external trigger that could launch a conversion). */

  89.   FunctionalState DiscontinuousConvMode; /*!< Specify whether the conversions sequence of ADC group regular is performed in Complete-sequence/Discontinuous-sequence
  90.                                        (main sequence subdivided in successive parts).
  91.                                        Discontinuous mode is used only if sequencer is enabled (parameter 'ScanConvMode'). If sequencer is disabled, this parameter is discarded.
  92.                                        Discontinuous mode can be enabled only if continuous mode is disabled. If continuous mode is enabled, this parameter setting is discarded.
  93.                                        This parameter can be set to ENABLE or DISABLE. */

  94.   uint32_t NbrOfDiscConversion;   /*!< Specifies the number of discontinuous conversions in which the main sequence of ADC group regular (parameter NbrOfConversion) will be subdivided.
  95.                                        If parameter 'DiscontinuousConvMode' is disabled, this parameter is discarded.
  96.                                        This parameter must be a number between Min_Data = 1 and Max_Data = 8. */

  97.   uint32_t ExternalTrigConv;      /*!< Select the external event source used to trigger ADC group regular conversion start.
  98.                                        If set to ADC_SOFTWARE_START, external triggers are disabled and software trigger is used instead.
  99.                                        This parameter can be a value of @ref ADC_regular_external_trigger_source.
  100.                                        Caution: external trigger source is common to all ADC instances. */

  101.   uint32_t ExternalTrigConvEdge;  /*!< Select the external event edge used to trigger ADC group regular conversion start.
  102.                                        If trigger source is set to ADC_SOFTWARE_START, this parameter is discarded.
  103.                                        This parameter can be a value of @ref ADC_regular_external_trigger_edge */

  104.   uint32_t ConversionDataManagement; /*!< Specifies whether the Data conversion data is managed: using the DMA (oneshot or circular), or stored in the DR register or transfered to DFSDM register.
  105.                                        Note: In continuous mode, DMA must be configured in circular mode. Otherwise an overrun will be triggered when DMA buffer maximum pointer is reached.
  106.                                        This parameter can be a value of @ref ADC_ConversionDataManagement.
  107.                                        Note: This parameter must be modified when no conversion is on going on both regular and injected groups
  108.                                        (ADC disabled, or ADC enabled without continuous mode or external trigger that could launch a conversion). */

  109.   uint32_t Overrun;                  /*!< Select the behavior in case of overrun: data overwritten or preserved (default).
  110.                                        This parameter applies to ADC group regular only.
  111.                                        This parameter can be a value of @ref ADC_Overrun.
  112.                                        Note: In case of overrun set to data preserved and usage with programming model with interruption (HAL_Start_IT()): ADC IRQ handler has to clear
  113.                                        end of conversion flags, this induces the release of the preserved data. If needed, this data can be saved in function
  114.                                        HAL_ADC_ConvCpltCallback(), placed in user program code (called before end of conversion flags clear).
  115.                                        Note: Error reporting with respect to the conversion mode:
  116.                                              - Usage with ADC conversion by polling for event or interruption: Error is reported only if overrun is set to data preserved. If overrun is set to data
  117.                                                overwritten, user can willingly not read all the converted data, this is not considered as an erroneous case.
  118.                                              - Usage with ADC conversion by DMA: Error is reported whatever overrun setting (DMA is expected to process all data from data register). */

  119.   uint32_t LeftBitShift;             /*!< Configures the left shifting applied to the final result with or without oversampling.
  120.                                           This parameter can be a value of @ref ADCEx_Left_Bit_Shift */

  121.   FunctionalState BoostMode;         /*!< Configures the Boost mode control.
  122.                                         When selecting an analog ADC clock frequency bigger than 20MHz,
  123.                                       it is mandatory to first enable the BOOST Mode.
  124.                                           This parameter can be set to ENABLE or DISABLE. */

  125.   FunctionalState OversamplingMode;        /*!< Specify whether the oversampling feature is enabled or disabled.
  126.                                         This parameter can be set to ENABLE or DISABLE.
  127.                                         Note: This parameter can be modified only if there is no conversion is ongoing on ADC groups regular and injected */

  128.   ADC_OversamplingTypeDef Oversampling;   /*!< Specify the Oversampling parameters.
  129.                                                Caution: this setting overwrites the previous oversampling configuration if oversampling is already enabled. */
  130. }ADC_InitTypeDef;

  131. /**
  132.   * @brief  Structure definition of ADC analog watchdog
  133.   * @note   The setting of these parameters by function HAL_ADC_AnalogWDGConfig() is conditioned to ADC state.
  134.   *         ADC state can be either:
  135.   *         ADC disabled or ADC enabled without conversion on going on ADC groups regular and injected.
  136.   */
  137. typedef struct
  138. {
  139.   uint32_t WatchdogNumber;    /*!< Select which ADC analog watchdog is monitoring the selected channel.
  140.                                    For Analog Watchdog 1: Only 1 channel can be monitored (or overall group of channels by setting parameter 'WatchdogMode')
  141.                                    For Analog Watchdog 2 and 3: Several channels can be monitored (by successive calls of 'HAL_ADC_AnalogWDGConfig()' for each channel)
  142.                                    This parameter can be a value of @ref ADCEx_analog_watchdog_number. */

  143.   uint32_t WatchdogMode;      /*!< Configure the ADC analog watchdog mode: single/all/none channels.
  144.                                    For Analog Watchdog 1: Configure the ADC analog watchdog mode: single channel/all channels, ADC groups regular and/or injected.
  145.                                    For Analog Watchdog 2 and 3: There is no configuration for all channels as AWD1. Set value 'ADC_ANALOGWATCHDOG_NONE' to reset
  146.                                    channels group programmed with parameter 'Channel', set any other value to program the channel(s) to be monitored.
  147.                                    This parameter can be a value of @ref ADCEx_analog_watchdog_mode. */

  148.   uint32_t Channel;           /*!< Select which ADC channel to monitor by analog watchdog.
  149.                                    For Analog Watchdog 1: this parameter has an effect only if parameter 'WatchdogMode' is configured on single channel (only 1 channel can be monitored).
  150.                                    For Analog Watchdog 2 and 3: Several channels can be monitored. To use this feature, call successively the function HAL_ADC_AnalogWDGConfig() for each channel to be added (or removed with value 'ADC_ANALOGWATCHDOG_NONE').
  151.                                    This parameter can be a value of @ref ADC_channels. */

  152.   FunctionalState ITMode;            /*!< Specify whether the analog watchdog is configured in interrupt or polling mode.
  153.                                    This parameter can be set to ENABLE or DISABLE */

  154.   uint32_t HighThreshold;     /*!< Configure the ADC analog watchdog High threshold value.
  155.                                    Depending of ADC resolution selected (16, 14, 12, 10 or 8 bits), this parameter must be a number
  156.                                    between Min_Data = 0x0000 and Max_Data = 0xFFFF, 0x3FFF, 0xFFF, 0x3FF or 0xFF respectively. */

  157.   uint32_t LowThreshold;      /*!< Configures the ADC analog watchdog Low threshold value.
  158.                                    Depending of ADC resolution selected (16, 14, 12, or 8 bits), this parameter must be a number
  159.                                    between Min_Data = 0x0000 and Max_Data = 0xFFFF, 0x3FFF, 0xFFF, 0x3FF or 0xFF respectively. */

  160. }ADC_AnalogWDGConfTypeDef;
复制代码










回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106826
QQ
 楼主| 发表于 2018-9-4 01:13:28 | 显示全部楼层
占2楼,明天继续整理。
回复

使用道具 举报

0

主题

3

回帖

12

积分

新手上路

积分
12
发表于 2018-9-4 23:20:54 | 显示全部楼层
你好版主,我现在也正在调试H7的ADC,使用HAL H7_V1.3.0库,DMA模式采集,  想使用双缓冲,但一直没成功。    我是定时间隔采集,比如:启动ADC转换后,启动定时器,时间到了,就停止ADC转换,再获取缓存接收到的字节数,并读取;当再次启动时,可否让DMA传输再从缓存首地址开始呢?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106826
QQ
 楼主| 发表于 2018-9-5 00:53:25 | 显示全部楼层
小毛驴 发表于 2018-9-4 23:20
你好版主,我现在也正在调试H7的ADC,使用HAL H7_V1.3.0库,DMA模式采集,  想使用双缓冲,但一直没成功。  ...

我还在学习HAL库中。

推荐使用定时器触发,另外,你当前要用DMA自带的双缓冲方式,是没有必要停止的,启动后一直转换即可,并开启DMA中断,获取当前是那个缓冲传输完毕,获取数据即可,可以做到数据的实时获取和处理
回复

使用道具 举报

0

主题

3

回帖

12

积分

新手上路

积分
12
发表于 2018-9-5 10:30:17 | 显示全部楼层
eric2013 发表于 2018-9-5 00:53
我还在学习HAL库中。

推荐使用定时器触发,另外,你当前要用DMA自带的双缓冲方式,是没有必要停止的, ...

非常感谢你的及时回复,我现在就是不知道怎么使用用双缓冲~

#define ADC1_DMA_IRQ      DMA1_Stream0_IRQn
#define  ADC1_DMA_Stream   DMA1_Stream0                                            //ADC1-->DMA1_Stream0
#define ADC1_DMA_CLK_ENABLE()  __HAL_RCC_DMA1_CLK_ENABLE()
#define ADC1_Convert_BufSize       ((uint16_t)300)                                    //电压信号AD转换数据缓存大小                                                                                                                                                       
#define ADC1_SigTriNum     ADC1_Convert_BufSize                                                                                                                        //ADC1 单次触发采集次数
/* 内部函数定义 --------------------------------------------------------------*/
static  void ADC_PeriphClk_Init(void);                                         //ADC外设时钟初始化
static  void ADC1_DMA_Init(void);                                              //ADC1 DMA配置

/* 外部变量定义 --------------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
FlagStatus  ADC1_DataFramEnd;
uint16_t  ADC1_BufEveNum;                                   //ADC1 有效数据个数

uint16_t  ADC1_Buf1[ADC1_Convert_BufSize];                                               
uint16_t  ADC1_Buf2[ADC2_Convert_BufSize];               

/*********************************************************************************************************
* 功能       :ADC初始化(压信号输入)
* 输入参数   :无
* 返回值说明 :无
* 其他说明   :完成压力、电压、电流,共3路ADC输入初始化配置;
**********************************************************************************************************/
void ADC_Init(void)
{
  ADC_GPIO_CLK1_2_ENABLE();
  ADC_GPIO_CLK2_2_ENABLE();

  ADC_PeriphClk_Init();                                                       //ADC外设时钟初始化
  __HAL_RCC_ADC12_CLK_ENABLE();                                               //ADC时钟使能
  
  ADC1_DMA_Init();                                                            //ADC1(压力)初始化   
}  

//ADC外设时钟初始化
static  void ADC_PeriphClk_Init(void)
{  
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

  //ADC转换时钟配置(25M外部晶振,ADC时钟选用PLL2P,其输出=HSE/DINM2*DIVN2/DINP2,即72M)
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;                //ADC外设时钟配置
  PeriphClkInitStruct.PLL2.PLL2M = 5;                                          //DIVM2=5,(可配值:1-63)
  PeriphClkInitStruct.PLL2.PLL2N = 72;                                         //DIVN2=72,(可配值:4-512)
  PeriphClkInitStruct.PLL2.PLL2P = 5;                                          //DIVP2=5, (可配值:1-128)
  PeriphClkInitStruct.PLL2.PLL2Q = 2;                                          //DIVQ2(固定为2)
  PeriphClkInitStruct.PLL2.PLL2R = 2;                                          //DIVR2(固定为2)
  PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2;
  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__);
  }  
}

static void ADC1_DMA_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  ADC_MultiModeTypeDef multimode;
  ADC_ChannelConfTypeDef sConfig;
   
  /*ADC1 GPIO Configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_1;                                 //ADC1_INP5 --> PB1
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);  

  //ADC转换参数配置
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;                         //ADC转换时钟为ADC外设时钟的 1/2
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;                               //16位数据
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;                               //禁止扫描模式(扫描模式用于多通道采集)
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;                               //ADC_EOC_SINGLE_CONV; ADC_EOC_SEQ_CONV
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;                                   //连续转换
  hadc1.Init.NbrOfConversion = 1;                                           //待转换的通道数
  hadc1.Init.DiscontinuousConvMode = DISABLE;                               //间续转换
  hadc1.Init.NbrOfDiscConversion = 1;                                       //
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;                         //软件触发模式
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;   
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_ONESHOT;//ADC_CONVERSIONDATA_DMA_CIRCULAR;    //转换后数据存放至 DMA移位存储器   
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;                            //溢出数据覆盖
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;                          
  hadc1.Init.BoostMode = ENABLE;                                            //Boost=1,最大ADC时钟36M;Boost=0,最大ADC时钟20M
  hadc1.Init.OversamplingMode = DISABLE;  
  
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  //开始校准
  if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  
  multimode.Mode = ADC_MODE_INDEPENDENT;                                  //独立模式
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  //ADC通道配置
  sConfig.Channel = ADC_CHANNEL_5;                                       //ADC1通道5
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5;                      //ADC转换周期 (64.5个时钟,采样率=36M/64.5 约为550K)
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

   /* DMA controller clock enable */
  ADC1_DMA_CLK_ENABLE();
  
  /* ADC1 DMA Init */
  /* ADC1 Init */
  hdma_adc1.Instance = ADC1_DMA_Stream;
  hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
  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_NORMAL;//DMA_CIRCULAR;
  hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;   
  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;            //禁用FIFO
  hdma_adc1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
  hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE;
  if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
   
  __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1);
  
  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(ADC1_DMA_IRQ, 0, 0);        
  HAL_NVIC_EnableIRQ(ADC1_DMA_IRQ);   
}

void ADC1_ConvertStart()
{
  ADC1_ClearBuf();
  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_ConvertBuf,ADC1_SigTriNum);      //DMA数据传输与ADC缓存均为32位,ADC转换值为16位,故数据长度*2
  
  //HAL_DMAEx_MultiBufferStart(&hdma_adc1,(uint32_t)hadc1.Instance->DR,(uint32_t)ADC1_Buf1,(uint32_t)ADC1_Buf2,ADC1_SigTriNum);
  
}

void ADC1_CovStop(void)
{
  uint16_t  TempLen;
  HAL_ADC_Stop(&hadc1);  
  TempLen = __HAL_DMA_GET_COUNTER(&hdma_adc1);   
  ADC1_BufEveNum = ADC1_SigTriNum - TempLen-1;
}

void ADC1_ClearBuf(void)
{
  memset(ADC1_ConvertBuf,0,sizeof(ADC1_ConvertBuf));
  ADC1_BufEveNum =0;
}

还请指教一下双缓冲的配置使用,非常感谢!!!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106826
QQ
 楼主| 发表于 2018-9-5 10:41:24 | 显示全部楼层
小毛驴 发表于 2018-9-5 10:30
非常感谢你的及时回复,我现在就是不知道怎么使用用双缓冲~

#define ADC1_DMA_IRQ      DMA1_Stream0_ ...

这个你自己测试下吧,我没有代码可供参考,或者请教下别人看看
回复

使用道具 举报

0

主题

3

回帖

12

积分

新手上路

积分
12
发表于 2018-9-5 10:46:20 | 显示全部楼层
好的,我自己再折腾折腾,折腾出来了   就发上来~     
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-6 02:36 , Processed in 0.228022 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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