首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

MLX90614(GY906)红外温度传感器使用说明、关键寄存器说明,通过STM32F1单片机软件模拟IIC通信协议,以及使用STM32F1单片机软件IIC协议控制并读取温度应用实例。

  • 25-04-25 05:01
  • 2155
  • 11554
blog.csdn.net

1 前言

本躯在使用MLX90614时,问商家要器件手册,他给我发一个毛用没有的示例程序,寄存器呢?客服说不知道您说的什么东西呢亲亲。

在CSDN上查这个器件,全是会员专享不说,给的内容还牛头不对马嘴。

本躯一气之下,决定亲自写文章,帮助后面的使用者快速学习并简单使用这个器件。

本文章代码运行环境:Keil;平台:STM32F103C8T6(注意:本文章代码与我自己测试的完整代码有部分改动,并且改动后的代码并没有测试,所以可能会出现细微的错误,如有错误请指正)

本文章主要内容:GY906硬件基础了解,器件连接,器件选型,STM32F1软件IIC,寄存器种类和配置。

2 MLX90614(GY906)红外传感器硬件

2.1 MLX90614(GY906)(以下全部称为GY906)器件连接

MLX90614支持IIC、UART等协议,一般我们使用更方便的IIC协议。

将你的IIC连接到MCU的IIC,VDD接3.3V,GND接地。

需要注意的是,GY906内部并没有集成上拉电阻,所以SDA和SCL都应该通过串联电阻连接到VCC。这里我推荐4.7KΩ电阻。

GY906的VDD按照器件手册上来说,可以接3-5V电源电压,但由于会出现较大的线性误差,推荐接3.3V电源。

图2-1 典型连接原理图

图2-2 误差与VDD的线性关系图,来源:MLX90614器件手册

如果需要更高的精度,可以采用以下滤波公式:T_C=T-(VDD-3)*0.6

2.2 GY906器件选型

相信大家在选择BAA、DCC等一堆器件时不清楚该选哪个,问客服又问不明白,先看一个图。

图2-3 不同型号的峰值和宽度域 来源:MLX90614器件手册

我们注意到除了xBA,其他型号宽度域是逐渐减小的,宽度域可以简单理解为视域,宽度域越大,红外检测的视野范围越广,但同时视野距离越近。

因此,想要满足长检测距离,应使用宽度域小的型号,比如xCC,甚至于xCI。

前面的x是什么意思呢,是测量精度,市面上常见的有B和D型,B型满足一般需求,D型满足医用级需求,比如红外测温。

在本文中,我们选用DCC型号,大约10CM测距,医用级精度。

2.3 GY906硬件简介和寄存器

GY906内部自动采集环境温度和目标物体温度,内置算法自动滤波。

通过FIR滤波器滤波、增益补偿和偏移补偿,IIR进一步滤波最后计算出最终温度数据。

用户在使用GY906时,使用到的寄存器很少,以下是主要寄存器和说明:

从机地址说明-数据格式功能
0x5A单片机使用从机地址时应左移一位 8位IIC从机地址
寄存器地址名称读写权限数据格式关键功能
0x06RAM_TA只读16位(开尔文)环境温度
0x07RAM_TOBJ1只读16位(开尔文)物体温度(主传感器)
0x08RAM_TOBJ2只读16位(开尔文)物体温度(副传感器,仅存在于双区域型号中)
0x04EEPROM_EMISSIVITY读写16位(0~65535)设置发射率(0.0~1.0)
0x05EEPROM_CONFIG读写16位(位控制)配置滤波、SMBus 地址等
0x2EEEPROM_SMBUS_ADDR读写16位(低7位)

修改 I2C 地址

2.3.1 温度数据寄存器

RAM_TA、RAM_TOBJ1、RAM_TOBJ2(DCC型号不存在)可以直接读取环境温度和物体温度,一共发送24位数据,先发送低八位数据,再发送高八位数据,最后发送PEC校验数据,每八位数据发送过来之后会发送一个ACK,所以我们只需要读取到两次ACK,就可以把全部的16位温度数据读取完毕。如果想使用PEC校验,只需要再读取一次ACK,读取到的PEC数据如果全部为0,则数据无误。

图2-4 接收数据格式 来源:MLX90614器件手册

写入数据与接收数据同理

图2-5 写入数据格式 来源:MLX90614器件手册

2.3.2 EEPROM_EMISSIVITY发射率设置寄存器

根据被测量物体发射率的不同,我们需要设置不同的发射率,比如如果测量人体,发射率应设置为0.96-0.98。

直接向发射率寄存器写入我们的发射率×65535,就可以设定发射率。(如0.98×65535)

2.3.3 EEPROM_CONFIG配置寄存器

