STM32 关于ADC采交直流问题探讨(一)

前沿

关于STM32采样问题,相信很多人曾遇到过这样的问题,无论是关于ADC底层相关的配置还是ADC采样方案的抉择,或者是ADC软硬件滤波算法,这里博主就自己曾做过的训练题为引申,探讨ADC采样过程中的问题。

1.ADC的认识

1.1 ADC初始化参数

/* Exported types ------------------------------------------------------------*/

/**
  * @brief   ADC Init structure definition  
  */
typedef struct
{
  uint32_t ADC_Resolution;                                 /*!< Configures the ADC resolution dual mode. This parameter can be a value of @ref ADC_resolution */                                   
  FunctionalState ADC_ScanConvMode;             /*!< Specifies whether the conversion is performed in Scan (multichannels)or Single (one channel) mode.
                                                                                   This parameter can be set to ENABLE or DISABLE */
  FunctionalState ADC_ContinuousConvMode;  /*!< Specifies whether the conversion is performed in Continuous or Single mode.
                                                                                   This parameter can be set to ENABLE or DISABLE. */
  uint32_t ADC_ExternalTrigConvEdge;          /*!< Select the external trigger edge and enable the trigger of a regular group.
                                                                           This parameter can be a value of
                                                                       @ref ADC_external_trigger_edge_for_regular_channels_conversion */
  uint32_t ADC_ExternalTrigConv;                  /*!< Select the external event used to trigger the start of conversion of a regular group.
                                                                           This parameter can be a value of
                                                                       @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */
  uint32_t ADC_DataAlign;                 /*!< Specifies whether the ADC data  alignment is left or right. This parameter can be
                                                                       a value of @ref ADC_data_align */
  uint8_t  ADC_NbrOfConversion;           /*!< Specifies the number of ADC conversions  that will be done using the sequencer for
                                                                       regular channel group.This parameter must range from 1 to 16. */
}ADC_InitTypeDef;

涉及的相关参数:ADC分辨率(6/8/10/12位)、扫描或非扫描模式、连续或不连续转换、触发方式、对齐方式等。
       这里值得注意的是规则组转化序列不能超过16。

1.2 ADC通用初始化参数

/**
  * @brief   ADC Common Init structure definition  
  */
typedef struct
{
  uint32_t ADC_Mode;                      /*!< Configures the ADC to operate in
                                               independent or multi mode.
                                               This parameter can be a value of @ref ADC_Common_mode */                                              
  uint32_t ADC_Prescaler;                 /*!< Select the frequency of the clock
                                               to the ADC. The clock is common for all the ADCs.
                                               This parameter can be a value of @ref ADC_Prescaler */
  uint32_t ADC_DMAAccessMode;             /*!< Configures the Direct memory access
                                              mode for multi ADC mode.
                                               This parameter can be a value of
                                               @ref ADC_Direct_memory_access_mode_for_multi_mode */
  uint32_t ADC_TwoSamplingDelay;          /*!< Configures the Delay between 2 sampling phases.
                                               This parameter can be a value of
                                               @ref ADC_delay_between_2_sampling_phases */

}ADC_CommonInitTypeDef;

这里涉及相关ADC单独/多重模式选择,两采样阶段采样间隔,DMA使能/失能,ADC分屏系数(注意ADC的时钟频率不超过36Mhz)

1.3 ADC相关配置库函数

/*  Function used to set the ADC configuration to the default reset state *****/  
void ADC_DeInit(void);

/* Initialization and Configuration functions *********************************/
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);

/* Analog Watchdog configuration functions ************************************/
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold);
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);

/* Temperature Sensor, Vrefint and VBAT management functions ******************/
void ADC_TempSensorVrefintCmd(FunctionalState NewState);
void ADC_VBATCmd(FunctionalState NewState);

/* Regular Channels Configuration functions ***********************************/
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_SoftwareStartConv(ADC_TypeDef* ADCx);
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
uint32_t ADC_GetMultiModeConversionValue(void);

/* Regular Channels DMA Configuration functions *******************************/
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState);

/* Injected channels Configuration functions **********************************/
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge);
void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx);
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);

/* Interrupts and flags management functions **********************************/
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);

2.定时器捕获模式

定时器功能:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和pwm)

2.1 初始化基本定时参数

/**
  * @brief  TIM Time Base Init structure definition  
  * @note   This structure is used with all TIMx except for TIM6 and TIM7.  
  */

