浅谈STM32 模数转换器 (ADC)(下)

2023-09-25  

温度传感器和VRENFINT通道框图

图片

要使用传感器,请执行以下操作:


选择 ADC1_IN16 或 ADC1_IN18 输入通道。

选择一个采样时间,该采样时间要大于数据手册中所指定的最低采样时间。

在 ADC_CCR 寄存器中将 TSVREFE 位置 1,以便将温度传感器从掉电模式中唤醒。

通过将 SWSTART 位置 1(或通过外部触发)开始 ADC 转换

读取 ADC 数据寄存器中生成的 V SENSE 数据

使用以下公式计算温度:

温度(单位为 °C)= {(V SENSE — V 25 ) / Avg_Slope} + 25


其中:


— V 25 = 25 °C 时的 V SENSE 值


— Avg_Slope = 温度与 V SENSE 曲线的平均斜率(以 mV/°C 或 μV/°C 表示)


由于ADC寄存器的相关配置相对比较简单,这里直接附上测量温度相关的ADC初始化和中断程序:


void ADC_Init()

{

  u32 prigroup = 0;                          

  u32 priority = 0;        


  RCC->APB2ENR  |=  1<<8;    //开ADC1时钟        


  ADC->CCR  =  0;

  ADC->CCR  |=  1<<23;    //使能温度传感器和 V REFINT 通道

  ADC->CCR  |=  1<<16;    //ADCCLK=21mHZ


  ADC1->CR1  =  0;//分辨率12位


  ADC1->CR2  =  0;          //数据右对齐

  ADC1->CR2  |=  1<<10;    //通道只要转换结束,则将EOC置1,使能溢出检测


  ADC1->SMPR1  =0;          //通道16采样时间3T


  ADC1->SQR3  |=  16<<0;


  ADC1->CR1  |=  1<<5;          //使能EOC中断

  ADC1->SR  &=~  (1<<1);        //清中断标记33

  prigroup = NVIC_GetPriorityGrouping();        //得到优先级分组

  priority = NVIC_EncodePriority(prigroup,1,2);  //优先级编码

  NVIC_SetPriority(ADC_IRQn,priority);        //设置中断优先级

  NVIC_EnableIRQ(ADC_IRQn);                  //使能ADC中断


  ADC1->CR2  |=  1<<0;      //使能ADC

  Delay_us(3);

  ADC1->CR2  |=  1<<30;  //启动AD转换

}



u16 ADC1_Value={0};      //定义二维数组,按行存入三个通道的转换结束

u8 ADC1_OK = 0;



//中断处理函数

void ADC_IRQHandler()

{

  if(ADC1->SR  &  (1<<1))

  {      

    ADC1->SR  &=~  (1<<1);        //写0,请标记

    ADC1_Value = ADC1->DR;    //按行依次存入各通道的转换结果

    ADC1_OK  =  1;                //采集完成结束标记置1

  }

}

接着编写主函数测试


#include "stm32f4xx.h"

#include "usart.h"

#include "delay.h"

#include "stdio.h"

#include "ADC.h"



extern u8 ADC1_OK;

extern u16 ADC1_Value;



int main()

{

  float wendu = 0; 


  NVIC_SetPriorityGrouping(7-2);

  Usart1_Init(115200);

  ADC_Init();



  while(1)

  {

    if(ADC1_OK == 1)

    {

      ADC1->SR  &=~ (1<<1);      //清中断标记

      ADC1_OK = 0;

      wendu = 3.3*ADC1_Value/4095;        //求温度数字值对应的模拟电压值

      wendu = (wendu -0.76)*1000/2.5+25;    //计算温度值


      printf("温度AD值:%d wendu = %.lf°C ",ADC1_Value,wendu);

      ADC1->CR2  |=  1<<0;        //再次开启ADC1

      Delay_us(3);

      ADC1->CR2  |=  1<<30;      //触发一次转换

    }

    Delay_ms(1000);

  }

}

从串口可以看到ADC读取的温度值,ADC温度测量成功。

图片

对于电池电压或者其他外部模拟量的测量,配置方法与温度测量类似,这里不再赘述。如果想要让CPU更多地用于算法或者其他功能的处理,同样可以配置DMA进行数据传输。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。