STM32 F103C8T6学习笔记17:类IIC通信—MLX90614红外非接触温度计

今日学习配置MLX90614红外非接触温度计 与 STM32 F103C8T6 单片机的通信

文章提供测试代码讲解、完整工程下载、测试效果图

本文需要用到的大概基础知识:1.3寸OLED配置通信显示、IIC通信、 定时器配置使用

这里就只贴出我的  OLED驱动方面的网址链接了:

其余的在我STM32 F103C8T6专栏里找吧.......

 STM32 F103C8T6学习笔记16:1.3寸OLED的驱动显示日历-CSDN博客

目录

MLX90614相关基础概念:

红外测温优势:

 MLX90614介绍:

MLX90614 存储器:

MLX90614 的 SMBus 协议:

起始信号与停止信号:

宏定义:

发送读取与PEC:

传感器与单片机引脚接线:

MLX90614配置应用设计函数:

类IIC引脚初始化:

定时器实时刷新OLED打印数据与BMP图像的标志:

数据读取与打印处理:

测试效果图与视频:

测试工程下载:


MLX90614相关基础概念:

红外测温优势:

一般来说,测温方式可分为接触式和非接触式

接触式测温只能测量被测物体与测温传 感器达到热平衡后的温度,所以响应时间长,且极易受环境温度的影响;

而红外测温是根据 被测物体的红外辐射能量来确定物体的温度,不与被测物体接触,具有影响动被测物体温度 分布场,温度分辨率高、响应速度快、测温范围广、不受测温上限的限制、稳定性好等特点, 近年来在家庭自动化、汽车电子、航空和军事上得到越来越广泛的应用。

 MLX90614介绍:

MLX90614系列模块是一组通用的红外测温模块。

在出厂前该模块已进行校验及线 性化,具有非接触、体积小、精度高,成本低等优点。被测目标温度和环境温度能通过单通 道输出,并有两种输出接口,适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设 备应用等。

MLX90614 是一款红外非接触温度计。TO-39 金属封装里同 时集成了红外感应热电堆探测器芯片和信号处理专用集成芯 片。 由于集成了低噪声放大器、17位模数转换器和强大的数字信 号处理单元,使得高精度和高分辨度的温度计得以实现。 温度计具备出厂校准化,有数字PWM和SMBus(系统管理 总线)输出模式。

作为标准,配置为 10 位的 PWM 输出格式用于连续传送温 度范围为-20…120 ˚C 的物体温度,其分辨率为 0.14 ˚C。 POR 默认模式是SMBus 输出格式

MLX90614 存储器:

EEPROM 只有某些存储单元用户能够写入,但是可以读出全部存储单元。

MLX90614 的 EEPROM 有32 个16 位存储单元,

其中存储单元

Tomax,Tomin,Ta 分别是 用户物体温度上下限和环境温度范围,

PWMCTRL是PWM配置寄存器。

RAM   用户不能向RAM写入数据,但是可以读一些存储单元。

MLX90614 的RAM有 32 个17位存储单元,

其中TA,TOBJ1是环境温度和物体温度

在SMBus方式下,可以从这几个存储单元读出环境和被测物体的温度。

MLX90614 的 SMBus 协议:

单片机与MLX90614红外测温模块之间通信的方式是  “类IIC” 通信

意思就是通信方式跟IIC通信方式很像但又不是IIC,它有另外一个名字叫做SMBus。

SMBus (System Management Bus)是1995年由 intel公司提出的一种高效同步串行总线,SMBus只有两根信号线:双向数据线和时钟信号线,容许CPU与各种外围接口器件以串行方式进行通信、交换信息,既可以提高传输速度也可以减小器件的资源占用,另外即使在没有SMBus 接口的单片机上也可利用软件进行模拟。。MLX90614 SMBus时钟的最大频率为100KHz,最小为 10KHz。

起始信号与停止信号:

宏定义:

这里直接贴出所有需要的宏定义供查阅了:

