今日学习配置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