MLX90615 是用于非接触温度测量的红外温度计

电压使用3.3V

-40 到 85 ˚C 传感器温度范围
 -40 到 115 ˚C 物体温度范围

 有两种输出模式: SMBus 模式  和  PWM 模式

这里我们使用的是 SMBus 模式,故PWM模式就不介绍了。

RAM地址表

上图中我们要注意是的Ta和To的地址,Ta是环境温度(就是他封装、外壳的温度)地址是0X06,To是被测量物体温度,地址是0X07。

以下是示例时序图的相关术语图:

 读取与写入的操作顺序

 读取RAM的被测物体温度例子

1、先发送IIC起始信号(对应图中S)

2、发送IIC写命令( 写命令即 将器件地址(0X5B)左移一位空出最后一位再按位或上0或者1,最后一位=0为写命令(对应图中W),=1为读命令,而0x5B左移之后就是0xB6,0xb6|0 = 0xb6)

3、等待从机应答(对应图中A)(在SCL为高电平的状态下,SDA被从机拉为低电平,即为应答;为高电平为非应答)

4、从机应答后发送寄存器地址这里的0X27代表的是从RAM中读取物体温度,RAM地址为2xH,其中x为未知;物体温度数据地址为07H,将两者相或 0x20|0x07 = 0x27)

2xH地址来源:

 07H地址来源见之前的RAM地址表

5、等待从机应答

6、发送IIC读命令0x5B<<1 | 1 = 0xb6 | 1 = 0xb7 )

7、等待从机应答

8、读取物体温度的低8位数据

9、主机发送应答

10、读取物体温度的高8位数据

11、主机发送应答

12、读取校验码

13、主机发送应答

14、IIC停止信号

上代码:

IIC.c

#include "iic.h"

//IIC起始信号
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停止信号
void IIC_Stop(void)
{
	SDA_OUT();
	SCL(0);
	SDA(0);
	
	SCL(1);
	delay_us(5);
	SDA(1);
	delay_us(5);
	
}

//主机发送应答
//0应答
//1非应答
char 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);
	return 0;
}
//等待从机应答
unsigned char IIC_Whit_Ack(void)
{
	
	char ack = 0;
	unsigned char ack_flag = 10;
//	SCL(0);
//	SDA(1);
	SDA_IN();
	delay_us(5);
	SCL(1);
	delay_us(5);
	while( (GETSDA()==1) && ( ack_flag ) )
	{
		ack_flag--;
		delay_us(5);
	}
	
	if( ack_flag <= 0 )
	{
		IIC_Stop();
		return 1;
	}
	else
	{
		SCL(0);
		SDA_OUT();
	}
	return ack;
}
//写一个字节
void IIC_Write(unsigned char 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;
	}	
}

//读1个字节
unsigned char IIC_Read(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( GETSDA() )
		{	
			receive|=1;   
		}
	  delay_us(5); 
   }					 
	SCL(0); 
  return receive;
}

//CRC校验
unsigned char crc8(const unsigned char *data, int len)
{
	const unsigned char POLYNOMIAL = 0x31;
	unsigned char crc = 0xFF;
	int j, i;

	for (j=0; j<len; j++)
	{                  
		crc ^= *data++;
		for ( i = 0; i <8; i++ )
		{
			crc = ( crc & 0x80 ) ? (crc << 1) ^ POLYNOMIAL : (crc << 1); 
		}                                                            
	}
	return crc;
}


IIC.h

#ifndef _IIC_H_
#define _IIC_H_

//使用的是  STM32F405RGT6

#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"

//根据寄存器进行修改
#define SDA_IN()    {GPIOB->MODER &= ~(0X03<<14);} //设置SDA为输入模式
#define SDA_OUT() 	{GPIOB->MODER |=  (0X01<<14);} //设置SDA为输出模式

