GD32F470 GY-906 MLX90614ESF BAA BCC DCI IR红外测温传感器模块温度采集模块移植

news2024/11/26 19:20:33

2.12 MLX90614红外无接触测温传感器
MLX90614 系列模块是一组通用的红外测温模块。在出厂前该模块已进行校验及线性化,具有非接触、体积小、精度高,成本低等优点。被测目标温度和环境温度能通过单通道输出,并有两种输出接口,适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设备应用等。测温方式可分为接触式和非接触式,接触式测温只能测量被测物体与测温传感器达到热平衡后的温度,所以响应时间长,且极易受环境温度的影响;而红外测温是根据被测物体的红外辐射能量来确定物体的温度,不与被测物体接触,具有影响动被测物体温度分布场,温度分辨率高、响应速度快、测温范围广、不受测温上限的限制、稳定性好等特点,所以我们选择mlx90614来作为红外测温模块。
  单片机与mlx90614红外测温模块之间通信的方式是“类IIC”通信,意思就是通信方式跟IIC通信方式很像但又不是IIC,它有另外一个名字叫做SMBus。SMBus (System Management Bus)是 1995 年由 intel 公司提出的一种高效同步串行总线,SMBus 只有两根信号线:双向数据线和时钟信号线,容许 CPU 与各种外围接口器件以串行方式进行通信、交换信息,即可以提高传输速度也可以减小器件的资源占用,另外即使在没有SMBus 接口的单片机上也可利用软件进行模拟。

2.12.1 模块来源
采购链接:GY-906 MLX90614ESF BAA BCC DCI IR红外测温传感器模块温度采集
资料下载链接:https://pan.baidu.com/s/1AsEBvVCiNAvTKqTeGSA60w
提取码:g06n

2.12.2 规格参数
工作电压:4.5~5.5V
工作电流:1.3~2.5mA
工作电流:1.3~2.5mA

2.12.3 移植过程
我们的目标是在梁山派GD32F470上能够测量物体温度和环境温度的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.12.3.1 查看资料
MLX90614中有两个存储器,分别为EEPROM和RAM。

  • MLX90614中共有32个字长为16位的EEPROM存储单元,其地址为000H—01FH。EEPROM中所有的寄存器都是可以通过SMBus进行读取,但只有部分寄存器是可以进行改写的(地址为0x00, 0x01, 0x02, 0x03, 0x04, 0x05*,0x0E, 0x0F, 0x19)。可改写部分如下图所示。因在出厂前模块已进行校验及线性化,所以我们直接使用默认参数,不需要修改。
名称功能说明地址
Tomax测量物体温度上限设定00H
Tomin测量物体温度下限设定01H
PWMCTRL测量物体温度下限设定02H
Ta rangePWM控制03H
Emissivity correction conefficient环境温度范围设定04H
Config Register1发射率校准系数:0.1-105H
SMBus address(LSByte only)配置寄存器0EH

在这里插入图片描述

  • MLX90614中总共有32个17位的RAM存储单元,用户不能通过RAM来写入数据,只能读取RAM中的部分存储单元读取16位存储数据。其采集的环境温度数据保存在地址06H存储单元中,采集的被测物体温度数据存储在07H存储单元中。因此运用存储在RAM地址中的数据,通过公式的计算,可以得到环境温度Ta及被测物体温度数据To。
    在这里插入图片描述
    时序说明
    需要注意的是数据的低8位在前面,高8位在后。

在这里插入图片描述
器件地址(Slave Address)在数据手册中有说明,默认器件地址为0X5A;

在这里插入图片描述
命令(Command)是根据要控制的是RAM还是eeprom来决定一个字节中的BIT7BIT5。剩余的BIT4BIT0由要操控的地址决定。

在这里插入图片描述
例如,我要读取RAM的Ta温度数据,则命令组成见下表。其中RAM地址为000x_xxxx,Ta温度数据地址为0x06=0000_0110,只取低5位则为xxx0_0110。

在这里插入图片描述
PEC是一个多项式为X8+X2+X1+1的CRC-8校验数据。
在数据手册中举了两个例子。其中0xB4为器件地址左移一位后的值。
在这里插入图片描述
得到温度的原始数据后,根据数据手册的说明进行换算即可得到温度。

在这里插入图片描述
以上是手册中举了一个例子,如果读取到的温度数据是0X3AF7,其10进制为15095,将10进制数 除以50或者乘以0.02得到301.9,再减去273.15即可得到实际温度。
温度 = 温度原始数据 * 0.02 - 273.15

