STM32L1x 片上温度传感器采用ADC及工厂校准数据提升测量温度精度

背景

由于项目临时需要温度数据,又不想改动硬件了,反正对温度精度要求不算太高,索性就用MCU片上温度传感器的温度,来替代了。这里自己根据网上帖子做了一些测试用例尝试测温,但是,效果都不理想。发现ST官方提供了一个例程《AN3964应用笔记STM32L1x 温度传感器应用举例》。这个测试例程比较老了,使用固件库开发,对我来说,我用STM32CubeMX或者STM32CubeIDE开发了,都是基于HAL库,所以面临一定的移植工作。本文实现了该应用笔记的解析,同时实现了STM32CubeMX+Keil uVision5的代码移植。这里提供移植过程中的所有文档,希望加速面临同样问题的小伙伴的开发进度。 

AN3964测温过程简介

这里也可以参考原始文档。本文也做点简单介绍,主要是提醒关键信息。

温度测量和数据处理
温度传感器的输出在芯片内部连至 STM32L1x ADC (模数转换器)的通道 16
ADC_IN16), ADC 通道用于采样和转换温度传感器的输出电压。必须进一步处理原始
ADC 数据,以便用标准温度单位显示温度 (摄氏度、华氏度、开氏温度)。
ADC 参考电压 (VDDA = VREF+)连至 STM32L1xxDISCOVERY 板的 3 V VDD 电源。若不
知道 VDD 的精确值,则与使用电池工作的应用一样,必须对它测量以得到正确的总体 ADC
转换范围 (见下节的详细信息)。
电池供电设备上的温度测量
若器件直接用电池供电,则微控制器的供电电压会有变化。若 ADC 参考电压连至 VDDA,即
低引脚数封装器件的连接方式, ADC 转换的值会随电池电压漂移。需要知道供电电压以补偿
该电压漂移。可使用芯片的内部电压参考 (VREFINT)来确定实际供电电压 (VDDA)。
ADC_IN17 内部参考输入上的 ADC 采样值 (Val_VREFINT)可由下式表示:
精确的芯片内部参考电压 (VREFINT)由 ADC 单独采样,在制造过程期间,将每个器件的
对应转换值 (Val_VREFINT_CAL)储存于受保护的存储区,其地址为产品数据手册中规定的
VREFINT_CAL。内部参考电压校准数据为 12 位的无符号数 (右对齐,存储于 2 个字节
中),由用于参考的 STM32L1x ADC 获取
工厂测量的校准数据总体精度为 ± 5 mV (若需更详细信息,请参考数据手册)。
我们可使用上式确定实际的 VDDA 电压,如下所示:
Val_VREFINT = = VREFINT × 212 VREF+ VREFINT × 4096 V DDA
V
VREF_MEAS = = VREF+ 3V 0.01V ±
V
DDA = 3 Val_V × REFINT_CAL Val_VREFINT

当采样温度传感器数据 ValTS_bat 时, ADC 量程会参考前面步骤中确定的实际 VDDA 值。因
为温度传感器工厂校准数据是在
ADC 量程设为 3 V 时获得的,所以我们需要归一化
ValTS_bat,以得到 ADC 量程为 3 V 时应获得的温度传感器数据 (ValTS)。可使用下式归
一化
ValTS_bat
ADC 参考为 3 V 供电 (STM32L1 Discovery 的情况),则不需要这样归一化,可直接使
用采样温度数据确定温度,如
2.2.1 章节:温度传感器校准中所述。

应用程序示例说明
每 2 秒,应用从温度传感器电压获取 16 个采样。使用四分均值算法,对 ADC 原始数据滤波、平均,以降低电源系统的噪声。将结果重新计算为标准的温度测量单位下的数值 (在本例中为 °C)。ADC 原始数据或当前温度值每 2 秒更新一次 LCD 显示,单位为摄氏度。用户可通过按用户按钮在两种温度数据表示之间切换。为演示 STM32L1x 超低功耗微控制器的低功耗能力,在温度传感器数据测量间歇期, CPU切换至停止模式, RTC (实时时钟)唤醒设为 2 秒。 ADC 数据获取和数据传输由直接存储器访问 (DMA)管理在此阶段 CPU 处于低功耗睡眠模式。仅在初始化阶段和数据处理期间, CPU 才处于运行模式,其频率为 16 MHz (基于 HSI 振荡器时钟)。

原始工程修改测试

原始工程是适配STM32L152,同时采用的固件库,我项目的板子使用的是STM32L151同时也没有LCD,想要测试该例程,需要进行更改。

这里只是提示更改过程的主要步骤,具体参考工程代码

设置lcd相关的代码不参与编译,同时修改main.c中相关的调用函数。