//置位SCL与SDA电平
#define SCL(BIT)  GPIO_WriteBit( GPIOB, GPIO_Pin_6, BIT)
#define SDA(BIT)  GPIO_WriteBit( GPIOB, GPIO_Pin_7, BIT)

//读取SDA的电平
#define GETSDA()  GPIO_ReadInputDataBit( GPIOB, GPIO_Pin_7)

///////////////////		IIC		///////////////////
void 					IIC_Start(void);
void 					IIC_Stop(void);
char 					IIC_Send_Ack(unsigned char ack);
unsigned char IIC_Whit_Ack(void);
void					IIC_Write(unsigned char dat);
unsigned char IIC_Read(void);
unsigned char crc8(const unsigned char *data, int len);


#endif

mlx90615.c

#include "mlx90615.h"

/************************************************************
 * 函数名称:MLX90615_IIC_Init
 * 函数说明:MLX90615引脚IIC初始化
 * 型    参:无
 * 返 回 值:无
 * 备    注://我的IIC引脚是 PB6-SCL  PB7-SDA
*************************************************************/
void MLX90615_IIC_Init(void)
{
	GPIO_InitTypeDef GPIOINIT={0};
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
	
	GPIOINIT.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIOINIT.GPIO_OType = GPIO_OType_OD;
	GPIOINIT.GPIO_PuPd = GPIO_PuPd_UP;
	GPIOINIT.GPIO_Speed = GPIO_Speed_25MHz;
	GPIOINIT.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(GPIOB,&GPIOINIT);
	SCL(1);      //拉高	
	SDA(1);		 //拉高
		
}
/************************************************************
 * 函数名称:I2C_CRC
 * 函数说明:CRC校验
 * 型    参:sp = 要校验的数据,len = 校验长度
 * 返 回 值:校验值
 * 备    注:无
*************************************************************/
unsigned char I2C_CRC(const unsigned char *sp, int len)       //I2C:数据校验函数
{
		const unsigned char PYM = 0x31;        //const:关键字:只读
		unsigned char crc = 0xff;       //8 位都是 1
		int i = 0, j = 0;
		
		for(i=0; i<len; i++)   //一共有16位:高8位,,低8位  len: 一般是 2
		{
				crc ^= *sp++;        //sp 的地址自增
				for(j=0; j<8; j++)
				{
					//真:执行:(crc << 1) ^ PYM ,,假:执行:(crc << 1)
				   crc = (crc & 0x80) ? (crc << 1) ^ PYM  : (crc << 1);  
				}
		}
		return crc;	
}
/************************************************************
 * 函数名称:MXL90615_Read
 * 函数说明:读取MXL90615的温度
 * 型    参:SlaveAddr = 器件地址  RegAddr = 要操作的寄存器地址
 * 返 回 值:温度值
 * 备    注:MLX90615的从机地址为 0X5B,读取被测物体温度地址0X27,读取环境温度地址0X26
*************************************************************/
float MXL90615_Read(unsigned char SlaveAddr, unsigned char RegAddr)
{
	int i = 0;
	unsigned char buff[3]={0};	//保存温度高低位与校验码
	unsigned char arr[6]={0};   //校验数据使用
	short temp = 0;				//高低位整合数据保存
	float T=0.0;			    //换算出的实际温度
	
	again:
	IIC_STOP();					
	
	IIC_START();
	IIC_WRITE((SlaveAddr<<1)|0);        //写命令
	if( IIC_WHIT_ACK() )				//等待响应
	{
			printf("ERROR CODE 1\r\n");
		goto again;
	}
	IIC_WRITE(RegAddr);                 //写入要操作的寄存器地址
	if( IIC_WHIT_ACK() ) 
	{
			printf("ERROR CODE 2\r\n");
		goto again;
	}

	IIC_START();	                    //重新开始IIC
	IIC_WRITE((SlaveAddr<<1)|1);	    //读命令
	if( IIC_WHIT_ACK() ) 
	{
		printf("ERROR CODE 3\r\n");
		goto again;
	}
	
	buff[0] = IIC_READ();			//保存温度数据的低8位
	IIC_SEND_ACK(ACK);				//主机发送应答
	buff[1] = IIC_READ();			//保存温度数据的高8位
	IIC_SEND_ACK(ACK);				//主机发送应答
	buff[2] = IIC_READ();			//保存校验码
	IIC_SEND_ACK(ACK);				//主机发送应答
	
	//停止时序
	IIC_Stop();								
	          
	
//使用校验
#if CRC_VERIFY_ENABLE
	
	arr[4]=SlaveAddr;		      //写命令
	arr[3]=RegAddr;			      //寄存器地址
	arr[2]=SlaveAddr+1;			  //读命令 
	arr[1]=buff[0];		          //低8位
	arr[0]=buff[1];	              //高8位

	//校验
	if( crc8(arr,2) != buff[2] )//校验正确
	{
		temp = (short)(buff[1]<<8) | buff[0];	//整合高低位
		T = (temp*0.02)-273.15 ;				//带入公式换算出实际温度
	
//		printf("MLX90615=%.2f\r\n",T);
	}
	else
	{
		printf("ERROR CODE 4\r\n");
		goto again;
	}
#endif   
	
//不使用校验
#if !CRC_VERIFY_ENABLE
		temp = (short)(buff[1]<<8) | buff[0];
		T = (temp*0.02)-273.15 ;
		printf("MLX90615=%.2f\r\n",T);
#endif
	
	return T;
}                                                                                  