该温度换算公式对To和Ta都适用。
2.12.3.2 引脚选择

测温传感器立创·梁山派
VIN5V
GNDGND
SCLPB9
SDAPB8

在这里插入图片描述

2.12.3.3 移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_mlx90614.c与bsp_mlx90614.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_mlx90614.c中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_mlx90614.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月19日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/

#include "bsp_mlx90614.h"
#include "bsp_usart.h"
#include "stdio.h"
#include "systick.h"


/******************************************************************
 * 函 数 名 称:MLX90614_GPIO_Init
 * 函 数 说 明:MLX90614的引脚初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:MLX90614是5V,而且立创·梁山派开发板的引脚输出是3.3V,
 *             故设置引脚模式时,必须设置为开漏模式
******************************************************************/
void MLX90614_GPIO_Init(void)
{
  /* 使能时钟 */
    rcu_periph_clock_enable(RCU_SCL);
        rcu_periph_clock_enable(RCU_SDA);
    
        /* 配置SCL为输出模式 */
        gpio_mode_set(PORT_SCL,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_SCL);
        /* 配置为推挽输出 50MHZ */
        gpio_output_options_set(PORT_SCL,GPIO_OTYPE_OD,GPIO_OSPEED_50MHZ,GPIO_SCL);
        
        /* 配置SDA为输出模式 */
        gpio_mode_set(PORT_SDA,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_SDA);
        /* 配置为推挽输出 50MHZ */
        gpio_output_options_set(PORT_SDA,GPIO_OTYPE_OD,GPIO_OSPEED_50MHZ,GPIO_SDA);
}


/******************************************************************
 * 函 数 名 称:IIC_Start
 * 函 数 说 明:IIC起始时序
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Start(void)
{
        SDA_OUT();
        
        SDA(1);
        delay_us(5);
        SCL(1); 
        delay_us(5);
        
        SDA(0);
        delay_us(5);
        SCL(0);
        delay_us(5);
                       
}
/******************************************************************
 * 函 数 名 称:IIC_Stop
 * 函 数 说 明:IIC停止信号
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Stop(void)
{
        SDA_OUT();
        SCL(0);
        SDA(0);
        
        SCL(1);
        delay_us(5);
        SDA(1);
        delay_us(5);
        
}

/******************************************************************
 * 函 数 名 称:IIC_Send_Ack
 * 函 数 说 明:主机发送应答或者非应答信号
 * 函 数 形 参:0发送应答  1发送非应答
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Send_Ack(unsigned char ack)
{
        SDA_OUT();
        SCL(0);
        SDA(0);
        delay_us(5);
        if(!ack) SDA(0);
        else         SDA(1);
        SCL(1);
        delay_us(5);
        SCL(0);
        SDA(1);
}


/******************************************************************
 * 函 数 名 称:I2C_WaitAck
 * 函 数 说 明:等待从机应答
 * 函 数 形 参:无
 * 函 数 返 回:0有应答  1超时无应答
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned char I2C_WaitAck(void)
{
        
        char ack = 0;
        unsigned char ack_flag = 10;
        SCL(0);
        SDA(1);
        SDA_IN();
        delay_us(5);
        SCL(1);
        delay_us(5);

        while( (SDA_GET()==1) && ( ack_flag ) )
        {
                ack_flag--;
                delay_us(5);
        }
        
        if( ack_flag <= 0 )
        {
                IIC_Stop();
                return 1;
        }
        else
        {
                SCL(0);
                SDA_OUT();
        }
        return ack;
}

/******************************************************************
 * 函 数 名 称:Send_Byte
 * 函 数 说 明:写入一个字节
 * 函 数 形 参:dat要写人的数据
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void Send_Byte(uint8_t dat)
{
        int i = 0;
        SDA_OUT();
        SCL(0);//拉低时钟开始数据传输
        
        for( i = 0; i < 8; i++ )
        {
                SDA( (dat & 0x80) >> 7 );
                __nop();
                SCL(1);
                delay_us(5);
                SCL(0);
                delay_us(5);
                dat<<=1;
        }        
}

/******************************************************************
 * 函 数 名 称:Read_Byte
 * 函 数 说 明:IIC读时序
 * 函 数 形 参:无
 * 函 数 返 回:读到的数据
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned char Read_Byte(void)
{
        unsigned char i,receive=0;
        SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
        {
        SCL(0);
        delay_us(5);
        SCL(1);
        delay_us(5);
        receive<<=1;
        if( SDA_GET() )
        {        
            receive|=1;   
        }
        delay_us(5); 
    }                                         
        SCL(0); 
  return receive;
}


/******************************************************************
 * 函 数 名 称:PEC_Calculation
 * 函 数 说 明:PEC校验
 * 函 数 形 参:pec要校验的数据地址   len校验的长度
 * 函 数 返 回:校验后的值
 * 作       者:LC
 * 备       注:无
******************************************************************/
static unsigned char PEC_Calculation(unsigned char *dat , unsigned char len)
{
    unsigned char i;
    unsigned char crc=0;
    while( len-- )
    {
        crc ^= *dat++;
        for( i=0 ; i<8 ; i++ )
        {
            if( crc&0x80 ) 
            {
                crc = (crc<<1)^0x07;
            } 
            else 
            {
                crc = (crc<<1);
            }
        }
    }
    return crc;
}