#define ACK         0
#define NACK          1
#define SA     	             0x00 //Slave address ??MLX90614????0x00,????????0x5a
#define RAM_ACCESS    	     0x00 //RAM access command
#define EEPROM_ACCESS   	   0x20 //EEPROM access command
#define RAM_TA               0x06 //环境
#define RAM_TOBJ1    	       0x07 //To1 address in the eeprom 物体
#define RAM_TOBJ2            0x08 //#define SMBUS_PORT               GPIOB
#define SMBUS_SCK                GPIO_Pin_10
#define SMBUS_SDA                GPIO_Pin_11#define RCC_APB2Periph_SMBUS_PORT                RCC_APB2Periph_GPIOB#define SMBUS_SCK_H()            SMBUS_PORT->BSRR = SMBUS_SCK
#define SMBUS_SCK_L()            SMBUS_PORT->BRR  = SMBUS_SCK
#define SMBUS_SDA_H()            SMBUS_PORT->BSRR = SMBUS_SDA
#define SMBUS_SDA_L()            SMBUS_PORT->BRR  = SMBUS_SDA#define SMBUS_SDA_PIN()          SMBUS_PORT->IDR & SMBUS_SDA 

//在SMBus上生成启动条件
void SMBus_StartBit(void)
{SMBUS_SDA_H();                // Set SDA lineSMBus_Delay(1);               // Wait a few microsecondsSMBUS_SCK_H();                // Set SCL lineSMBus_Delay(5);               // Generate bus free time between StopSMBUS_SDA_L();                // Clear SDA lineSMBus_Delay(10);              // Hold time after (Repeated) Start// Condition. After this period, the first clock is generated.//(Thd:sta=4.0us min)SMBUS_SCK_L();            // Clear SCL lineSMBus_Delay(2);            // Wait a few microseconds
}//在SMBus上生成停止条件
void SMBus_StopBit(void)
{SMBUS_SCK_L();                // Clear SCL lineSMBus_Delay(5);               // Wait a few microsecondsSMBUS_SDA_L();                // Clear SDA lineSMBus_Delay(5);               // Wait a few microsecondsSMBUS_SCK_H();                // Set SCL lineSMBus_Delay(10);              // Stop condition setup time(Tsu:sto=4.0us min)SMBUS_SDA_H();                // Set SDA line
}

发送读取与PEC:

//延时
void SMBus_Delay(u16 time)
{u16 i, j;for (i=0; i<4; i++){for (j=0; j<time; j++);}
}//从 RAM/EEPROM 读取数据
u16 SMBus_ReadMemory(u8 slaveAddress, u8 command)
{u16 data;                        // Data storage (DataH:DataL)u8 Pec;                                // PEC byte storageu8 DataL=0;                        // Low data byte storageu8 DataH=0;                        // High data byte storageu8 arr[6];                        // Buffer for the sent bytesu8 PecReg;                        // Calculated PEC byte storageu8 ErrorCounter;        // Defines the number of the attempts for communication with MLX90614ErrorCounter=0x00;                                // Initialising of ErrorCounterslaveAddress <<= 1;        //2-7???????do{
repeat:SMBus_StopBit();                            //If slave send NACK stop comunication--ErrorCounter;                                    //Pre-decrement ErrorCounterif(!ErrorCounter)                             //ErrorCounter=0?{break;                                            //Yes,go out from do-while{}}SMBus_StartBit();                                //Start conditionif(SMBus_SendByte(slaveAddress))//Send SlaveAddress ???Wr=0????????{goto        repeat;                            //Repeat comunication again}if(SMBus_SendByte(command))            //Send command{goto        repeat;                            //Repeat comunication again}SMBus_StartBit();                                        //Repeated Start conditionif(SMBus_SendByte(slaveAddress+1))        //Send SlaveAddress ???Rd=1????????{goto        repeat;                     //Repeat comunication again}DataL = SMBus_ReceiveByte(ACK);        //Read low data,master must send ACKDataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACKPec = SMBus_ReceiveByte(NACK);        //Read PEC byte, master must send NACKSMBus_StopBit();                                //Stop conditionarr[5] = slaveAddress;                //arr[4] = command;                        //arr[3] = slaveAddress+1;        //Load array arrarr[2] = DataL;                                //arr[1] = DataH;                                //arr[0] = 0;                                        //PecReg=PEC_Calculation(arr);//Calculate CRC}while(PecReg != Pec);                //If received and calculated CRC are equal go out from do-while{}data = (DataH<<8) | DataL;        //data=DataH:DataLreturn data;
}u8 SMBus_SendByte(u8 Tx_buffer)
{u8        Bit_counter;u8        Ack_bit;u8        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_out}else{bit_out=0;  // else clear bit_out}SMBus_SendBit(bit_out);                // Send the current bit on SDATx_buffer<<=1;                                // Get next bit for checking}Ack_bit=SMBus_ReceiveBit();                // Get acknowledgment bitreturn        Ack_bit;
}void SMBus_SendBit(u8 bit_out)
{if(bit_out==0){SMBUS_SDA_L();}else{SMBUS_SDA_H();}SMBus_Delay(2);                                        // Tsu:dat = 250ns minimumSMBUS_SCK_H();                                        // Set SCL lineSMBus_Delay(10);                            // High Level of Clock PulseSMBUS_SCK_L();                                        // Clear SCL lineSMBus_Delay(10);                            // Low Level of Clock Pulse
//        SMBUS_SDA_H();                                    // Master release SDA line ,return;
}u8 SMBus_ReceiveBit(void)
{u8 Ack_bit;SMBUS_SDA_H();          //?????????,????SMBUS_SCK_H();                        // Set SCL lineSMBus_Delay(2);                        // High Level of Clock Pulseif (SMBUS_SDA_PIN()){Ack_bit=1;}else{Ack_bit=0;}SMBUS_SCK_L();                        // Clear SCL lineSMBus_Delay(4);                        // Low Level of Clock Pulsereturn        Ack_bit;
}u8 SMBus_ReceiveByte(u8 ack_nack)
{u8         RX_buffer;u8        Bit_Counter;for(Bit_Counter=8; Bit_Counter; Bit_Counter--){if(SMBus_ReceiveBit())                        // 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_bufferRX_buffer &=0xfe;}}SMBus_SendBit(ack_nack);                        // Sends acknowledgment bitreturn RX_buffer;
}//计算接收字节的PEC
u8 PEC_Calculation(u8 pec[])
{u8         crc[6];u8        BitPosition=47;u8        shift;u8        i;u8        j;u8        temp;do{/*Load pattern value 0x000000000107*/crc[5]=0;crc[4]=0;crc[3]=0;crc[2]=0;crc[1]=0x01;crc[0]=0x07;/*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/BitPosition=47;/*Set shift position at 0*/shift=0;/*Find first "1" in the transmited message beginning from the MSByte byte5*/i=5;j=0;while((pec[i]&(0x80>>j))==0 && i>0){BitPosition--;if(j<7){j++;}else{j=0x00;i--;}}/*End of while *//*Get shift value for pattern value*/shift=BitPosition-8;/*Shift pattern value */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;}/*End of for*/shift--;}/*End of while*//*Exclusive OR between pec and crc*/for(i=0; i<=5; i++){pec[i] ^=crc[i];}/*End of for*/}while(BitPosition>8); /*End of do-while*/return pec[0];
}

传感器与单片机引脚接线:

MLX90614配置应用设计函数:

类IIC引脚初始化:

//MLX90614 SMBus通信 初始化
void SMBus_Init(void)
{GPIO_InitTypeDef    GPIO_InitStructure;/* Enable SMBUS_PORT clocks */RCC_APB2PeriphClockCmd(RCC_APB2Periph_SMBUS_PORT, ENABLE);/*??SMBUS_SCK?SMBUS_SDA????????*/GPIO_InitStructure.GPIO_Pin = SMBUS_SCK | SMBUS_SDA;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SMBUS_PORT, &GPIO_InitStructure);SMBUS_SCK_H();SMBUS_SDA_H();
}

定时器实时刷新OLED打印数据与BMP图像的标志:


//刷新时间标志uint16_t TDisplay_cnt,TDisplay;
//刷新BMP图像
uint16_t BMP_cnt,BMP_FLAG,BMPDisplay;	
//定时器2中断服务函数
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){		if(++TDisplay_cnt==15)  //定时器刷新温度{TDisplay_cnt=0;TDisplay=1;}if(++BMP_cnt==9)		        //定时器   刷新太空人图片{BMP_cnt=0;BMP_FLAG++;BMPDisplay=1;if(BMP_FLAG==29){BMP_FLAG=1;}}TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清出中断寄存器标志位,用于退出中断}
}

数据读取与打印处理:

//OLED打印读取到的温度值
void Print_temperature(void)
{if(TDisplay==1){char  buf[20];                //用于暂存oled数据float temp;                   //读取温度//		huanjing=temp*100;             //浮点数扩大100倍存入整数,方便显示
//		wuti=temp*100;                 //浮点数扩大100倍存入整数,方便显示	temp=SMBus_ReadTemp(RAM_TA);    //读取环境温度OLED_ShowCHinese(65+16*0,0,2);  //打印中文“环”OLED_ShowCHinese(65+16*1,0,3);  //打印中文“境”OLED_ShowCHinese(65+16*2,0,0);  //打印中文“温”OLED_ShowCHinese(65+16*3,0,1);  //打印中文“度”		//打印环境温度的值sprintf(buf,"%.2f C",temp);OLED_ShowString(70,2,(u8 *)buf,16);temp=SMBus_ReadTemp(RAM_TOBJ1);//读取物体温度OLED_ShowCHinese(65+16*0,4,4);  //打印中文“物”OLED_ShowCHinese(65+16*1,4,5);  //打印中文“体”OLED_ShowCHinese(65+16*2,4,0);  //打印中文“温”OLED_ShowCHinese(65+16*3,4,1);  //打印中文“度”			//打印物体温度的值sprintf(buf,"%.2f C",temp);OLED_ShowString(70,6,(u8 *)buf,16);		TDisplay=0;}
}

测试效果图与视频:

测试效果还行,能明显区分不同温度的物体:

类IIC通信—MLX90614红外非接触温度计

测试工程下载:

https://download.csdn.net/download/qq_64257614/89250067

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT4.0知识问答、DALL-E生成AI图片、Code Copilot辅助编程,打开新世界的大门

目录 1、DALL-E 文字转图片 在线AI修改2、Write For Me3、Code Copilot 目前最强的AI编程大模型4、Diagrams: Show Me5、Instant Website [Multipage] 网站合成神器6、AskYourPDF Research Assistant 无限PDF7、Diagrams & Data: Research, Analyze, Visualize 精读Excel …

TCP/IP和HTTP协议

TCP/IP OSI 七层模型在提出时的出发点是基于标准化的考虑&#xff0c;而没有考虑到具体的市场需求&#xff0c;使得该模型结构复杂&#xff0c;部分功能冗余&#xff0c;因而完全实现 OSI 参考模型的系统不多。而 TCP/IP 参考模型直接面向市场需求&#xff0c;实现起来也比较…

LeetCode 543.二叉树的直径

题目描述 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,4,5]…

报错“Install Js dependencies failed”【鸿蒙开发Bug已解决】

文章目录 项目场景:问题描述原因分析:解决方案:此Bug解决方案总结Bug解决方案寄语项目场景: 最近也是遇到了这个问题,看到网上也有人在询问这个问题,本文总结了自己和其他人的解决经验,解决了【报错“Install Js dependencies failed”】的问题。 报错如下 问题描述 …

【高质量】2024五一数学建模C题保奖思路+代码(后续会更新)

你的点赞收藏是我后续更新的最大动力&#xff01; 一定要点击文末的卡片&#xff0c;那是获取资料的入口&#xff01; 你是否在寻找数学建模比赛的突破点&#xff1f; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024 年五一数学建模&#xff08;C题&#xff09;…

复旦微JFM7VX690计算后IO接口模块,用于雷达信号处理、数据处理等需要高速密集计算的应用场景

计算后IO接口模块 1 介绍 1.1 产品概述 计算后IO接口模块主要由复旦微JFM7VX690型FPGA、国产以太网收发器YT8521、国产BMC芯片GD32F450、国产CPLD芯片EF2L45BG256B、国产内存颗粒等主要芯片组成&#xff0c;采用标准6U VPX尺寸设计。 本计算后IO接口模块主要用于雷达信号处…

Nginx负载均衡主备模式

1. 背景 使用Nginx代理后端服务&#xff0c;有时候某些服务是不能使用多台负载均衡&#xff0c;但又想保障高可用&#xff0c;所以采用主备模式&#xff0c;记录如下&#xff1a; 2. 参考 nginx 负载均衡Nginx-负载均衡-后端状态max_conns、down、backup、max_fails、fail_t…

【webrtc】MessageHandler 1: 基于线程的消息处理:以10毫秒处理音频为例

基于m98 G:\CDN\rtcCli\m98\src\audio\null_audio_poller.h分发的消息由MessageHandler 类通过其抽象接口OnMessage 实现处理 NullAudioPoller NullAudioPoller 是一个处理audio的消息的分发器 poll 启动:

2024深圳杯数学建模竞赛A题(东三省数学建模竞赛A题):建立火箭残骸音爆多源定位模型

