【STM32篇】驱动MXL90614红外测温模块
本次实验使用的测温模块型号GY-906-DCC模块,测距为10cm左右。
一、简介
MLX90614 是一款红外非接触温度计。TO-39 金属封装里同时集成了红外感应热电堆探测器芯片和信处理专用集成芯片。
由于集成了低噪声放大器、17 位模数转换器和强大的数字信号处理单元,使得高精度和高分辨度的温计得以实现。温度计具备出厂校准化,有数字 PWM 和 SMBus(系统管理总线)输出模式。
作为标准,配置为 10 位的 PWM 输出格式用于连续传送温度范围为-20…120 ˚C 的物体温度,其分辨率为 0.14 ˚C。POR 默认模式是 SMBus 输出格式。
图1.典型应用电路图
(一)引脚定义和描述
图2.顶视图
引脚名 |
功能 |
VSS |
地。 金属罐也连接到该引脚上。 |
SCL/Vz |
两线通信协议的串行时钟信号。该引脚上的 5.7V 齐纳二极管用于连接外部双极晶体管 以实现对器件高电源电压 8 …16V 的应用。 |
PWM/SDA |
数字信号输入 / 输出。正常模式下该引脚以脉宽调制方式输出测量的物体温度。 SMBus 兼容模式下自动配置为开漏 NMOS。 |
VDD |
外部电源电压。 |
(二)MLX90614 存储器
EEPROM
EEPROM 里只有限定数目的地址是允许客户改写的。整个 EEPROM 可通过 SMBus 接口读和写。
图3.EEPROM
MLX90614 的 EEPROM 有 32 个 16 位存储单元,其中存储单元 Tomax,Tomin,Ta 分别是用户物体温度上下限和环境温度范围,PWMCTRL 是 PWM 配置寄存器。
MLX90614 可通过 PWM 或是 SMBus 兼容接口读取,由 EEPROM 配置选择 PWM 输出模式。 (出厂默认为SMBus) PWM 输出有两种可编程的格式,单个和双重数据传送,提供单线读取两个温度的功能。(双重可以选择物体或是物体和环境温度) PWM 周期通过片上振荡器驱动并可编程。
RAM
RAM 中不能写入数据,只能进行读取,并且只有有限数目是客户感兴趣的。
图4.RAM
MLX90614 的RAM有 32 个 17 位存储单元,其中TA,TOBJ1,TOBJ2是环境温度和物体温度,在SMBus方式下,可以从这几个存储单元读出环境和被测物体的温度。
命令 Command
图5.命令码
xxxxx 代表要读取/写入的内存地址的 低5 位。
(三)两线协议
SMBus 接口为两线协议,允许主控器件 (MD) 和一个或是一个以上的从动器件 (SD) 通信。系统在给定的时刻只有一个主控器件。MLX90614 只作为从动器件使用。
使用模拟IIC实现SMBus通信。
图6.IIC通信协议
起始信号和停止信号
图7.起始信号和停止信号
起始信号:在 SCL 线是高电平时 SDA 线从高电平向低电平切换。
停止信号:SCL 是高电平时 SDA 线由低电平向高电平切换。
起始和停止条件一般由主机产生 总线在起始条件后被认为处于忙的状态 在停止条件的某段时间后总线被认为再次处于空闲状态。如果产生重复起始 Sr 条件而不产生停止条件 总线会一直处于忙的状态。
//起始信号
void MLX906_START_Sign(void)
{MLX906_SDA_OUT();//输出模式MLX906_SDA_H;MLX906_SCL_H;Delay_us(2);MLX906_SDA_L;Delay_us(2);MLX906_SCL_L;//钳住总线,准备开始数据传输Delay_us(1);
}
//停止信号
void MLX906_STOP_Sign(void)
{MLX906_SDA_OUT();//输出模式MLX906_SCL_L;MLX906_SDA_L;Delay_us(2);MLX906_SCL_H;MLX906_SDA_H;Delay_us(1);
}
应答信号和非应答信号
图8.应答信号
SCL在高电平期间SDA始终处于低电平,需要在传输完毕一个字节后发送。
//主机应答(ACK信号)
void MLX906_Ack(void)
{ MLX906_SDA_OUT();//输出模式MLX906_SDA_L;MLX906_SCL_L;Delay_us(2);MLX906_SCL_H;Delay_us(2);MLX906_SCL_L;
}
图9.非应答信号
SCL在高电平期间SDA始终处于高电平,需要在传输完毕一个字节后发送。
//不产生ACK应答信号
void MLX906_Nack(void)
{MLX906_SDA_OUT();//输出模式MLX906_SCL_L;MLX906_SDA_H;Delay_us(2);MLX906_SCL_H;Delay_us(2);MLX906_SCL_L;Delay_us(2);
}
响应
图10.IIC总线的响应
数据传输必须带响应。相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间,发送器释放SDA线(高)。
在响应的时钟脉冲期间 ,接收器必须将SDA 线拉低 ,使它在这个时钟脉冲的高电平期间保持稳定的低电平。
uint8_t MLX906_Wait_Ack(void)
{MLX906_SDA_IN();//输入模式uint8_t utime=0;MLX906_SDA_H;Delay_us(1);MLX906_SCL_H;Delay_us(1);while(MLX906_READ_SDA()){utime++;if(utime>=255){MLX906_STOP_Sign();return 1;//非应答信号}}MLX906_SCL_L;return 0;//应答信号
}
数据传输
在数据传输过程中,数据线SDA需在时钟线SCL为高电平时保持稳定,在低电平期间可修改或读取数据线电平状态。
发送到 SDA 线上的每个字节必须为8位 ,每次传输可以发送的字节数量不受限制 ,每个字节后必须跟一个响应位。
发送数据:
//发送一个字节数据
uint8_t MLX906_SendByte(uint8_t byte1)
{uint8_t i,byte;byte=byte1;MLX906_SDA_OUT();//输出模式for(i=0;i<8;i++)//高位先发{if(byte&0x80){MLX906_SDA_H;}else{MLX906_SDA_L;}MLX906_SCL_H;Delay_us(2);MLX906_SCL_L;Delay_us(2);byte<<=1;}MLX906_SDA_H;//释放总线return MLX906_Wait_Ack();//等待响应
}
读数据:
//读取一个字节
uint8_t MLX906_ReadByte(void)
{uint8_t byte=0;uint8_t i;MLX906_SDA_IN();//输入模式for(i=0;i<8;i++){MLX906_SCL_H;//SCL高电平时读取数据if(MLX906_READ_SDA()){byte|= 1<<(7-i);}MLX906_SCL_L;//下降沿时从机修改数据Delay_us(2);}MLX906_Nack();return byte;
}
二、总线协议
图11.SMBus 数据包组成
在 SD 接收到每个 8 位数据后,会回复 ACK/NACK 信息。当 MD 初始化通信,将首先发送受控地址,只有能识别该地址的 SD 会确认,其它的会保持沉默。如果 SD 未确认其中的任意字节,MD 应停止通信并重新发送信息。NACK 也会在 PEC 接收后出现,这意味着在接收的信息有错误并且 MD 应重新发送信息。
PEC 的计算结果是基于 除 START,REPEATED START,STOP,ACK, 和 NACK 位外的所有位。 PEC 是 CRC-8 的多项式 aX8+X2+X1+1。每个字节的最高有效位首先传送。
(一)读数据
图12.SMBus读数据格式
(二)软件流程
多个MLX90614可以用于一个系统中,通过地址不同区分器件,器件默认的地址为5AH,因此在多 MLX90614 系统中,需要给每个 MLX90614 分配一个不同的地址,在只有一个MLX90614 的系统中,MLX90614 识别地址 00h,即在单个 MLX90614 系统中,可以使用该地址访问它。
图13.读数据流程图
从MLX90614 种读出的数据是 16 位的,由高 8 位(DataH)和低 8 位(DataL)两部分组成,其中RAM地址 07H单元存储的是TOBJ1数据,数据范围从 0x27AD到 0x7FFF,表示的温度范围是-70.01℃到+382.19℃。
//读内存
uint16_t MLX906_ReadMemory(void)
{uint8_t Pec,PecReg,ErrorCounter;uint8_t TempL=0;uint8_t TempH=0;uint8_t arr[6];ErrorCounter=0;do{ErrorCounter++;if(ErrorCounter==10){return 0;} MLX906_START_Sign();//起始信号if(MLX906_SendByte(0x00))//发送MLX90614地址continue;if(MLX906_SendByte(0x07))//发送读MLX90614 RAM地址continue;MLX906_START_Sign();//重新启动if(MLX906_SendByte(0x01))//发送数据采集命令continue;TempL=MLX906_ReadByte();//读取地位数据TempH=MLX906_ReadByte();//读取高位数据Pec=MLX906_ReadByte();//读取校验位MLX906_STOP_Sign();//停止信号arr[5]= 0x00;arr[4]= 0x07;arr[3]= 0x01;arr[2]= TempL;arr[1]= TempH;arr[0]= 0;PecReg=CRC_Calculation(arr);//计算CRC校验}while(PecReg!=Pec);return (uint16_t)((TempH<<8)|TempL);
}
(三)环境温度和物体温度的计算
环境温度Ta
物体温度To
//读温度
float MLX906_Read_Temp(void)
{return (float )MLX906_ReadMemory()*0.02-273.15;
}
三、实验结果
手腕温度测量(未校准),可能有所误差。
图14.手腕温度测量
mian函数中轮询打印。
图15.UART读取温度数据
四、附件
mlx906.h
#ifndef _MLX906_H_
#define _MLX906_H_#include "stm32f10x.h"
#include "systick.h"/*
引脚连接:SCL 时钟线 - PB10SDA 数据线 - PB11*/
#define MLX906_SCL_H GPIO_WriteBit(GPIOB,GPIO_Pin_10,Bit_SET)
#define MLX906_SCL_L GPIO_WriteBit(GPIOB,GPIO_Pin_10,Bit_RESET)
#define MLX906_SDA_H GPIO_WriteBit(GPIOB,GPIO_Pin_11,Bit_SET)
#define MLX906_SDA_L GPIO_WriteBit(GPIOB,GPIO_Pin_11,Bit_RESET)
#define MLX906_READ_SDA() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)//配置SDA数据线的输入输出模式
#define MLX906_SDA_OUT() ?????//输出模式 自己配置哦
#define MLX906_SDA_IN() ?????//输入模式//此处为笔者小设计中才用到的,不用管
#define MLX906_STATE_READ 1
#define MLX906_STATE_UNREAD 0
#define ANOMALY_TEMP 37 //体温异常extern float MLX906_Temp;
extern uint8_t MLX906_Temp_State;void MLX906_Init(void);
float MLX906_Read_Temp(void);#endif
mlx906.c
#include "mlx906.h"//MLX初始化函数
void MLX906_Init(void)
{//初始化引脚GPIO_InitTypeDef mlx906_gpio_init;mlx906_gpio_init.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;mlx906_gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出mlx906_gpio_init.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&mlx906_gpio_init);MLX906_SCL_H;//拉高引脚电平MLX906_SDA_H;
}/* IIC 时序 *///起始信号
void MLX906_START_Sign(void)
{MLX906_SDA_OUT();//输出模式MLX906_SDA_H;MLX906_SCL_H;Delay_us(2);MLX906_SDA_L;Delay_us(2);MLX906_SCL_L;//钳住总线,准备开始数据传输Delay_us(1);
}
//停止信号
void MLX906_STOP_Sign(void)
{MLX906_SDA_OUT();//输出模式MLX906_SCL_L;MLX906_SDA_L;Delay_us(2);MLX906_SCL_H;MLX906_SDA_H;Delay_us(1);
}
uint8_t MLX906_Wait_Ack(void)
{MLX906_SDA_IN();//输入模式uint8_t utime=0;MLX906_SDA_H;Delay_us(1);MLX906_SCL_H;Delay_us(1);while(MLX906_READ_SDA()){utime++;if(utime>=255){MLX906_STOP_Sign();return 1;//非应答信号}}MLX906_SCL_L;return 0;//应答信号
}
//主机应答(ACK信号)
void MLX906_Ack(void)
{MLX906_SDA_OUT();//输出模式MLX906_SDA_L;MLX906_SCL_L;Delay_us(2);MLX906_SCL_H;Delay_us(2);MLX906_SCL_L;
}
//不产生ACK应答信号
void MLX906_Nack(void)
{MLX906_SDA_OUT();//输出模式MLX906_SCL_L;MLX906_SDA_H;Delay_us(2);MLX906_SCL_H;Delay_us(2);MLX906_SCL_L;Delay_us(2);
}//读取一个字节
uint8_t MLX906_ReadByte(void)
{uint8_t byte=0;uint8_t i;MLX906_SDA_IN();//输入模式for(i=0;i<8;i++){MLX906_SCL_H;//SCL高电平时读取数据if(MLX906_READ_SDA()){byte|= 1<<(7-i);}MLX906_SCL_L;//下降沿时从机修改数据Delay_us(2);}MLX906_Nack();return byte;
}
//发送一个字节数据
uint8_t MLX906_SendByte(uint8_t byte1)
{uint8_t i,byte;byte=byte1;MLX906_SDA_OUT();//输出模式for(i=0;i<8;i++)//高位先发{if(byte&0x80){MLX906_SDA_H;}else{MLX906_SDA_L;}MLX906_SCL_H;Delay_us(2);MLX906_SCL_L;Delay_us(2);byte<<=1;}MLX906_SDA_H;//释放总线return MLX906_Wait_Ack();//等待响应
}//crc校验
uint8_t CRC_Calculation(uint8_t pec[])
{uint8_t crc[6];//存放多项式uint8_t BitPosition = 47;uint8_t shift;uint8_t i,j,temp;do{crc[5]=0;crc[4]=0;crc[3]=0;crc[2]=0;crc[1]=0x01;crc[0]=0x07;BitPosition = 47;shift = 0;i=5;j=0;while((pec[i]&(0x80>>j))==0 && i>0){BitPosition--;if(j<7){j++;}else{j= 0x00;i--;}}shift= BitPosition-8;while(shift){for(i=5;i<0xFF;i--){if((crc[i-1]&0x80)&&(i>0)){temp=1;}else{temp=0;}crc[i]<<=1;crc[i]+=temp;}shift--;}for(i=0;i<=5;i++){pec[i]^=crc[i];}}while(BitPosition>8);return pec[0];
}
//读内存
uint16_t MLX906_ReadMemory(void)
{uint8_t Pec,PecReg,ErrorCounter;uint8_t TempL=0;uint8_t TempH=0;uint8_t arr[6];ErrorCounter=0;do{ErrorCounter++;if(ErrorCounter==10){return 0;} MLX906_START_Sign();//起始信号if(MLX906_SendByte(0x00))//发送MLX90614地址continue;if(MLX906_SendByte(0x07))//发送读MLX90614 RAM地址continue;MLX906_START_Sign();//重新启动if(MLX906_SendByte(0x01))//发送数据采集命令continue;TempL=MLX906_ReadByte();//读取地位数据TempH=MLX906_ReadByte();//读取高位数据Pec=MLX906_ReadByte();//读取校验位MLX906_STOP_Sign();//停止信号arr[5]= 0x00;arr[4]= 0x07;arr[3]= 0x01;arr[2]= TempL;arr[1]= TempH;arr[0]= 0;PecReg=CRC_Calculation(arr);//计算CRC校验}while(PecReg!=Pec);return (uint16_t)((TempH<<8)|TempL);
}
//读温度
float MLX906_Read_Temp(void)
{return (float )MLX906_ReadMemory()*0.02-273.15;
}
注:GPIO时钟已在main.c文件中做了相关配置。
SDA数据线的输入输出模式配置 由 读者自行配置。
望有助于各位理解,如有侵权,请联系删除。
2023/1/7
【STM32篇】驱动MXL90614红外测温模块相关推荐
- STM32驱动MLX90614红外测温模块
简介:STM32F103C8T6驱动MLX90614红外测温模块源码介绍. 开发平台:KEIL ARM MCU型号:STM32F103C8T6 传感器型号:MLX90614 特别提示:驱动内可能使用了 ...
- STM32H7驱动GY906红外测温传感器
STM32H7通过iic驱动GY906红外测温模块 ,大部分代码来自网上 1.将iic.h和iic.c文件添加到自己项目中 2.初始化GY906 SMBus_Init(); //初始化GY906 3. ...
- STM32系列(HAL库)——F103C8T6 通过GY906/MLX90614红外测温模块实现温度测量
1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件准备 (1)GY-906-BCC红外测温模块 (2)F1的板子,本例使用经典F103C8T6 (3 ...
- 基于stm32人脸识别和红外测温
目录 一.项目功能 二.原理图 三.实物视频 四.实物图片 五.程序 资料下载地址:基于STM32人脸识别和红外测温 一.项目功能 本系统由stm32f103c8t6单片机最小系统电路+k210人脸识 ...
- MLX90614红外测温模块使用
一.MLX90614介绍(官方介绍,很官方) MLX90614 是一款红外非接触温度计.TO-39 金属封装里同 时集成了红外感应热电堆探测器芯片和信号处理专用集成芯 片. 由于集成了低噪声放大器.1 ...
- 燃太TN901红外测温模块LCD1602显示
山远的博客 学以致用 首页 旧版 首页 标签 留言本 单片机 文学 趣闻 美图 C#编程 燃太TN901红外测温模块LCD1602显示 燃太TN901红外测温模块LCD1602显示,可设置高温低温报警 ...
- ESP32设备驱动-MLX90614红外测温传感器驱动
MLX90614红外测温传感器驱动 1.MLX90614介绍 MLX90614 是一款用于非接触式温度测量的红外温度计.IR 敏感型热电堆检测器芯片和信号调节 ASIC 都集成在同一 TO-39 罐封 ...
- STM32+MLX90614红外测温
红外测温 文章目录 红外测温 前言 一.传感器 二.代码 1.MLX90614.C 2.MLX90614.h 总结 前言 手上有一个红外测温模块,拿出来玩一玩 一.传感器 一共有四个引脚,看到SCL和 ...
- 红外测温枪,超进化 -- 智能温度传感器 基于 arduino 的智能测温模块
红外测温枪,超进化!--智能温度传感器!基于 arduino 的智能测温模块. 前言 硬件选择 代码讲解 通过 SDDC 协议接入 Spirit 1 部分 配置设备信息 数据获取与发送流程 融合!特殊 ...
最新文章
- 认识一下Kotlin语言,Android平台的Swift
- Facebook如何运用机器学习进行亿级用户数据处理
- 某书2018面试题之最长对称子串
- Ksenia and Pan Scales(思维题)
- 迷你世界显示未连接服务器成功,迷你世界登录未成功是什么意思 | 手游网游页游攻略大全...
- 怎样在IIS下配置PHP
- oracle混音插件教程,Waves插件个人经验谈
- h2o java,H2O AutoML入门开发简介
- 计算机辅助教学课件中的辅导型模式是以,【2017年整理】1、下面属于计算机辅助教学简称的是 ( ).doc...
- 科大讯飞指定录音文件转文字(异步)
- 程序物语(五):经营自己的程序生涯
- 凭什么都是Java开发三年,而他能进大厂薪资是“我”2倍?
- discuz网站没备案无执照接入支付宝充值功能
- python如何判断列表是否为空_python简单判断序列是否为空的方法
- error怎么开机 fan_笔记本开机显示fan error怎么解决?
- 微信小程序-获取设备宽高
- vue集成activiti6.0 详细教程
- iphone界面元素的大小
- 最全AI学习路线+资源,推荐收藏!
- 【连载】《linux入门很简单》电子版——作者:刘金鹏(第一章初来乍到——启动)...