STM32F4系列:ADC功能介绍

1. STM32F4 ADC 简介

    STM32F4xx 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。 STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它具有多达 19 个复用通道,可测量来自 16 个外部源、两个内部源和 VBAT 通道的信号。这些通道的 A/D 转换可在单次、连续、扫描或不连续采样模式下进行。 ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中。ADC 具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。注: STM32F4 的 ADC 最大的转换速率为 2.4Mhz,也就是转换时间为 0.41us(在 ADCCLK=36M,采样周期为 3 个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。

1.1 ADC 特性

  • 可配置 12 位、 10 位、 8 位或 6 位分辨率
  • 在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断
  • 单次和连续转换模式
  • 用于自动将通道 0 转换为通道“ n”的扫描模式
  • 数据对齐以保持内置数据一致性
  • 可独立设置各通道采样时间
  • 外部触发器选项,可为规则转换和注入转换配置极性
  • 不连续采样模式
  • 双重/三重模式(具有 2 个或更多 ADC 的器件提供)
  • 双重/三重ADC 模式下可配置的 DMA 数据存储
  • 双重/三重交替模式下可配置的转换间延迟
  • ADC 转换类型(参见数据手册)
  • ADC电源要求:全速运行时为 2.4 V 到 3.6 V,慢速运行时为 1.8 V
  • ADC 输入范围: VREF— VIN VREF+
  • 规则通道转换期间可产生 DMA 请求
  • 1.2 ADC 工作框图


    IO 口需要使用 ADC 功能,只需要将 IO 口配置为模拟输入,然后再去编程此 IO 口对应的 ADC 通道;
    注意:不是所有的 IO 口都有 ADC 通道,需要查找数据手册的 ADC 通道映射表。

    1.3 通道选择

        STM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。
        通过一个形象的例子可以说明: 假如你在家里的院子内放了 5 个温度探头,室内放了 3 个温度探头; 你需要时刻监视室外温度即可,但偶尔你想看看室内的温度;因此你可以使用规则通道组循环扫描室外的 5 个探头并显示 AD 转换结果,当你想看室内温度时,通过一个按钮启动注入转换组(3 个室内探头)并暂时显示室内温度,当你放开这个按钮后,系统又会回到规则通道组继续检测室外温度。从系统设计上,测量并显示室内温度的过程中断了测量并显示室外温度的过程,但程序设计上可以在初始化阶段分别设置好不同的转换组,系统运行中不必再变更循环转换的配置,从而达到两个任务互不干扰和快速切换的结果。可以设想一下,如果没有规则组和注入组的划分,当你按下按钮后,需要从新配置 AD 循环扫描的通道,然后在释放按钮后需再次配置 AD 循环扫描的通道。
        上面的例子因为速度较慢,不能完全体现这样区分(规则通道组和注入通道组)的好处,但在工业应用领域中有很多检测和监视探头需要较快地处理,这样对 AD 转换的分组将简化事件处理的程序并提高事件处理的速度。
        有 16 条复用通道。可以将转换分为两组:规则转换和注入转换。每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。例如,可按以下顺序对序列进行转换: ADC_IN3、ADC_IN8、 ADC_IN2、 ADC_IN2、 ADC_IN0、 ADC_IN2、 ADC_IN2、 ADC_IN15。

  • 一个规则转换组最多由 16 个转换构成。必须在 ADC_SQRx 寄存器中选择转换序列的规则通道及其顺序。规则转换组中的转换总数必须写入ADC_SQR1 寄存器中的 L[3:0] 位。
  • 一个注入转换组最多由 4 个转换构成。必须在 ADC_JSQR寄存器中选择转换序列的注入通道及其顺序。注入转换组中的转换总数必须写入 ADC_JSQR 寄存器中的 L[1:0] 位。
  • 如果在转换期间修改 ADC_SQRx 或 ADC_JSQR 寄存器,将复位当前转换并向 ADC 发送一
    个新的启动脉冲,以转换新选择的组。
                    通道号   ADC1   ADC2   ADC3
                    通道 0   PA0     PA0     PA0
                    通道 1   PA1     PA1     PA1
                    通道 2   PA2     PA2     PA2
                    通道 3   PA3     PA3     PA3
                    通道 4   PA4     PA4     PF6
                    通道 5   PA5     PA5     PF7
                    通道 6   PA6     PA6     PF8
                    通道 7   PA7     PA7     PF9
                    通道 8   PB0     PB0     PF10
                    通道 9   PB1     PB1     PF3
                    通道 10  PC0     PC0     PC0
                    通道 11  PC1     PC1     PC1
                    通道 12  PC2     PC2     PC2
                    通道 13  PC13   PC13     PC13
                    通道 14  PC4     PC4     PF4
                    通道 15  PC5     PC5     PF5
        注意: 我们使用 ADC 通道时,查找 stm32f405.407 数据手册的 Page46。
    温度传感器、 VREFINT 和 VBAT 内部通道
  • 对于 STM32F40x 和 STM32F41x 器件,温度传感器内部连接到通道 ADC1_IN16。内部参考电压 VREFINT 连接到ADC1_IN17。
  • 对于 STM23F42x 和 STM32F43x 器件,温度传感器内部连接到与 VBAT共用的通道ADC1_IN18。一次只能选择一个转换(温度传感器或 VBAT)。同时设置了温度传感器和 VBAT 转换时,将只进行 VBAT转换。
  • 内部参考电压 VREFINT 连接到 ADC1_IN17。
  • VBAT 通道连接到通道ADC1_IN18。该通道也可转换为注入通道或规则通道。
    注意: 温度传感器、 VREFINT 和 VBAT通道只在主 ADC1 外设上可用。
  • 1.4 ADC 相关寄存器

    1.4.1 外设时钟使能寄存器 (RCC_APB2ENR)


    例如:使能ADC1外设时钟

    RCC->APB2ENR |=(1<<8);//ADC1
    

    1.4.2 ADC 状态寄存器 (ADC_SR)

    1.4.3 ADC 控制寄存器 1 (ADC_CR1)

    1.4.4 ADC 控制寄存器 2 (ADC_CR2)

        
        注意: 开启注入转换有两种方法:
        1. 使用此位开启转换;
        2. 使用 CR1 寄存器的注入组自动转换,再去使能规则转换。

        注意: 在没有 DMA 管理数据,并且规则转换序列长度不为 1 时,必须将此位置 1,才能在每个通道转换结束都得到转换结果。
    1. 注意:单次转换和连续转换可以和扫描模式进行组合。

    1. 单次不扫描: 只转换序列第一个通道,然后结束。
    2. 单次扫描: 转换整个序列一次,然后结束。
    3. 连续不扫描: 连续转换换序列第一个通道。
    4. 连续扫描: 连续转换整个序列。

    2. 注意:一个 ADC 只有一个模数转换器,必须开启模数转换器,才能开启规则组或者注入组的 AD 转换。

    1.4.5 ADC 采样时间寄存器 1 (ADC_SMPR1)

    1.4.6 ADC 采样时间寄存器 2 (ADC_SMPR2)


            注意:组 SMP0~SMP18 分别对应 19 个复用通道的采样时间。
                举例:配置 ADC1_CH 4 的采样时间为 480 周期
                ADC1->SMPR2 |= 7<<(4*3);

    1.4.7 ADC 规则序列寄存器 1 (ADC_SQR1)

    1.4.8 ADC 规则序列寄存器 2 (ADC_SQR2)

    1.4.9 ADC 规则序列寄存器 3 (ADC_SQR3)

    1.4.10 ADC 注入序列寄存器 (ADC_JSQR)


    1.4.11 ADC 注入数据寄存器 x (ADC_JDRx) (x= 1…4)

    1.4.12 ADC 规则数据寄存器 (ADC_DR)


    1.5 ADC 编写流程

    1. 设置 ADC 对应的 GPIO– 模拟输入
    2. 配置 ADC 工作方式 – CR1、 CR2
    3. 配置采样周期
    4. 配置转换序列个数和转换哪个序列
    5. 使能 ADC
    6. 编写 AD 转换函数
      ···使能转换开关
      ···等待转换完成
      ···获取数字量
      那么下面就以内部温度传感器为例,如下代码所示:
    ADC_HandleTypeDef hadc1;//ADC句柄
    
    //初始化ADC
    void MY_ADC_Init(void)
    {   
      hadc1.Instance = ADC1;
      hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;				//4分频,ADCCLK=PCLK2/4=90/4=22.5MHZ
      hadc1.Init.Resolution = ADC_RESOLUTION_12B;						//12位模式
      hadc1.Init.ScanConvMode = DISABLE;								//非扫描模式
      hadc1.Init.ContinuousConvMode = DISABLE;							//关闭连续转换
      hadc1.Init.DiscontinuousConvMode = DISABLE;						//禁止不连续采样模式
      hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;	//使用软件触发
      hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;					//软件触发
      hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;						//右对齐
      hadc1.Init.NbrOfConversion = 1;									//1个转换在规则序列中 也就是只转换规则序列1 
      hadc1.Init.DMAContinuousRequests = DISABLE;						//关闭DMA请求
      hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;					//关闭EOC中断
      if (HAL_ADC_Init(&hadc1) != HAL_OK)								//初始化  
      {
        Error_Handler();
      }
    }
    
    //ADC底层驱动,引脚配置,时钟使能
    //此函数会被HAL_ADC_Init()调用
    //hadc:ADC句柄
    void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
    {
    	if(adcHandle->Instance==ADC1)
    	{
        	__HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟
        }
    }
    
    //获得ADC值
    uint16_t get_adc(uint32_t ch)   
    {
        ADC_ChannelConfTypeDef sConfig = {0};
        
        sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;				//选择内部温度传感器通道
        sConfig.Rank = 1;										//1个序列
        sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;		//采样时间
        if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)//通道配置
        {
          Error_Handler();
        }
    	
        HAL_ADC_Start(&hadc1);                               //开启ADC
    	
        HAL_ADC_PollForConversion(&hadc1,10);                //轮询转换
       
    	return (uint16_t )HAL_ADC_GetValue(&hadc1);	        //返回最近一次ADC1规则组的转换结果
    }
    
    //获取指定通道的转换值,取times次,然后平均 
    //times:获取次数
    //返回值:通道ch的cnt次转换结果平均值
    uint16_t Get_Adc_Average(uint32_t ch,uint8_t cnt)
    {
    	uint32_t temp_val=0;
    	uint8_t n;
    	for(n=0;n<cnt;n++)
    	{
    		temp_val+=get_adc(ch);
    		delay_ms(5);
    	}
    	return temp_val/cnt;
    } 
    
    //得到温度值
    //返回值:温度值(扩大了100倍,单位:℃.)
    short Get_Temprate(void)
    {
    	uint32_t adcx;
    	short result;
     	double temperate;
    	adcx=Get_Adc_Average(ADC_CHANNEL_TEMPSENSOR,10);//读取内部温度传感器通道,10次取平均
    	temperate=(float)adcx*(3.3/4096);		//电压值
    	temperate=(temperate-0.76)/0.0025 + 25; //转换为温度值 
    	result=temperate*=100;					//扩大100倍.
    	return result;
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32F4系列:ADC功能介绍

    发表评论