typedef struct
{
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF */

  uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                       This parameter can be a value of @ref TIM_Counter_Mode */

  uint32_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.  */

  uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                      This parameter can be a value of @ref TIM_Clock_Division_CKD */

  uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                       reaches zero, an update event is generated and counting restarts
                                       from the RCR value (N).
                                       This means in PWM mode that (N+1) corresponds to:
                                          - the number of PWM periods in edge-aligned mode
                                          - the number of half PWM period in center-aligned mode
                                       This parameter must be a number between 0x00 and 0xFF.
                                       @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;

2.2 输入比较参数初始化

/**
  * @brief  TIM Input Capture Init structure definition  
  */

typedef struct
{

  uint16_t TIM_Channel;      /*!< Specifies the TIM channel.
                                  This parameter can be a value of @ref TIM_Channel */

  uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.
                                  This parameter can be a value of @ref TIM_Input_Capture_Polarity */

  uint16_t TIM_ICSelection;  /*!< Specifies the input.
                                  This parameter can be a value of @ref TIM_Input_Capture_Selection */

  uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
                                  This parameter can be a value of @ref TIM_Input_Capture_Prescaler */

  uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                  This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;

定时器输入捕获模式可以来测量脉冲宽度或者测量频率
1

3.相关训练题及测试要求

3.1 信号采集模块

× 测量直流信号幅值:

  • 输入可调直流信号0~1V,测量相应的信号幅值并在LCD上显示测量值。

× 测量方波信号频率:

  • 输入方波信号频率50~1KHz, 测量其频率并在LCD上显示频率值。
    2

    3.2发挥部分

    • 信号源产生正弦交流信号(50~1KHz),幅值在-1v~+1v范围内可调。STM32测量正弦波信号的幅值和频率,并将测量值显示在LCD上。

    • 显示信号幅值和频率外,在LCD上显示正弦波信号曲线。

4.总体方案流程图

3
对应软件总体框架

/*****************************************************
*   函数功能:主函数模块
*     作者:klaus 邮箱:xcf2016a@outlook.com
*     功能介绍:集成各功能模块
*   版本:1.1(暂无改动)
******************************************************/
int main(void)
{    
    TIM3_Int_Init(1000-1,840-1);
    TIM4_Int_Init(Tim4SetCnt-1,84-1);
    TIM2_pwm_input(0xffffffff,84-1); 
    BSP_ADC_Init();              
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    KEY_Init();
    LED_Init();    
    delay_init(168);
    OLED_Init();

    while(1)
    {
        if(flag_10ms)
        {
            key_action();//按键函数
            if(delay%50==0)    
                Oled_show();//显示函数
            system_maintain();
            sample_process();//采样函数
            flag_10ms=0;
        }
    }
}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32F7中,使用ADC模块进行外部电压集的步骤如下: 1. 配置ADC模块的时钟和引脚:在初始化函数中,需要配置ADC的时钟和引脚。具体的配置方法可以参考STM32F7的官方文档。 2. 配置ADC模块的参数:需要配置ADC模块的样率、样时间、精度等参数。具体的配置方法可以参考STM32F7的官方文档。 3. 启动ADC模块:调用启动函数启动ADC模块。 4. 等待ADC转换完成:ADC转换完成后,会触发中断或者DMA传输完成中断。需要等待中断触发,然后读取ADC转换结果。 5. 读取ADC转换结果:读取ADC转换结果,并进行处理。 下面是一个简单的代码示例,演示如何集外部电压: ``` #include "stm32f7xx.h" void ADC_Init(void) { //1. 配置ADC时钟和引脚 RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; GPIOA->MODER |= GPIO_MODER_MODER0; //PA0作为模拟输入 //2. 配置ADC参数 ADC1->CR1 |= ADC_CR1_RES_12; //12位精度 ADC1->SMPR1 |= ADC_SMPR1_SMP0; //样时间 //3. 启动ADC模块 ADC1->CR2 |= ADC_CR2_ADON; } uint16_t ADC_Read(void) { uint16_t adc_value = 0; //4. 等待ADC转换完成 ADC1->CR2 |= ADC_CR2_SWSTART; while(!(ADC1->SR & ADC_SR_EOC)); //5. 读取ADC转换结果 adc_value = ADC1->DR; return adc_value; } int main(void) { ADC_Init(); while(1) { uint16_t adc_value = ADC_Read(); //进行处理 } } ``` 需要注意的是,这只是一个简单的示例代码,具体的实现方式还需要根据实际的需求进行调整。同时,还需要注意ADC模块的电源和参考电压等设置,以保证样的准确性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值