原来工程使用的MCU休眠和按键,这里都不需要,所以注释并添加相关代码,实现工程能够正常运行到STM32L151,其中添加延时代码如下 

 //__WFI();  
	//Delay(2000);
	T_StartupTimeDelay = 100000;
while (T_StartupTimeDelay--);

工程实际运行的结果如下:从下图可以看出测量的室温为30°,也算准确。

移植STM32CubeMX+Keil uVision5 

 上述工程对我来说,用途不大,只能用来演示。最终使用到项目上还得完成STM32CubeMX+Keil uVision5移植。这里主要难点是对ADC的配置,可以参考如下配置:

 

Main函数主要代码中

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  printf("   ** TEMPERATURE SENSOR EXAMPLE **    \r\n");


  /* Test user or factory temperature sensor calibration value */
  if ( testFactoryCalibData() == SUCCESS ) {
	getFactoryTSCalibData(&calibdata);
	printf("   ** getFactoryTSCalibData **    \r\n");
  }
  else if ( testUserCalibData() == SUCCESS ) {
	  calibdata = *USER_CALIB_DATA;
	  printf("   ** testUserCalibData **    \r\n");
  }
  else {
    /* User calibration or factory calibration TS data are not available */
		calibdata.TS_CAL_1 = DEFAULT_COLD_VAL;
    calibdata.TS_CAL_2 = DEFAULT_HOT_VAL;
    writeCalibData(&calibdata);
    calibdata = *USER_CALIB_DATA;
	printf("   ** writeCalibData **    \r\n");	
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  
	 if (HAL_ADC_Start_DMA(&hadc,
                        (uint32_t *)ADC_ConvertedValueBuff,
                        ADC_CONV_BUFF_SIZE
                       ) != HAL_OK)
	{
		Error_Handler();
	}  
	HAL_Delay(2000);
	  
	// Process mesured Temperature data - calculate average temperature value in
    processTempData();
	printf("temperature_C = %d\r\n", temperature_C);
  }
  /* USER CODE END 3 */
}

测试结果截图如下:

调试过程问题

调试过程中发现温度一直不稳定,并且不准确偏差太大,都偏差都80°左右,经过详细的对比排查,发现最后四个通道的ADC采样周期设置不准确,修改后,回复正常。

这里也可以用手按住MCU,可以看到温度会又有缓慢上升现象。 

本文使用资源下载路径

STM32L1x片上温度传感器采用ADC及工厂校准数据提升测量温度精度,移植固件库代码,同时实现了CubeMX+KeiluV资源-CSDN文库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/898976.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

得物App3D博物馆亮相“两博会”,正品保障助力消费体验升级

近日,2024中国体育文化博览会、中国体育旅游博览会(以下简称“两博会”)在苏州国际展览中心盛大开幕。本次展会汇聚了众多国内外体育文化、体育旅游领域的顶尖企业和品牌,共同展示体育产业的发展成果和最新趋势。在C展馆C21展位&a…

Adams函数构建器(Function Builder)教程来了

学会使用函数构建器是在进行Adams仿真分析的必备技能,通过函数构建器可以查询和使用Adams的各种设计时函数和运行时函数,并能够构建用户自己的函数,大多数情况下的力或者驱动都不是简单的数字,而是需要函数来驱动的,那…

GEE数据集:2001年-2019年全球土地覆被估算(GLanCE)

目录 简介 数据集说明 空间信息 代码1 代码2 代码链接 APP链接 结果 引用 许可 网址推荐 知识星球 机器学习 简介 全球土地覆被估算(GLanCE) 全球土地覆被估算(GLanCE)数据集利用 30 米空间分辨率的大地遥感卫星图…

【拯救头痛大作战!有效应对焦虑引发的“脑内风暴”】

在这个快节奏、高压力的时代,焦虑似乎成了许多人难以摆脱的“隐形伴侣”。它不仅悄无声息地侵蚀着我们的心理健康,还可能引发一系列生理反应,其中最常见也最让人苦恼的便是——焦虑导致的头疼。今天,就让我们一起探索如何有效应对…

Linux介绍及常用命令

Linux 系统简介 1969 年,AT&T 公司的⻉尔实验室P MIT 合作开发的 Unix,在于创建⼀个⽤于⼤型、并⾏、多⽤户的操作系统Unix 的推⼴:从学校⾛进企业Unix 的版本要两个: AT&T System V ——就是俗称的 系统 5Berkley Soft…

【数据结构】-数组

数组 特点: 数组的地址连续,可以通过下标获取数据。 1. 数组扩容 步骤: $1. 创建一个比原来数组更长的新数组 $2. 让原来数组当中的数据依次复制到新数组当中 $3. 让arr指向新数组,原数组空间释放 2. 数组插入 2.1 最后位置…

kotlin 入门总结

