大鹏2365 发表于 2022-4-30 23:44

STM32 Cubemx 使用AD转换获取温度值

AD基本原理

ADC 全称:Analog to Digital Concerter,称为模/数转换器或者模拟/数字转换器。是指将连续变化的模拟信号转换为离散的数字信号的器件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9jtsVpBg-1581689219083)(https://gitee.com/nie_hen/test/raw/master/小书匠/1567820870143.png)]
常用的ADC有积分型、逐次逼近型、并行比较型/串并行型、Σ -Δ调制型、电容阵列逐次比较型及压频变换型。
我们使用的是 逐次逼近性。
逐次逼近型AD由一个比较器和DA转换器通过逐次比较逻辑构成,从MSB开始,顺序地对每一位将输入电压与内置DA转换器输出进行比较,经n次比较而输出数字值。其电路规模属于中等。其优点是速度较高、功耗低。


大鹏2365 发表于 2022-4-30 23:46

A/D转换器的主要技术指标
A/D完成一次转换所需要的时间。转换时间的倒数为转换速率。
分辨率:
衡量A/D转换器能够分辨出输入模拟量最小变化程度的技术指标。用输出的二进制位数或BCD码位数表示。
量化误差:
量化过程引起的误差称为量化误差。是由于有限位数字量对模拟量进行量化而引起的误差。

大鹏2365 发表于 2022-4-30 23:46

AD转换
ADC时钟 : ADC_CLK由 PCLK2经过分频产生,最大是 14M,(分频具体见stm32时钟RCC部分)。一般我们设置 PCLK2=HCLK=72M
采样时间 : 采样周期最小是 1.5 个(ADC_CLK 周期,1/ADC_CLK),即如果我们要达到最快的采样,那么应该设置采样周期为 1.5 个周期。

大鹏2365 发表于 2022-4-30 23:47

一般设置 PCLK2=72M,经过 ADC 预分频器(6分频)能分频到最大的时钟只能是 12M,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us,这个是最常用的。
数据储存的对齐方式:数据可以左对齐和右对齐,一般使用右对齐。

ADC转换方式选择:查询、中断和DMA、

大鹏2365 发表于 2022-4-30 23:47

应用 温度检测

P1接热敏电阻(NTC),型号MF52A103G3380。阻值10K,2%精度;B值3380K。

(1)单片机程序采集:
Vx = (ADC1_Value * 3.3) / 4096;

大鹏2365 发表于 2022-4-30 23:48

(2)计算Rt实际电阻值:
Rt =(R21* Vx) / (3.3-Vx); //由电路,推出电阻与电压关系
将(1)式代入得Rt=(R21* ADC1_Value)/ (4096-ADC1_Value)
即使Rt=(10000* ADC1_Value)/ (4096-ADC1_Value)

大鹏2365 发表于 2022-4-30 23:50

(3)数据处理
查表方式
根据Rt=R0exp{B(1/T-1/T0)}, 可以设计t与Rt之间表格
根据(2)的结果,查表得到温度t。
直接计算,利用"math.h“
温度T与电阻Rt的关系
T=1/(ln(Rt/R0)/B+1/T0)
对应的摄氏温度t=T-273.15=1/(ln(Rt/R0)/B+1/T0)-273.15

大鹏2365 发表于 2022-4-30 23:50

大鹏2365 发表于 2022-4-30 23:53

CubeMx配置

    配置时钟 ADC时钟6分频后12M

大鹏2365 发表于 2022-4-30 23:53

配置ADC 数据左对齐 使能连续转换模式

大鹏2365 发表于 2022-4-30 23:54

程序设计

使用计算法 :
需要导入 math.h
#include “math.h”
进行转换并计算的代码
uint16_t ADC1temp1(void)
{        uint16_t ADC1_Value;
       floatt,Rt;       
       HAL_ADC_Start(&hadc1);
           HAL_ADC_PollForConversion(&hadc1, 50);
        if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
       {
           ADC1_Value = HAL_ADC_GetValue(&hadc1);
          Rt=(float)((10000*ADC1_Value)/ (4096-ADC1_Value));
       t=1/(log((Rt/10000))/3380+1/(273.15+25))-273.15;/ /t=1/(ln(Rt/R0)/B+1/T0)-273.15
        return 10*t;//扩大10倍,含1位小数
       }
}

大鹏2365 发表于 2022-4-30 23:55

程序设计

使用计算法 :
需要导入 math.h
#include “math.h”
进行转换并计算的代码
uint16_t ADC1temp1(void)
{        uint16_t ADC1_Value;
       floatt,Rt;       
       HAL_ADC_Start(&hadc1);
           HAL_ADC_PollForConversion(&hadc1, 50);
        if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
       {
           ADC1_Value = HAL_ADC_GetValue(&hadc1);
          Rt=(float)((10000*ADC1_Value)/ (4096-ADC1_Value));
       t=1/(log((Rt/10000))/3380+1/(273.15+25))-273.15;/ /t=1/(ln(Rt/R0)/B+1/T0)-273.15
        return 10*t;//扩大10倍,含1位小数
       }
}


调用这个函数 获取到的返回值 就是温度的十倍 可以直接放到数码管显示的函数中。
用数码管进行显示温度值。


大鹏2365 发表于 2022-4-30 23:55

使用查表法:
根据阻值计算温度计算起来费时间,增加功耗。查表法是将阻值和温度根据该温度传感器对应起来,计算出来阻值根据二分查找法找到对应的温度,并使用线性计算就可以获取温度值。

大鹏2365 发表于 2022-4-30 23:58

写出温度和阻值所对应的的数组
float array_Temp[] = {
-40,-30,-20,-10,-5,-3,-1,0,
2,4,6,8,10,13,15,18,
20,22,24,25,26,27,28,29,
30,31,32,33,34,35,36,37,38,
39,40,42,45,48,52,60,65,
70,75,80,85,90,95,100,105,

};
float array_Resis[] = {
201,116,70.03,43.35,34.48,31.52,28.85,27.62,
25.32,23.23,21.34,19.63,18.07,15.98,14.47,13.09,
12.11,11.21,10.39,10.00,9.631,9.277,8.938,8.613,
8.302,8.004,7.718,7.444,7.180,6.928,6.683,6.654,6.230,
6.016,5.810,5.423,4.897,4.429,3.883,3.001,2.582,
2.223,1.921,1.667,1.451,1.268,1.112,0.977,0,8262,

};

大鹏2365 发表于 2022-4-30 23:58

使用二分法查找 以及线性计算法
float search_temp(float rsis)
{
int start=0,end=sizeof(array_Temp);
        int j;
while(1)
{
j = (end + start)/2;
if (rsis > array_Resis)
{
       
        end = j-1;
}
else if (rsis == array_Resis)
        break;
else
        start = j+1;
if (end - start <0)
        break;
}
       
if (start-end ==1)
{       
        float R = (array_Temp-array_Temp)/(array_Resis-array_Resis)*(rsis-array_Resis)+array_Temp;
        //DisplayDigtal(end);
        return R;
}else
        return array_Temp;
}

大鹏2365 发表于 2022-4-30 23:59

上面这个函数需要传入阻值
阻值的计算是在ADC计算法那里,最后一步换成调用这个函数。

Pulitzer 发表于 2022-10-7 09:05


电压范围称为工作电源电压

Uriah 发表于 2022-10-7 16:06


防止因瞬间大电流引起的电源电压下降

Bblythe 发表于 2022-10-7 19:05


与15号引脚连接的C1称为旁路电容

童雨竹 发表于 2023-6-1 08:02


在孔璧内部作金属处理后,可以让内部的各层线路能够彼此连接。
页: [1]
查看完整版本: STM32 Cubemx 使用AD转换获取温度值