STM32 ADC采集板载温度

STM32 ADC简介

​ STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立使用, 也可以使用双重模式(提高采样率)。STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。 它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。

​ STM32F103 系列最少都拥有 2 个 ADC,我们选择的 STM32F103ZET 包含有 3 个 ADC。 STM32 的 ADC 最大的转换速率为 1Mhz,也就是转换时间为 1us(在 ADCCLK=14M,采样周期 为 1.5 个 ADC 时钟下得到),不要让 ADC 的时钟超过 14M,否则将导致结果准确度下降。

ADC规则通道组和注入通道组解析

​ STM32 将 ADC 的转换分为 2 个通道组:规则通道组注入通道组规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之 后,规则通道才得以继续转换。 通过一个形象的例子可以说明:假如你在家里的院子内放了 5 个温度探头,室内放了 3 个温度探头;你需要时刻监视室外温度即可,但偶尔你想看看室内的温度;因此你可以使用规则通道组循环扫描室外的 5 个探头并显示 AD 转换结果,当你想看室内温度时,通过一个按钮启动注入转换组(3 个室内探头)并暂时显示室内温度,当你放开这个按钮后,系统又会回到规则通道组继续检测室外温度。从系统设计上,测量并显示室内温度的过程中断了测量并显示室外温度的过程,但程序设计上可以在初始化阶段分别设置好不同的转换组,系统运行中不必再变更循环转换的配置,从而达到两个任务互不干扰和快速切换的结果。可以设想一下,如果没有规则组和注入组的划分,当你按下按钮后,需要从新配置 AD 循环扫描的通道,然后在释放按钮后需再次配置 AD 循环扫描的通道。

​ 上面的例子因为速度较慢,不能完全体现这样区分(规则通道组和注入通道组)的好处,但在工业应用领域中有很多检测和监视探头需要较快地处理,这样对 AD 转换的分组将简化事件处理的程序并提高事件处理的速度。

​ STM32 其 ADC 的规则通道组最多包含 16 个转换,而注入通道组最多包含 4 个通道。STM32 的 ADC 可以进行很多种不同的转换模式。

ADC转换模式

单次转换模式

​STM32 的 ADC 在单次转换模式下,只执行一次转换,该模式可以通过 ADC_CR2 寄存器 的 ADON 位(只适用于规则通道)启动,也可以通过外部触发启动(适用于规则通道和注入通道),这是 CONT 位为 0。 以规则通道为例,一旦所选择的通道转换完成,转换结果将被存在 ADC_DR 寄存器中, EOC(转换结束)标志将被置位,如果设置了 EOCIE,则会产生中断。然后 ADC 将停止,直到下次启动。

连续转换模式

在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启 动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1

扫描模式

此模式用来扫描一组模拟通道。 扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被 ADC_SQRX寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT 位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换

CubeMX配置

本次实验使用ADC1采集板载NTC(负温度系数热敏电阻)输入到单片机引脚的电压值,转化为数字量后用数码管显示对应的温度,并可通过串口发送温度信息到串口助手上

时钟配置

首先要设置ADC的时钟,因为不能超过14MHz,所以ADC分频系数选为6,得到12MHz的时钟给到ADC1,2,3

ADC时钟频率:72/6=12MHZ

采样周期设置为1.5时,另外因为采样到值以后进行转换需要12.5周期,那么实际转换时间为;

12MHZ /1.5 /12.5 = 640KHZ

频率换算周期等于1的倒数;

1s/640KHZ=1000 000us /640 000HZ =1.5625us

所以实际采样转换时间为1.5625us

ADC1参数配置

因为硬件电路中NTC输入引脚接到了单片机的PC13,使用的是ADC1的通道13,所以配置ADC1通道13的参数

因为你ADC1的通道0,1,2被其他模块占用了,所以这里显示红色,对配置通道13没影响

Scan Conversion Mode  ADC工作在扫描模式(多通道)还是单次(单通道)模式。可以设置这个参数为ENABLE 或者DISABLE。
Continuous Conversion Mode  ADC模数转换工作在连续模式。可以设置这个参数为 ENABLE或者DISABLE 。
Discontinuous Conversion Mode  ADC模数转换工作在不连续模式(单次模式)。可以设置这个参数为 ENABLE或者DISABLE 。

外部触发转换源可以选择定时器比较事件或者触发事件,这里选择软件触发,用代码启动ADC转换

数码管和串口的引脚也要配置

检测原理

因为NTC热敏电阻的阻值会随着温度的变化而变化,通过一个10k电阻分压后输入到单片机的ADC检测引脚,ADC检测的是输入的电压,并将电压转换为数字量,得到ADC的采集值;

因为热敏电阻不同温度对应的电阻值在数据手册中可以查到,所以根据公式可以算出输入到引脚的电压,将不同的电阻对应的电压做成表格

然后可以参考STC15的ADC采集值计算公式来计算不同的电压经过ADC转换后会得到的采集值

因为32单片机的ADC是12位的,所以上面公式的1024要改为4095( 212 - 1),因为计数值都是从0开始的,0 ~ 4095就刚好4096,所以ADC的采集值 = 4095 * Vin/Vcc

