一、MLX90615使用说明

         MLX90615是一款红外温度传感器,默认使用SMBus模式,如果需要使用PWM模式则需要修改EEPROM地址中Config Register中的值才能将其配置为PWM模式。笔者因为老师给的电路板使用的模式为PWM,因此需要配置EEPROM寄存器的值,将其配置为PWM模式进行温度的读取。找了很多相关的资料,但是基本上没有使用PWM捕获获取温度的资料。笔者在使用I2C写入数据修改的EEPROM寄存器值配置工作模式时遇到了很多的问题,花了一天多的时间才得以解决。因此发一贴来分享遇见的这些问题。EEPROM Config Register的地址为0X02,每位具体代表的值如下图所示:

MLX90615内部含有两块内存一个是EEPRM一个是RAM。

按上图所示0x1?选择的是EEPROM,0x2?选中的RAM,0x27是RAM中温度存放的地址,0x12是EEPROM Config Register的地址,芯片的器件地址为0x00(或者是0x5B)。具体的IIC通信过程如下图所示:

知晓了上诉基本原理之后就需要编程实现上诉功能,来获取传感器采集到的温度。值得注意的是,MLX90615的IIC通信都要需要进行校验,即最后的PEC,采用的ocr-8校验,如果校验不通过则代表写入或者读取的数据有问题。

二、STM32与MLX90615之间的IIC通信

本文采用的MCU为STM32F103VET6,采用模拟IIC的方式进行MCU和温度传感器MLX90615之间通信。按照上述所示的IIC通信过程编写响应程序,具体编程如下图所示:

2.1 用到的引脚相关宏定义,便于主函数的编写

#ifndef __MLX90615_H__
#define __MLX90615_H__#include "stm32f10x.h"
#include "bsp_SysTick.h"#define u8        uint8_t
#define u16     uint16_t
#define u32     uint32_t#define ACK     0
#define NACK    1//MLX90615 constants
#define SA                     0x00 // Slave address
#define DEFAULT_SA             0x5B // Default Slave address
#define RAM_Access             0x20 // RAM access command
#define EEPROM_Access          0x10 // EEPROM access command#define mlx_I2C_PORT            GPIOB //使用到的CPIO口
#define mlx_SCL_PIN             GPIO_Pin_10
#define mlx_SDA_PIN             GPIO_Pin_11#define mlx_SCL_LOW()            mlx_I2C_PORT->BRR = mlx_SCL_PIN         // define  SCL
#define mlx_SCL_HIGH()          mlx_I2C_PORT->BSRR =    mlx_SCL_PIN     // define  SCL#define mlx_SDA_LOW()             mlx_I2C_PORT->BRR = mlx_SDA_PIN         // define   SDA
#define mlx_SDA_HIGH()          mlx_I2C_PORT->BSRR =    mlx_SDA_PIN     // define   SDA#define mlx_SCL_State()          ((mlx_I2C_PORT->IDR & mlx_SCL_PIN) != 0) //获取SCL的值
#define mlx_SDA_State()         ((mlx_I2C_PORT->IDR & mlx_SDA_PIN) != 0) //获取SDA的值

2.2 GPIO的初始化

//   函数名称:    mlx_gpio_init()
//
//  函数功能:    初始化IO口
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:  配置CPIO位低速推挽输出模式
//==========================================================
void mlx_gpio_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);              //开启GPIOB时钟GPIO_InitStructure.GPIO_Pin =  mlx_SCL_PIN | mlx_SDA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(mlx_I2C_PORT, &GPIO_InitStructure);mlx_SCL_HIGH();mlx_SDA_HIGH();
}
//==========================================================
//  函数名称:    mlx_SDA_OUT()
//
//  函数功能:    IIC数据线输出模式
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:  最开始的GPIO初始化已经写过了但是检测应答信号的时候需要修改位浮空输入
//因此在后面的使用中需要SDA引脚再次初始化位输出模式 因此单独写一个输出配置函数
//==========================================================
void mlx_SDA_OUT(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);              //开启GPIOB时钟GPIO_InitStructure.GPIO_Pin =   mlx_SDA_PIN;GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;              //输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;              //低速GPIO_Init(mlx_I2C_PORT, &GPIO_InitStructure);
}//==========================================================
//  函数名称:    mlx_SDA_IN()
//
//  函数功能:    IIC数据线输入模式
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:  配置为输入检测应答信号
//==========================================================
void mlx_SDA_IN(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);          //开启GPIOB时钟GPIO_InitStructure.GPIO_Pin =  mlx_SDA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //输入模式GPIO_Init(mlx_I2C_PORT, &GPIO_InitStructure);
}