更新完整代码和成品完整论文 《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓&#xff08;浏览器打开&#xff09; https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 2024深圳杯数学建模竞赛A题&#xff08;东三省数学建模竞赛A题&#xff0…

【Go 语言入门专栏】Go 语言的起源与发展

前言 Go 语言是当下最为流行的编程语言之一&#xff0c;大约在 2020、2021 年左右开始于国内盛行&#xff0c;许多大厂很早就将部分 Java 项目迁移到了 Go&#xff0c;足可看出其在性能方面的优越性。 相信各位都知道&#xff0c;在爬虫业务中&#xff0c;并发是一个关键的需…

解决iview(view ui)中tabs组件中使用图片预览组件ImagePreview,图片不显示问题

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、问题描述二、原因分析三、解决方案总结 前言 最近在写个人项目的web端和浏览器插件&#xff0c;其中一个功能是base64和图片的转换。因为分成四个小功能&#xff0c;所以使用的iview的tabs来展示不同功能&#xff0c…

如何解决DA14531编译工程出现大量报错的问题

在编译DA14531某个工程时&#xff0c;在这台电脑可以编译&#xff0c;另外一台电脑就编译不过&#xff0c;出现很多错误问题。那要怎样处理呢&#xff1f; 建议安装新MDK版本 可能是MDK版本问题&#xff0c;在不同的电脑安装不同的MDK版本&#xff0c;用新的版本可以编译通过&…

计算机网络—数据链路层

一、数据链路层的基本概念 结点&#xff1a;主机、路由器 链路&#xff1a;网络中两个结点之间的物理通道&#xff0c;链路的传输介质主要有双绞线、光纤和微波。分为有线链路、无线链路 数据链路&#xff1a;网络中两个结点之间的逻辑通道&#xff0c;把实现控制数据协议的…

java在应用程序里获取不到扬声器设备,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

MF(推荐系统的矩阵分解技术)论文笔记

论文概述 推荐系统的矩阵分解技术可以为用户提供更为准确的个性化推荐&#xff0c;对比传统的近邻技术&#xff0c;矩阵分解技术可以纳入更多信息&#xff0c;如隐式反馈、时间效应和置信度 近邻技术&#xff1a;基于用户或物品之间的相似性进行推荐&#xff0c;当用户之间已…

针孔相机模型原理坐标系辨析内参标定流程内参变换

针孔相机的内参标定 针孔相机原理真空相机模型图片的伸缩和裁剪变换 内参标定———非线性优化张正定标定详细原理(含公式推导)通过多张棋盘格照片完成相机的内参标定流程(C代码)其他工具箱 相机分为短焦镜头和长焦镜头&#xff0c;短焦镜头看到的视野更广阔&#xff0c;同样距…

CSS高级选择器

一、属性选择器 以value开头的att属性的E元素&#xff1a;E[att^"value"]{ ;} a[href^http]{background-color"red";} css a[href^http]{background-color"red"; } html <!DOCTYPE html> <html lang"en"> <head&…

MySQL基础学习(待整理)

MySQL 简介 学习路径 MySQL 安装 卸载预安装的mariadb rpm -qa | grep mariadb rpm -e --nodeps mariadb-libs安装网络工具 yum -y install net-tools yum -y install libaio下载rpm-bundle.tar安装包&#xff0c;并解压&#xff0c;使用rpm进行安装 rpm -ivh \ mysql-communi…

【数据结构(邓俊辉)学习笔记】向量04——有序向量

文章目录 0.概述1.比较器2.有序性甄别3.唯一化3.1低效算法3.1.1实现3.1.2 复杂度3.1.3 改进思路3.2 高效算法3.2.1 实现3.2.2 复杂度 4.查找4.1统一接口4.2 语义定义4.3 二分查找4.3.1 原理4.3.2 实现4.3.3 复杂度4.3.4 查找长度4.3.5 不足 4.4 Fibonacci查找4.4.1 改进思路4.4…

图搜索算法详解与示例代码

在计算机科学领域&#xff0c;图搜索算法是一类用于在图数据结构中查找特定节点或路径的算法。图搜索算法在许多领域都有着广泛的应用&#xff0c;包括网络路由、社交网络分析、游戏开发等。本文将详细介绍几种常见的图搜索算法&#xff0c;包括深度优先搜索&#xff08;DFS&am…