在配置寄存器中,我们可以写入数据来控制寄存器是否上电复位(谨慎使用),是否开启强数字滤波(建议开启),和设置SMBus从机地址(一般默认为0x5A)。

位名称功能默认值
15POR(上电复位)1 = 执行复位,0 = 正常0
14IIR_FILTER数字滤波强度(0=弱,1=强)0
13:8保留必须保持 00
7:0SMBus 地址设置 SMBus 从机地址(0x00~0x7F)0x5A

 

2.3.4 EEPROM_SMBUS_ADDR SMBus从机地址寄存器

可以直接读取从机地址或改变从机地址,仅低7位有效。

3 STM32F1软件IIC

由于网上大把软件IIC,在此我不在赘述,直接给出代码(才不是因为我懒)。至于我为什么使用软件IIC,而不使用STM32F1单片机自带的硬件IIC,我只能说硬件IIC谁用谁知道,一个标志位能把你程序直接卡死。

3.1 Delay.c

  1. #include "stm32f10x.h"
  2. void Delay_us(uint32_t xus)
  3. {
  4. SysTick->LOAD = 72 * xus;
  5. SysTick->VAL = 0x00;
  6. SysTick->CTRL = 0x00000005;
  7. while(!(SysTick->CTRL & 0x00010000));
  8. SysTick->CTRL = 0x00000004;
  9. }
  10. void Delay_ms(uint32_t xms)
  11. {
  12. while(xms--)
  13. {
  14. Delay_us(1000);
  15. }
  16. }
  17. void Delay_s(uint32_t xs)
  18. {
  19. while(xs--)
  20. {
  21. Delay_ms(1000);
  22. }
  23. }

3.2 Delay.h

  1. #ifndef __DELAY_H
  2. #define __DELAY_H
  3. void Delay_us(uint32_t us);
  4. void Delay_ms(uint32_t ms);
  5. void Delay_s(uint32_t s);
  6. #endif

3.3 MyIIC.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. //软件模拟I2C
  4. //B10口为SCL;B11为SDA;可自行重新配置
  5. void MyI2C_W_SCL(uint8_t BitValue)
  6. {
  7. GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
  8. Delay_us(10);
  9. }
  10. void MyI2C_W_SDA(uint8_t BitValue)
  11. {
  12. GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
  13. Delay_us(10);
  14. }
  15. uint8_t MyI2C_R_SDA(void)
  16. {
  17. uint8_t BitValue;
  18. BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
  19. Delay_us(10);
  20. return BitValue;
  21. }
  22. void MyI2C_Init(void)
  23. {
  24. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  25. GPIO_InitTypeDef GPIO_InitStructure;
  26. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  27. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
  28. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  29. GPIO_Init(GPIOB, &GPIO_InitStructure);
  30. GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
  31. }
  32. void MyI2C_Start(void)
  33. {
  34. MyI2C_W_SDA(1);
  35. MyI2C_W_SCL(1);
  36. MyI2C_W_SDA(0);
  37. MyI2C_W_SCL(0);
  38. }
  39. void MyI2C_Stop(void)
  40. {
  41. MyI2C_W_SDA(0);
  42. MyI2C_W_SCL(1);
  43. MyI2C_W_SDA(1);
  44. }
  45. void MyI2C_SendByte(uint8_t Byte)
  46. {
  47. uint8_t i;
  48. for (i = 0; i < 8; i ++)
  49. {
  50. MyI2C_W_SDA(Byte & (0x80 >> i));
  51. MyI2C_W_SCL(1);
  52. MyI2C_W_SCL(0);
  53. }
  54. }
  55. uint8_t MyI2C_ReceiveByte(void)
  56. {
  57. uint8_t i, Byte = 0x00;
  58. MyI2C_W_SDA(1);
  59. for (i = 0; i < 8; i ++)
  60. {
  61. MyI2C_W_SCL(1);
  62. if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}
  63. MyI2C_W_SCL(0);
  64. }
  65. return Byte;
  66. }
  67. void MyI2C_SendAck(uint8_t AckBit)
  68. {
  69. MyI2C_W_SDA(AckBit);
  70. MyI2C_W_SCL(1);
  71. MyI2C_W_SCL(0);
  72. }
  73. uint8_t MyI2C_ReceiveAck(void)
  74. {
  75. uint8_t AckBit;
  76. MyI2C_W_SDA(1);
  77. MyI2C_W_SCL(1);
  78. AckBit = MyI2C_R_SDA();
  79. MyI2C_W_SCL(0);
  80. return AckBit;
  81. }

3.4 MyIIC.h

  1. #ifndef __MYI2C_H
  2. #define __MYI2C_H
  3. void MyI2C_Init(void);
  4. void MyI2C_Start(void);
  5. void MyI2C_Stop(void);
  6. void MyI2C_SendByte(uint8_t Byte);
  7. uint8_t MyI2C_ReceiveByte(void);
  8. void MyI2C_SendAck(uint8_t AckBit);
  9. uint8_t MyI2C_ReceiveAck(void);
  10. #endif