分别是SCL和SDA引脚进行初始化操作,后面两个初始化时因为SDA引脚需要检测应答信号,因此需要改变GPIO的工作模式,所以单独写了输入模式和输出模式的初始化程序。

2.3 开始位和停止位

//==========================================================
//  函数名称:    start_bit()
//
//  函数功能:    IIC  开始时序
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:
//==========================================================
void START_bit(void)
{   mlx_SDA_OUT();mlx_SDA_HIGH();Delay_us(5);mlx_SCL_HIGH();Delay_us(5);mlx_SDA_LOW();Delay_us(4);mlx_SCL_LOW();Delay_us(5);
}//==========================================================
//  函数名称:    stop_bit()
//
//  函数功能:    IIC  停止时序
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:
//==========================================================
void STOP_bit(void)
{mlx_SDA_OUT();mlx_SCL_LOW();Delay_us(5);mlx_SDA_LOW();Delay_us(5);mlx_SCL_HIGH();Delay_us(5);mlx_SDA_HIGH();
}

2.4 接收和发送函数

//==========================================================
//  函数名称:    send_bit()
//
//  函数功能:    IIC 写入数据时序
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:
//==========================================================
void send_bit(unsigned char bit_out)
{       mlx_SDA_OUT();if(bit_out) mlx_SDA_HIGH();     else         mlx_SDA_LOW();Delay_us(1);mlx_SCL_HIGH();Delay_us(5);mlx_SCL_LOW();Delay_us(5);return;
}//End of send_bit()//==========================================================
//  函数名称:    Receive_bit()
//
//  函数功能:    IIC 读取数据时序
//
//  入口参数:    时间
//
//  返回参数:    无
//
//  说明:
//==========================================================
unsigned char Receive_bit(void)
{unsigned char Ack_bit;mlx_SDA_IN();    __NOP();__NOP();__NOP();Delay_us(3);mlx_SCL_HIGH();Delay_us(1);if(mlx_SDA_State())Ack_bit=1;elseAck_bit=0;mlx_SCL_LOW();  Delay_us(1);    return  Ack_bit;
}//End of Receive_bit
//==========================================================
//  函数名称:    TX_byte()
//
//  函数功能:    IIC发送数据
//
//  入口参数:    Tx_buffer:数据
//
//  返回参数:    无
//
//  说明:
//==========================================================
unsigned char TX_byte(unsigned char Tx_buffer)
{unsigned char  Bit_counter;unsigned char   Ack_bit;unsigned char   bit_out;for(Bit_counter=8; Bit_counter; Bit_counter--){if(Tx_buffer&0x80) bit_out=1; // If the current bit of Tx_buffer is 1 set bit_outelse             bit_out=0; // else clear bit_outsend_bit(bit_out);  // Send the current bit on SDATx_buffer<<=1;         // Get next bit for checking}Ack_bit=Receive_bit();// Get acknowledgment bitreturn Ack_bit;
}// End of TX_bite()//==========================================================
//  函数名称:    RX_byte()
//
//  函数功能:    IIC 读取数据
//
//  入口参数:    ack_nack: unsigned char ack_nack (acknowledgment bit)
//                          0 - Master device sends ACK
//                          1 - Master device sends NACK
//
//  返回参数:    无
//
//  说明:
//==========================================================
unsigned char RX_byte(unsigned char ack_nack)
{unsigned char  RX_buffer=0;unsigned char  Bit_Counter;for(Bit_Counter=8; Bit_Counter; Bit_Counter--){if(Receive_bit())                       // Get a bit from the SDA line{RX_buffer <<= 1;                  // If the bit is HIGH save 1  in RX_bufferRX_buffer |=0x01;}else{RX_buffer <<= 1;                   // If the bit is LOW save 0 in RX_buffer RX_buffer &=0xfe; }}send_bit(ack_nack);                       // Sends acknowledgment bitreturn RX_buffer;
}

2.5 读取函数和发送函数

//==========================================================
//  函数名称:    MemRead()
//
//  函数功能:    从框架/EEPROM读取数据
//
//  入口参数:    SlaveAddress:读取地址
//                          command:命令
//
//  返回参数:    温度值
//
//  说明:
//==========================================================
unsigned int MemRead(unsigned char SlaveAddress,unsigned char command)
{unsigned int  data;                // Data storage (DataH:DataL)unsigned char Pec;             // PEC byte storageunsigned char DataL;         // Low data byte storageunsigned char DataH;            // High data byte storageunsigned char arr[6];          // Buffer for the sent bytesunsigned char PecReg;           // Calculated PEC byte storageunsigned char ErrorCounter;       // Defines the number of the attempts for communication with MLX90614ErrorCounter=0x00;                // Initialising of ErrorCounterdo{repeat:STOP_bit();                    //If slave send NACK stop comunication  --ErrorCounter;         //Pre-decrement ErrorCounterif(!ErrorCounter){  //ErrorCounter=0?printf("break 1\r\n");break;                        //Yes,go out from do-while{}}START_bit();               //Start conditionif(TX_byte(SlaveAddress)){ //Send SlaveAddressprintf("repeat 1\r\n");goto    repeat;         //Repeat comunication again}if(TX_byte(command)){       //Send command  printf("repeat 2\r\n");goto   repeat;         //Repeat comunication again}START_bit();                //Repeated Start conditionif(TX_byte(SlaveAddress+1)){ //Send SlaveAddress-------------------???printf("repeat 3\r\n");goto  repeat;         //Repeat comunication again}DataL=RX_byte(ACK);            //Read low data,master must send ACKDataH=RX_byte(ACK);        //Read high data,master must send ACKPec=RX_byte(NACK);            //Read PEC byte, master must send NACKSTOP_bit();                           //Stop conditionarr[5]=SlaveAddress;       //arr[4]=command;                  //arr[3]=SlaveAddress+1;      //Load array arr arr[2]=DataL;                     //arr[1]=DataH;                        //arr[0]=0;                                //PecReg=PEC_calculation(arr);//Calculate CRCprintf("PecReg:%d\n", PecReg);printf("Pec:%d\n", Pec);printf("DataL:%d\tDataH:%d\r\n",DataL,DataH);}while(PecReg != Pec);      //If received and calculated CRC are equal go out from do-while{}*((unsigned char *)(&data))=DataL;       // *((unsigned char *)(&data)+1)=DataH ;  //data=DataH:DataLreturn data;
}
void MemWrite(unsigned char SlaveAddress,unsigned char command, uint16_t data)
{//uint8_t Pec;             // PEC byte storageuint8_t i;uint8_t DataL;         // Low data byte storageuint8_t DataH;          // High data byte storageuint8_t arr[6];            // Buffer for the sent bytesuint8_t PecReg;         // Calculated PEC byte storage//uint8_t ask_status;/*擦除地址中的数据仅限于EEPROM*/SendRequest(); //复位DataL = (data & 0x00ff); //要写入数据的低8位DataH = (data>>8); //要写入数据的高8位printf("datal:%d dataH:%d \n", DataL, DataH);//计算擦除值的PECarr[5]=0;arr[4]=SlaveAddress;      //arr[3]=command;                  //arr[2]=0x00;     //Load array arr arr[1]=0x00;                      //arr[0]=0;                        //                              //PecReg=PEC_calculation(arr);//Calculate CRCSTOP_bit();   Delay_ms(5);START_bit();                    //Start conditionTX_byte(SlaveAddress); //Send SlaveAddress//Delay_ms(1);TX_byte(command);          //Send command  0012//Delay_ms(1);//擦除扇区for(i=0; i <2 ;i++){if (TX_byte(0x00) == 1){printf("应答失败\n");}//Delay_ms(1);}if (TX_byte(PecReg) == 1){printf("清除扇区检验失败\n");}STOP_bit();  /*写入需要的数据仅限于EEPROM*/SendRequest();//复位//计算输入值的PECarr[5]=0; arr[4]=SlaveAddress;       //arr[3]=command;                  //arr[2]=DataL;        //Load array arr arr[1]=DataH;                     //arr[0]=0;                        //                          //PecReg=PEC_calculation(arr);//Calculate CRC//printf("打印的PEC值:%d\n",PecReg);//TX_byte(PecReg);STOP_bit();                            //Stop conditionDelay_ms(5);START_bit();                //Start conditionTX_byte(SlaveAddress); //Send SlaveAddress//Delay_ms(1);TX_byte(command);      //Send command  //Delay_ms(1);TX_byte(DataL);           //Read low data,master must send ACK//ask_status = read_ack();//printf("askstatus的值为%d \n", ask_status);//Delay_ms(1);TX_byte(DataH);        //Read high data,master must send ACK//ask_status = read_ack();//printf("askstatus的值为%d \n", ask_status);//Delay_ms(1);if (TX_byte(PecReg) == 1){printf("输入数据检验失败\n");}//TX_byte(Pec);           //Read PEC byte, master must send NACK//ask_status = read_ack();//printf("askstatus的值为%d \n", ask_status);//Delay_ms(1);STOP_bit();                          //Stop condition
}

上述为使用IIC读取和写入数据的代码。值得注意的是,这个传感器读取和写入数据的时候必须进Packet Error Code校验。校验要是不通过代表写入或者读取数据失败。具体的代码后面会上传。

三、如何使用PWM捕获或者是SMBUS读取温度数据

unsigned char    SlaveAddress;       //Contains device address
unsigned char   command;            //Contains the access command
unsigned int    data;               //Contains data value
//float temp;
uint16_t send_data = 5328;          //pwm工作模式 输出1kz的pwm send_data = 5329; smbus模式
SlaveAddress=SA;                               //Set device address
command=0x12;    //eeprom config   command=0x27 读取温度数据;if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON)
{MemWrite(SlaveAddress,command,send_data);//data=MemRead(0x00,command); //Read memory//temp=CalcTemp(data);//sprintf((char *)buf," tmp:%0.2f      ",temp);//printf("data:%d\r\n",data);Delay_ms(1000);printf("写入成功%d\n", send_data);
}
if(Key_Scan(KEY2_GPIO_PORT, KEY2_GPIO_PIN) == KEY_ON)
{data=MemRead(SlaveAddress,command); //Read memorytemp=CalcTemp(data);printf("data:%d\r\n",data);Delay_ms(1000);
}
float CalcTemp(unsigned int value)
{float temp;temp=(value*0.02)-273.15;//       _NOP();Delay_us(1);return temp;
}

如上述代码所示,按下按键1就能修改传感器的工作模式,如果是在SMBUS工作模式下按下按键2则可以读取温度。如果是在PWM工作模式下,需要修改对应的电路图,具体电路如下图所示:

如果使用PWM捕获需要使用STM32的高级定时器功能来实现PWM捕获,具体代码可以自行百度或者参考野火STM32教程,直接拷贝对应模块的代码就能进行使用,根据自身的需求修改对面的源码。

四、结语

第一次在CSDN发帖子,不知道该怎么写,感觉写的很差,其中有错误的地方欢迎大家指出。

上述的两张图片分别为直接测量的室温,和手指直接放在传感器上测出来的温度,因为没有温度计,感觉上来说温度还是挺正确的。

参考的帖子:https://blog.csdn.net/baoke485800/article/details/51320740

链接:https://pan.baidu.com/s/1vbqCcuCYBJ8EqlU8_1vYkQ 
提取码:c7cf
复制这段内容后打开百度网盘手机App,操作更方便哦

STM32使用I2C和PWM捕获读取MLX90615温度值相关推荐

  1. 基于FPGA的IIC读取LM74A温度值

    基于FPGA的IIC读取LM74A温度值 IIC总线概述 采用串行总线技术可以使系统的硬件设计大大简化.系统的体积减小.可靠性提高.同时,系统的更改和扩充极为容易.常用的串行扩展总线有: I2C (I ...

  2. STM32通用定时器输出PWM控制舵机 —— 重装载值、比较值、当前值

    参考:stm32 定时器输出PWM原理及工作原理+控制舵机 作者:点灯小哥 发布时间: 2021-03-09 23:17:52 网址:https://blog.csdn.net/weixin_4601 ...

  3. nrf52832通过i2c官方库nrf_drv_twi读取tmp117温度

    twi调试过程如下: 1 代码实现:分别实现对nrf_drv_twi_init,nrf_drv_twi_rx, nrf_drv_twi_tx相关官方库的调用 2 修改工程配置文件sdk_config. ...

  4. 32读取ltc的温度值_Arduino基础入门篇29—模拟温度传感器LM35

    温度传感器就是利用物质随温度变化特性的规律,把温度转换成可输出信号的传感器,是普遍应用的传感器之一.本篇介绍模拟温度传感器-LM35. 1. LM35介绍 LM35是很常用的温度传感器元件,电路连接非 ...

  5. STC15F2K60S2读取DS18B20温度串口显示

    为方便大家调试,特附该程序的项目下载地址 STC15F2K60S2读取DS18B20温度实例下载地址 //************************** //程序说明:stc15f2k60s2采 ...

  6. STM32模拟I2C协议获取MLX90615红外温度传感器测温数据(Open Drain管脚配置)

    STM32模拟I2C协议获取MLX90615红外温度传感器测温数据(Open Drain管脚配置) STM32的GPIO管脚可以配置为Open Drain输出模式,并且有两个功能: 可以设置内部上拉, ...

  7. arduino i2c 如何写16位寄存器_基于STM32使用I2C读取传感器数据

    撑腰会儿:I2C通信协议介绍​zhuanlan.zhihu.com 上文介绍了I2C协议的基本结构,今天,使用STM32和LM75A温度传感器来实现I2C读取信息. 首先,为了使用I2C读取传感器测量 ...

  8. STM32学习记录:输入捕获应用

    目录 前言 一.输入捕获的应用 1.1.测量脉宽或者频率 1.2.测量频率的步骤方法 1.3.测量脉宽的步骤方法 二. 输入捕获工作过程 2.1.CH1为例,输入捕获工作过程 2.2.输入通道 2.3 ...

  9. STM32F1读取MLX90615非接触式红外温度传感器

    MLX90615 简介 MLX90615是一种红外温度计,用于非接触式温度测量.红外敏感热电堆探测器芯片和信号调节芯片集成在同一个TO-46 CAN封装中.由于采用了低噪声放大器.16位模数转换器和强 ...

最新文章

  1. python中tk窗口刷新_80 行 Python 代码写个图形计算器
  2. eclipse中查看java源代码设置方法
  3. 第十六届智能车竞赛总决赛线上比赛赛道设计
  4. 从零开始一个http服务器(五)-模拟cgi
  5. 驰骋工作流引擎设计系列05 启动流程设计
  6. Python安装Whl文件
  7. Spring 核心容器类BeanFactory
  8. Flink解析kafka canal未压平数据为message报错
  9. 【必懂C++】第一个程序当然是HelloWorld呀 01
  10. 你应该知道的 CSS 基础知识
  11. 关于对象流两端的数据不一致的问题:
  12. 【Gym-100085 K】Kingdom Roadmap【树上构造题】
  13. JBoss中间件漏洞总结
  14. Php把ts转为mp4,ts格式转换mp4 - 狸窝
  15. 打卡day01 python基础—常用数据类型
  16. 电脑关机后电源灯还亮
  17. Win10 电脑屏幕亮度随背景颜色变化而变化
  18. 【PID优化】基于matlab粒子群算法优化BP神经网络PID控制【含Matlab源码 2022期】
  19. Xcode 发布测试包TestFlight
  20. MySQL 修改报错 You can't specify target table 'tb_trade' for update in FROM clause

热门文章

  1. 现货黄金3月1日行情分析:关注通胀博弈关键点 金市高位震荡
  2. Open Cluster Management 部署应用实践
  3. 时间控件的添加,My97DatePicker时间控件的下载
  4. 注意力评分函数(掩蔽softmax操作,加性注意力,缩放点积注意力)
  5. 北京ios培训-如何选择好的iOS开发培训机构
  6. 优达twitter 清理_Udacity优达学城数据分析视频
  7. matlab for判断语句,matlab使用笔记(一)——matlab语言中if、for语句与C语言中的差别...
  8. 8255a初始化c语言程序,8255A的c语言程序.doc
  9. 解剖95后—洞悉未来十年消费红利.pdf
  10. 从理论到实践落地「微服务