/************************************************************
 * 函数名称:MLX90615_Read
 * 函数说明:读取MLX90615的温度
 * 型    参:SlaveAddr = 器件地址  RegAddr = 要操作的寄存器地址
 * 返 回 值:温度值
 * 备    注:   SlaveAddr = 0X5A默认器件地址    
 *              RegAddr   = 0X07读取被测量物体温度   
 *              RegAddr   = 0X06读取环境温度 
*************************************************************/
#define CRC_VERIFY_ENABLE 1
float MLX90614_Read(unsigned char SlaveAddr, unsigned char RegAddr)
{
        int i = 0;
        unsigned char buff[3]={0};        //保存温度高低位与校验码
        unsigned char arr[6]={0};        //校验数据使用
        uint16_t temp = 0;                        //高低位整合数据保存
        float T=0.0;                                //换算出的实际温度
        
        IIC_Start();
        Send_Byte((SlaveAddr<<1)|0);//写命令
        I2C_WaitAck();                 //等待响应

    
        Send_Byte(RegAddr);//写入要操作的寄存器地址
        I2C_WaitAck();
   
    do{
        delay_1ms(1);
        IIC_Start();        //重新开始IIC
        Send_Byte((SlaveAddr<<1)|1);        //读命令
    }while( I2C_WaitAck() );

        buff[0] = Read_Byte();                        //保存温度数据的低8位
        IIC_Send_Ack(0);                                //主机发送应答
        buff[1] = Read_Byte();                        //保存温度数据的高8位
        IIC_Send_Ack(0);                                //主机发送应答
        buff[2] = Read_Byte();                        //保存校验码
        IIC_Send_Ack(1);                                //主机发送应答
        IIC_Stop();        //停止时序                                                        
                  
        
//使用校验
#if CRC_VERIFY_ENABLE
    arr[0] = (SlaveAddr<<1);    //器件地址+写     
    arr[1] = RegAddr;           //命令
    arr[2] = (SlaveAddr<<1)+1;  //器件地址+读
    arr[3] = buff[0];           //数据低8位
    arr[4] = buff[1];           //数据高8位
    
    if( PEC_Calculation(arr, 5) == buff[2] )//如果校验正确
    {
        temp = (short)(buff[1]<<8) | buff[0];//整合高低位
        T = (temp * 0.02) - 273.15 ;         //带入公式换算出实际温度
    }
    else
    {
        printf("ERROR CODE 4\r\n");
    }
#endif   
        
//不使用校验
#if !CRC_VERIFY_ENABLE
    temp = (uint16_t)(buff[1]<<8) | buff[0];
    T = (temp*0.02)-273.15 ;
#endif
        
        return T;
}                                                                                  


在文件bsp_mlx90614.h中,编写如下代码。

#ifndef _BSP_MLX90614_H_
#define _BSP_MLX90614_H_

#include "gd32f4xx.h"

//端口移植
#define RCU_SDA RCU_GPIOB
#define PORT_SDA GPIOB
#define GPIO_SDA GPIO_PIN_8

#define RCU_SCL RCU_GPIOB
#define PORT_SCL GPIOB
#define GPIO_SCL GPIO_PIN_9

//设置SDA输出模式
#define SDA_OUT()        gpio_mode_set(PORT_SDA,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_SDA)
//设置SDA输入模式
#define SDA_IN()        gpio_mode_set(PORT_SDA,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,GPIO_SDA)
//获取SDA引脚的电平变化
#define SDA_GET()        gpio_input_bit_get(PORT_SDA,GPIO_SDA)
//SDA与SCL输出
#define SDA(x)          gpio_bit_write(PORT_SDA,GPIO_SDA, (x?SET:RESET))
#define SCL(x)          gpio_bit_write(PORT_SCL,GPIO_SCL, (x?SET:RESET))


