[应用相关]

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

[复制链接]
807|19
手机看帖
扫描二维码
随时随地手机跟帖
大鹏2365|  楼主 | 2022-4-30 23:44 | 显示全部楼层 |阅读模式
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次比较而输出数字值。其电路规模属于中等。其优点是速度较高、功耗低。
29615626d596bf3f60.png

使用特权

评论回复
大鹏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 | 显示全部楼层
13295626d5abed7f40.png

使用特权

评论回复
大鹏2365|  楼主 | 2022-4-30 23:53 | 显示全部楼层
CubeMx配置

    配置时钟 ADC时钟6分频后12M
66037626d5adedc58f.png

使用特权

评论回复
大鹏2365|  楼主 | 2022-4-30 23:53 | 显示全部楼层
配置ADC 数据左对齐 使能连续转换模式
70588626d5b705946b.png

使用特权

评论回复
大鹏2365|  楼主 | 2022-4-30 23:54 | 显示全部楼层
程序设计

使用计算法 :
需要导入 math.h
#include “math.h”
进行转换并计算的代码
uint16_t ADC1temp1(void)
{        uint16_t ADC1_Value;
           float  t,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;
           float  t,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[j])
{
       
        end = j-1;
}
else if (rsis == array_Resis[j])
        break;
else
        start = j+1;
if (end - start <0)
        break;
}
       
if (start-end ==1)
{       
        float R = (array_Temp[start]-array_Temp[end])/(array_Resis[start]-array_Resis[end])*(rsis-array_Resis[end])+array_Temp[end];
        //DisplayDigtal(end);
        return R;
}else
        return array_Temp[j];
}

使用特权

评论回复
大鹏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 | 显示全部楼层

在孔璧内部作金属处理后,可以让内部的各层线路能够彼此连接。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

473

帖子

0

粉丝