这样,就有了不同温度下的电阻值,电压值,ADC采集值,就可以做成一张表格

把四舍五入后的最小采集值和最大采集值写成一个二维数组,后面只要在程序中,查找ADC转换的采集值处于哪个数组值之间,就可以得知对应的温度值了

程序

程序与之前STC15实战的代码类型,因为同样是使用NTC热敏电阻检测温度

NTC.c

/*
* @name   Get_NTC_Voltage
* @brief  获取NTC的电压
* @param  None
* @retval None
*/
static void Get_NTC_Voltage()
{//开启ADCHAL_ADC_Start(&hadc1);//等待ADC规则组转化完成if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK){NTC.usADC_Value = HAL_ADC_GetValue(&hadc1);     //获取ADC转换结果NTC.fNTC_Voltage = (NTC.usADC_Value*3.3)/4095;  //反向计算出输入ADC引脚的电压printf("ADC转换的原始值 = %d\r\n",NTC.usADC_Value);printf("计算得出的电压值 = %.2f\r\n",NTC.fNTC_Voltage);}else{printf("ADC转换错误或超时!\r\n");}
}
//NTC型号: B3950  10k  1%
//温度表,对应温度-30℃~70℃
//Note:如果采集值 > 3867,则温度低于-30℃;采集值 < 589,则温度高于70℃
const uint16_t  NTC_Table[101][2] =
{{3850,3867},{3837,3854},{3822,3840},{3807,3826},{3791,3810},{3774,3795},{3757,3778},{3739,3761},{3721,3743},{3701,3724},{3681,3704},{3660,3684},{3638,3663},{3616,3641},{3592,3618},{3568,3595},{3543,3570},{3517,3545},{3491,3519},{3463,3492},{3435,3464},{3405,3435},{3375,3405},{3344,3375},{3312,3343},{3280,3311},{3246,3279},{3212,3245},{3177,3211},{3141,3176},{3105,3140},{3067,3104},{3029,3066},{2991,3028},{2951,2990},{2911,2950},{2871,2910},{2829,2870},{2788,2828},{2745,2787},{2705,2744},{2660,2704},{2616,2659},{2572,2615},{2528,2571},{2484,2527},{2440,2483},{2395,2439},{2350,2394},{2305,2349},{2260,2304},  //对应20℃  --下标为50{2216,2259},{2171,2215},{2126,2170},{2082,2125},{2037,2081},{1992,2036},{1947,1991},{1903,1946},{1859,1902},{1815,1858},{1772,1814},{1729,1771},{1687,1728},{1646,1687},{1604,1645},{1564,1603},{1524,1563},{1484,1523},{1446,1483},{1408,1445},{1370,1407},{1334,1369},{1297,1333},{1262,1296},{1228,1261},{1194,1227},{1161,1193},{1128,1160},{1096,1129},{1062,1095},{1035,1067},{1006,1038},{977 ,1009},{949 , 981},{921 , 953},{895 , 926},{869 , 900},{843 , 875},{819 , 850},{795 , 826},{771 , 802},{749 , 779},{727 , 757},{705 , 735},{684 , 714},{664 , 694},{644 , 674},{625 , 654},{607 , 636},{589 , 617}
};
/*
* @name   Get_Temperature_Value
* @brief  获取温度值
* @param  None
* @retval None
*/
static void Get_Temperature_Value()
{uint8_t temp;//获取NTC电压值NTC.Get_NTC_Voltage();//ADC采集值越界检测if(NTC.usADC_Value > 3867)  //最低-30度{NTC.usADC_Value = 3867;printf("Temperature is below -30℃\r\n");}if(NTC.usADC_Value < 589)   //最高 70度{NTC.usADC_Value = 589;printf("Temperature is higher than 70℃\r\n");}//二分法查表if(NTC.usADC_Value > NTC_Table[50][1])  //低于20度{//查询下标为0~49的一维数组,对应-30 ~ 19度for(temp=0;temp<=49;temp++){if((NTC.usADC_Value >= NTC_Table[temp][0]) && (NTC.usADC_Value <= NTC_Table[temp][1])){break;  //找到ADC采集值所在的一维数组,退出循环,得到下标数据temp}}}else if(NTC.usADC_Value < NTC_Table[50][0])  //高于20度{//查询下标为51~100的一维数组,对应21 ~ 70度for(temp=51;temp<=100;temp++){if((NTC.usADC_Value >= NTC_Table[temp][0]) && (NTC.usADC_Value <= NTC_Table[temp][1])){break;  //找到ADC采集值所在的一维数组,退出循环,得到下标数据temp}}}else{temp = 50;  //下标为50}//计算温度NTC.fTemperature = (float)temp  - 30;printf("Temperature is: %.1f℃ \r\n\r\n",NTC.fTemperature);
}

System.c

系统主函数中,每隔一秒在数码管上显示当前获得的温度值