目录 1、构造函数 2、数据类 data class, 3、object 单例类,相当于java线程安全的懒加载 4、companion object 伴生对象,类似于包装静态值的一个区域块 5、解构 6、空安全 7、条件语句 8、集合 9 属性和支持属性 属性 支持属性 10 …

HarmonyOS Next模拟器异常问题及解决方法

1、问题1:Failed to get the device apiVersion. 解决方法:关闭模拟器清除用户数据重启

【java】数组(超详细总结)

目录 一.一维数组的定义 1.创建数组 2.初始化数组 二.数组的使用 1.访问数组 2.遍历数组 3.修改数据内容 三.有关数组方法的使用 1.toString 2. copyOf 四.查找数组中的元素 1.顺序查找 2.二分查找binarySearch 五.数组排序 1.冒泡排序 2.排序方法sort 六.数组逆置…

redis的配置文件解析

我的后端学习大纲 我的Redis学习大纲 1.1.Redis的配置文件: 1.Redis的配置文件名称是:redis.conf 2.在vim这个配置文件的时候,默认是不显示行号的,可以编辑下面这个文件,末尾加上set nu,就会显示行号: 1.…

React源码03 - React 中的更新

03 - React 中的更新 React 中创建更新的方式: 初次渲染:ReactDOM.render、ReactDOM.hydrate 后续更新:setState、forceUpdate 1. ReactDOM.render() 先创建 ReactRoot 顶点对象然后创建 FiberRoot 和 RootFiber创建更新,使应用进…

Qt | http获取网页文件(小项目)

点击上方"蓝字"关注我们 ctrl+r 运行 URL可以自己替换一个试一试 【源码获取】 链接:https://pan.baidu.com/s/1QzHKZPXjkpx2p5TWUS_acA?pwd=5xsd 提取码:5xsd 01、QProgressDialog >>> QProgressDialog 是 Qt 框架中的一个类,主要用于显示一个进…

Java使用dom4j生成kml(xml)文件遇到No such namespace prefix: xxx is in scope on:问题解决

介绍addAttribute和addNamepsace: addAttribute 方法 addAttribute 方法用于给XML元素添加属性。属性(Attributes)是元素的修饰符,提供了关于元素的额外信息,并且位于元素的开始标签中。属性通常用于指定元素的行为或样式&#…

Golang | Leetcode Golang题解之第497题非重叠矩形中的随机点

题目: 题解: type Solution struct {rects [][]intsum []int }func Constructor(rects [][]int) Solution {sum : make([]int, len(rects)1)for i, r : range rects {a, b, x, y : r[0], r[1], r[2], r[3]sum[i1] sum[i] (x-a1)*(y-b1)}return Sol…

ReactOS系统中搜索给定长度的空间地址区间中的二叉树

搜索给定长度的空间地址区间 //搜索给定长度的空间地址区间 MmFindGap MmFindGapTopDown PVOID NTAPI MmFindGap(PMADDRESS_SPACE AddressSpace,ULONG_PTR Length,ULONG_PTR Granularity,BOOLEAN TopDown );PMADDRESS_SPACE AddressSpace,//该进程用户空间 ULONG_PTR Length,…

JavaScript入门中-流程控制语句

本文转载自:https://fangcaicoding.cn/article/52 大家好!我是方才,目前是8人后端研发团队的负责人,拥有6年后端经验&3年团队管理经验,截止目前面试过近200位候选人,主导过单表上10亿、累计上100亿数据…

echart改变最后一个节点的图标

需求 在折线图的最后一个节点增加一个gif动图表示增长 一、静态图的使用 采用symbol属性进行设置,结果就是只能展示静态图 无法插入gif series: [{data: [150, 230, 224, 218, 135, 147, {value:200,symbol:image://https://ylxstatic.storage.ylingxin.com/va…

PostgreSQL数据库查看shared buffer配置

哈喽,大家好,我是木头左! PostgreSQL是一个功能强大的开源关系型数据库管理系统,广泛应用于各种规模的应用程序。在PostgreSQL中,shared buffer是一个重要的性能调优参数,它直接影响到数据库查询的性能。本…

【信息论基础第六讲】离散无记忆信源等长编码包括典型序列和等长信源编码定理

一、信源编码的数学模型 我们知道信源的输出是消息序列,对于信源进行编码就是用码字集来表示消息集,也就是要进行从消息集到码字集的映射。 根据码字的特征我们又将其分为D元码,等长码,不等长码,唯一可译码。 我们通过…

使用Yolov10和Ollama增强OCR

1. 训练自定义 Yolov10 数据集 利用物体检测增强 OCR 的第一步是在数据集上训练自定义 YOLO 模型。YOLO(只看一遍)是一种功能强大的实时对象检测模型,它将图像划分为网格,使其能够在一次前向传递中识别多个对象。这种方法非常适合…