void MLX90614_GPIO_Init(void);
float MLX90614_Read(unsigned char SlaveAddr, unsigned char RegAddr);
#endif

2.12.4 移植验证
在自己工程中的main主函数中,编写如下。

/********************************************************************************
  * 文 件 名: main.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2022年04月19日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "sys.h"
#include "bsp_usart.h"
#include "bsp_mlx90614.h"

/************************************************
函数名称 : main
功    能 : 主函数
参    数 : 无
返 回 值 : 无
作    者 : LC
*************************************************/
int main(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
    systick_config();                                                  // 滴答定时器初始化
    sart_gpio_config(9600U);                                          // 串口0初始化
    MLX90614_GPIO_Init();
    printf("start\r\n");
    while(1) 
        {
            printf("temperature = %.2f\r\n", MLX90614_Read(0X5A, 0X07) );
            delay_1ms(1000);  
    }
}

移植现象:测量手心温度为36℃左右。

在这里插入图片描述
移植成功示例,见文件2.12.4-1 。

文件2.12.4-1

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

齐力控股集团现已加入2024年第13届生物发酵展

参展企业介绍 齐力控股集团专业生产高精度卫生级不锈钢设备配件及管道所有连接件、锻造、精加工一站式服务。产品广泛适用于制药、饮料、乳制品、啤酒、生物化工等领域。所有产品均按3A、SMS、DIN、RJT、IDF、DS等标准制造&#xff0c;所有产品均达到GMP药典要求。我们是一家有…

数字乡村创新之路:科技引领农村实现高质量发展

随着信息技术的快速发展&#xff0c;数字乡村建设已成为推动农村高质量发展的重要引擎。数字乡村通过科技创新&#xff0c;不仅改变了传统农业生产方式&#xff0c;也提升了乡村治理水平&#xff0c;为农民带来了更加便捷的生活。本文将从数字乡村的内涵、科技引领农村高质量发…

AAA Stylized Projectiles Vol1

28种具有命中和闪光效果的独特投射物:咒语、火球、箭、子弹、激光等等! 该资产包括: -28种独特的投射物(咒语、火球、箭头、子弹、激光等),与AAA魔术圈、盾牌和3D激光包风格相同 -27种独特的命中效果 -25个闪光效果 -96个纹理 -7个多用途粒子着色器 -演示场景拍摄脚本 -实…

2月白酒行业线上(京东天猫淘宝)电商数据分析:知名酒企全线飘红,同比增长120%!

2024年2月&#xff0c;白酒行业迎来了一波销售热潮。 从鲸参谋数据来看&#xff0c;在综合电商平台&#xff08;京东天猫淘宝&#xff09;白酒销售累计卖出约624万件&#xff0c;同比去年涨幅63%&#xff1b;销售额累计约49亿元&#xff0c;同比去年涨幅123%。白酒行业在整体酒…

JS继承与原型、原型链

在 JavaScript 中&#xff0c;继承是实现代码复用和构建对象关系的重要概念。本文将讨论原型链继承、构造函数继承以及组合继承等几种常见的继承方式&#xff0c;并提供相应的示例代码&#xff0c;并分析它们的特点、优缺点以及适用场景。 在开始讲解 JavaScript 的继承方式之…

VUE——概述

vue是前端框架&#xff0c;基于MVVM思想。 引入 从官网下载vue文件 <script src"js/vue.js"></script> 定义vue对象 new Vue({el: "#x",//vue接管区域&#xff0c;#表示选择器&#xff0c;x是id名字data: {message: "y"} })案例…

vue两个特性和什么是MVVM

一、什么是vue 1.构建用户界面 用vue往html页面中填充数据&#xff0c;非常的方便 2.框架 框架是一套线成的解决方案 vue的指令、组件&#xff08;是对ui结构的复用&#xff09;、路由、vuex 二、vue的特性 1.数据驱动视图 2.双向数据绑定 1.数据驱动视图 数据的变化会驱动…

MySQL 8.0.13安装配置教程

写个博客记录一下&#xff0c;省得下次换设备换系统还要到处翻教程&#xff0c;直接匹配自己常用的8.0.13版本 1.MySQL包解压到某个路径 2.将bin的路径加到系统环境变量Path下 3.在安装根目录下新建my.ini配置文件&#xff0c;并用编辑器写入如下数据 [mysqld] [client] port…