/*
* @name   Run
* @brief  系统运行
* @param  None
* @retval None
*/
static void Run()
{//获取温度值NTC.Get_Temperature_Value();//显示温度if(NTC.fTemperature < 0)  //如果温度是负数{Display.Disp_other(Disp_NUM_3,0x40,Disp_DP_OFF);  //3号数码管显示负号}else                      //否则是正数{Display.Disp_other(Disp_NUM_3,0x00,Disp_DP_OFF);  //3号数码管关闭}Display.Disp_Hex(Disp_NUM_1,(uint8_t)NTC.fTemperature%10,Disp_DP_OFF);Display.Disp_Hex(Disp_NUM_2,(uint8_t)NTC.fTemperature/10,Disp_DP_OFF);HAL_Delay(1000);  //每隔一秒采集一次
}

实验效果


STM32物联网项目-ADC采集实验板板温度(NTC热敏电阻)相关推荐

  1. STM32实现双通道ADC采集电压电流值

    本次的实验是通过配置DMA来获取ADC采集到的数据的. 软件实现如下: adc.c文件 #include "adc.h"#define ADC1_DR_Address ((u32) ...

  2. STM32 F446RET6多通道ADC采集

    本次配置是根据STM32CUBEIDE去开发的 DMA搬运数据规则 使用DMA搬运数据的时候我们会先建立一个数据缓冲区,将DMA采集的数据存放到数据缓冲区内.采集到的ADC的值根据通道的顺序一个一个的 ...

  3. STM32物联网项目-SHT30温湿度采集(IIC通信)

    SHT30温湿度采集(IIC通信) SHT30数字温湿度传感器 SHT3x湿度传感器系列包括低成本版本SHT30.标准版本SHT31,以及高端版本SHT35. SHT3x湿度传感器系列结合了多种功能和 ...

  4. STM32物联网项目-DMA使用介绍(ADC+DAC)

    使用DMA搬运ADC和DAC的值 DMA 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输.无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来 ...

  5. STM32物联网项目-通过ESP12S模块连接TCP服务器

    通过ESP12S模块连接TCP服务器 可参考STC15实战的WiFi通信:http://t.csdn.cn/Aw0Uc ESP-12S模块 引脚功能定义 实验目标 STM32通过串口与ESP-12S模 ...

  6. STM32物联网项目-SPI FLASH编程

    SPI编程--读写Flash芯片(W25Q64JV) FLASH芯片介绍--W25Q64JV W25Q64JV的芯片手册是英文的,用软件翻译了一下,有些地方翻译得不准确,大概了解一下即可,例如芯片的工 ...

  7. STM32物联网项目-RTC时钟

    RTC时钟 RTC简介 实时时钟是一个独立的定时器.RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能.修改计数器的值可以重新设置系统当前的时间和日期. RTC模块和时钟配置系 ...

  8. STM32物联网项目-低功耗模式

    低功耗模式 电源框图 VDD供电区域一般为2V ~ 3.6V,经过电压调节器可降压到1.8V给CPU核心.存储器和内置数字外设供电,为了降低CPU的功耗, 后备供电区域可由电池供电,输入引脚为VBAT ...

  9. STM32物联网项目-DAC输出模拟量以及正弦波

    DAC输出正弦波 DAC介绍 ​ STM32 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输出型的 DAC.DAC 可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合 ...

最新文章

  1. Python使用文本拼图
  2. 09丨缓存异常:如何解决缓存和数据库的数据不一致问题
  3. Linux系统磁盘满了
  4. stm32 web 参数_老司机们都是怎么学习STM32的?
  5. Rochambeau POJ - 2912 (枚举和加权并查集+路径压缩)找唯一裁判
  6. xmlrpc.php 漏洞利用
  7. 如何在Wireshark确定数据集?
  8. ASP.NET 2.0中的Session状态丢失的解决办法
  9. 微软 SQL Server 2016 SP1 开发者版入驻 Windows 容器
  10. c++如何快速写出get set_如何快速写出产品文案?(4大核心方法)
  11. 时钟芯片ds1302的使用
  12. linux ora -03113,ORA-03113解决方法
  13. 个人设想中的TCAX GUI生成的带python脚本代码的ASS字幕文件
  14. python爬虫总结,看这篇就够了
  15. 81 文件操作——关闭文件
  16. C#Unity3d怪物在一定范围内巡逻发现玩家自动跟踪攻击,血量低于30%自动向后跳3米并缓慢回血的代码和使用
  17. 千万别吃着别人,骂着别人
  18. mysql查询手机号199开头_从今天起,你将能用上199开头的手机号了……
  19. SSH Tunnel隧道
  20. python读取excel(读写处理xls或xlsx)

热门文章

  1. Big-man进军Linux系统(一)
  2. Python股票监控机器人,加强版!
  3. 关于髋关节固定支具的介绍
  4. dexie.js 中文教程
  5. 小梅哥FPGA时序分析和约束实例演练课程
  6. UEM系列(二)初识UEM“探针”技术
  7. 计算机专业学生宿舍用台式,大学带台式机的人多吗 方便吗
  8. Mac anaconda相关
  9. Java(设计模式)
  10. 【商品架构day5】淘宝:TOP1的商品系统长什么样子