4 STM32F1通过软件IIC读取MLX90614温度数据

4.1 MLX90614.c

  1. #include "MyIIC.h"
  2. #include "MLX90614_Address.h"
  3. float a_temp=0; //环境温度
  4. float o_temp=0; //物体温度
  5. uint32_t MLX90614_ReadReg(uint8_t RegAddress)
  6. {
  7. uint8_t Data[2]={0};
  8. uint16_t Data_all=0;
  9. MyI2C_Start();
  10. MyI2C_SendByte(MLX90614_ADDRESS);
  11. MyI2C_ReceiveAck();
  12. MyI2C_SendByte(RegAddress);
  13. MyI2C_ReceiveAck();
  14. MyI2C_Start();
  15. MyI2C_SendByte(MLX90614_ADDRESS | 0x01);
  16. MyI2C_ReceiveAck();
  17. Data[0] = MyI2C_ReceiveByte();
  18. MyI2C_ReceiveAck();
  19. Data[1] = MyI2C_ReceiveByte();
  20. MyI2C_SendAck(1);
  21. MyI2C_Stop();
  22. Data_all=(Data[1]<<8)+Data[0];
  23. return Data_all;
  24. }
  25. void MLX90614_Init(void)
  26. {
  27. MyI2C_Init();
  28. }
  29. void MLX90614_TO(void)
  30. {
  31. int i=MLX90614_ReadReg(MLX90614_RAM_TOBJ1);
  32. i=(i*2)-27315;
  33. o_temp=i*0.01;
  34. }
  35. void MLX90614_TA(void)
  36. {
  37. int i=MLX90614_ReadReg(MLX90614_RAM_TA);
  38. i=(i*2)-27315;
  39. a_temp=i*0.01;
  40. }

4.2 MLX90614.h

  1. #ifndef __MLX90614_H
  2. #define __MLX90614_H
  3. #define float a_temp; //环境温度
  4. #define float o_temp; //物体温度
  5. uint32_t MLX90614_ReadReg(uint8_t RegAddress);
  6. void MLX90614_Init(void);
  7. void MLX90614_TO(void);
  8. void MLX90614_TA(void);
  9. #endif

4.3 MLX90614_Address.h

  1. #ifndef __MLX90614_Address_H
  2. #define __MLX90614_Address_H
  3. #define MLX90614_ADDRESS 0x5A<<1
  4. #define MLX90614_RAM_TA 0x06
  5. #define MLX90614_RAM_TOBJ1 0x07
  6. #define MLX90614_RAM_TOBJ2 0x08
  7. #define MLX90614_EEPROM_EMISSIVITY 0x04
  8. #define MLX90614_EEPROM_CONFIG 0x05
  9. #define MLX90614_EEPROM_SMBUS_ADDR 0x2E
  10. #endif

5 主程序示例

  1. #include "stm32f10x.h"
  2. #include "Delay.h"
  3. #include "MyI2C.h"
  4. #include "MLX90614.h"
  5. #include "MLX90614_Address.h"
  6. int main(void)
  7. {
  8. MLX90614_Init();
  9. Delay_ms(20);
  10. float ambient_temperature=0; //环境温度储存于此
  11. float object_temperature=0; //物体温度储存于此
  12. while (1)
  13. {
  14. MLX90614_TA(); //读取环境温度并储存到a_temp
  15. Delay_ms(20);
  16. MLX90614_TO(); //读取物体温度并储存到o_temp
  17. Delay_ms(20);
  18. ambient_temperature=a_temp;
  19. object_temperature=o_temp;
  20. }
  21. }

6 结语

由此,就能简单得到环境温度和物体温度。

当然,很多内容我都没写,比如写入数据的代码,比如配置发射率和强数字滤波的代码。

再比如说,这样对着额头测体温依然是不准的,因为额头的温度实际上并不是人体核心温度。环境的温度、汗液的散热、血管的收缩和扩张,甚至于此时这个人的血压和心率,都非常影响额头温度和核心温度的差值。当然,这并不是完全无法解决,有兴趣的小伙伴可以自己试试。

并且我还删掉了大部分的注释。软件不难看懂,希望大家能好好学习基础知识,并且自己加上属于自己的注释,当然,如果能修改代码变成自己的代码习惯就更好了。

万事开头难,有了基础打底,剩下的进阶内容大家自己加油。

本躯水平有限,若有错误恳请斧正。

 

注:本文转载自blog.csdn.net的史上最甜的躯的文章"https://blog.csdn.net/m0_70470290/article/details/146568339"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

124
嵌入式
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top