【漏洞复现】用友NC-Cloud系统queryRuleByDeptId存在SQL注入漏洞

“ 如棠安全的技术文章仅供参考&#xff0c;此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的…

世优科技上榜2024年度《中国虚拟数字人影响力指数报告》

日前&#xff0c;第三期《中国虚拟数字人影响力指数报告》在中国网络视听大会上正式发布。本期《报告》由中国传媒大学媒体融合与传播国家重点实验室&#xff08;以下简称“国重实验室”&#xff09;、中国传媒大学数字人研究院编制&#xff0c;中国网络视听协会、人民日报智慧…

目标检测——铁路工人数据集

一、重要性及意义 提升铁路工作安全性。铁路工人常常需要在铁路轨道附近进行各种作业&#xff0c;如维修、检查等&#xff0c;这些工作往往伴随着较高的安全风险。一个准确的铁路工人检测系统能够在第一时间识别并警示工人或操作员的接近&#xff0c;从而避免潜在的碰撞事故&a…

能源照明运作机制与智能调控技术实现途径

随着城市化进程的加速&#xff0c;智慧城市已成为现代城市发展的重要方向。能源照明作为城市基础设施的重要组成部分&#xff0c;其运作机制与智能调控技术的实现对于提高城市能源利用效率、促进可持续发展具有重要意义。 能源照明是一个涵盖广泛、错综复杂的领域&#xff0c;它…

C++ Primer 总结索引 | 第十二章:动态内存

1、到目前为止&#xff0c;我们编写的程序中 所使用的对象 都有着严格定义的生存期。全局对象 在程序启动时分配&#xff0c;在程序结束时 销毁。对于 局部自动对象&#xff0c;当我们进入 其定义所在的程序块时被创建&#xff0c;在 离开块时销毁。局部static对象 在第一次使用…

文心一言 VS 讯飞星火 VS chatgpt (227)-- 算法导论16.3 9题

九、证明&#xff1a;对于一个由随机生成的8位字符组成的文件&#xff0c;没有任何压缩方法可以望将其压缩、哪怕只是压缩一位。(提示&#xff1a;比较可能的文件数量和可能的编码文件数量。) 文心一言&#xff1a; 确实&#xff0c;对于一个由随机生成的8位字符组成的文件&a…

蓝桥杯相关算法学习(Python)

一、排序 排序算法是指将一组数据按照某种规则重新排列&#xff0c;使得数据呈现出递增或递减的顺序。常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等。 1.冒泡排序 解释&#xff1a; 冒泡排序通过不断交换相邻两个元素的位置&#xff0c;使…

如何辨别蜂蜜的好坏?具体看哪些指标?

蜂蜜的好坏是通过检测指标反应出来的。 衡量蜂蜜质量的指标很多&#xff0c;主要分五类。 第一类是蜂蜜的基础性检测。如&#xff1a;感官、水分、灰分、酸度、蜂蜜的真实性&#xff08;SM-X&#xff09;等&#xff1b; 第二类是营养成分检测。如&#xff1a;果糖与葡萄糖含…

GC Roots

JVM垃圾回收的时候如何确定垃圾&#xff1f; 在说GC Roots之前&#xff0c;我们先看看JVM是如何确定垃圾的&#xff0c;从而进行回收 什么是垃圾 简单来说就是内存中已经不再被使用的空间就是垃圾 如何判断一个对象是否可以被回收 引用计数法 Java中&#xff0c;引用和对象…

node res.end返回json格式数据

使用 Node.js 内置 http 模块的createServer()方法创建一个新的HTTP服务器并返回json数据&#xff0c;代码如下&#xff1a; const http require(http);const hostname 127.0.0.1; const port 3000;const data [{ name: 测试1号, index: 0 },{ name: 测试2号, index: 1 },…

【R】Error in library(foreach) : 不存在叫‘foreach’这个名字的程辑包

Error in library(foreach) : 不存在叫‘foreach’这个名字的程辑包 此外: Warning message: package ‘parallel’ is a base package, and should not be updated 解决方法 缺少名为 foreach 的包&#xff0c;使用install.packages("foreach")将名为foreach 的包…

Flask Python:模糊查询filter和filter_by,数据库多条件查询

数据库&#xff08;sqlalchemy&#xff09;多条件查询 前言一、filter、filter_by实现过滤查询1、filter_by()基础查询并且查询&#xff08;多条件查询&#xff09; 2、filter()like&#xff1a;模糊查询and&#xff1a;并且查询or&#xff1a;或者查询 二、all(),first(),get(…