mlx90615.h

#ifndef _MLX90615_H_
#define _MLX90615_H_

#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "iic.h"

//是否使用CRC校验  1使用  0不使用
//不使用也没有事只是有时候会出现数据不对的情况
//
#define CRC_VERIFY_ENABLE   1		

	
#define ACK		0			//应答
#define NACK	1			//非应答


//  移植注意:
//	将自己的IIC时序函数对应替换即可  
//		我自己的函数是:
//		void IIC_Write(unsigned char com);		//传入要写入的地址
//		unsigned char IIC_Read(void);			//返回IIC的数据
//		unsigned char IIC_Whit_Ack(void);		//返回从机是否有应答 ACK or NACK
//		void IIC_Send_Ack(unsigned char ack);	//主机发送应答信号 ACK or NACK
//
#define IIC_START  		IIC_Start		//IIC开始信号
#define IIC_STOP  		IIC_Stop		//IIC结束信号
#define IIC_WRITE  		IIC_Write		//IIC写
#define IIC_READ  		IIC_Read		//IIC读
#define IIC_WHIT_ACK  IIC_Whit_Ack		//IIC等待从机应答
#define IIC_SEND_ACK  IIC_Send_Ack		//IIC主机发送应答


void MLX90615_IIC_Init(void);//IIC引脚初始化
float MXL90615_Read(unsigned char SlaveAddr, unsigned char RegAddr);//读取温度



#endif

main.c

#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "iic.h"
#include "mlx90615.h"

/***************************************

编 译 版 本:MDK-keil5.37--CC5 
编 辑 时 间:2022-12-12
编 辑 人 员:老怪.

****************************************/

int main(void)
{
	float Temp = 0.0;

	//中断分组 2组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//滴答定时器初始化
	delay_init(168);

	//串口1配置
	USART1_Init();	        
	
	//MLX90615的IIC引脚初始化
	MLX90615_IIC_Init();
	
	while(1)               
	{   	 		
		//读取RAM中的被测物体温度数据
		Temp = MXL90615_Read(0x5b,0x27);
		printf("Temp = %.2f\r\n", Temp);
		delay_ms(500);
	}       
		
}

效果:

当我的手放在传感器上方时,温度为30摄氏度左右

 

工程链接:

链接:https://pan.baidu.com/s/1a2Ox9xRNFDR_o1e6ldiMww?pwd=1234
提取码:1234

 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