特性和优点: 体积小,成本低 易集成 宽温度范围内的出厂校准设置: 传感器温度范围-40…+125 °C 物体温度范围-70…+380 °C Ta和To 由0到+50°C 温度范围内,精度可达到0.5°C (医用) 高精度校准 测量辨析度可达 0.02°C 单个和双重视野版本 兼容SMBus数字接口 客户定制的PWM连续读数输出 3V和 5V 电源电压 电源电压可从 8…16V 调节 节能工作模式 适用于不同应用领域的多种封装方式和测量方式 车用级别标准 应用实例: 高精度无接触测量 用于车用空调控制系统的温度舒适度传感器 用于住宅,商业和工业建筑的空调温度感应元件 挡风玻璃防雾应用 汽车视野死角检测 工业移动元件温度控制 打印机、复印机温度控制 家电温度控制 卫生保健 家畜监控 移动物体探测 多区域温度控制 – 两线通信可支持多达100个传感器 热动继电器 / 警报 体温测量??
MLX90614是一款红外非接触温度计。TO-39金属封装里同时集成了红外感应热电堆探测器芯片和信号处理专用集成芯片。 由于集成了低噪声放大器、17位模数转换器和强大的数字信号处理单元,使得高精度和高分辨度的温度计得以实现。 温度计具备出厂校准化,有数字PWM和SMBus(系统管理总线)输出模式。 作为标准,配置为10位的PWM输出格式用于连续传送温度范围为-20…120 °C的物体温度,其分辨率为0.14 °C。POR默认模式是SMBus输出格式。
? ? ?时序
? ? ? ? SCL 引脚的辅助功能 (齐纳二极管) 会给时钟脉冲增加下脉冲信号 (5V 版本) ,如图所示。 (见图 9) 这个脉冲是由片上合成齐纳二极管的瞬态响应造成的,典型时间大约为15μs。SCL线上电抗增加也会加剧该效应。该脉冲不会影响MLX90614识别SCL的上升沿。但可能会妨碍总线上非MLX90614从动器件的正常工作。
?
? ? ? PWM/SDA 的数据必须在SCL为低时改变。 (SCL下降沿后间隔至少) 在SCL的上升沿,MD和SD的数据被读出,建议在SCL为低电平的中间时刻改变数据。
? ? ?睡眠模式 ? ? ?MLX90614可通过SMBus接口发送“进入睡眠模式”命令来进入睡眠模式。5V版本没有该功能。为了将电流损耗降为2.5uA (典型值),在模式中SCL保持低电平 。通过将SCL引脚置为高电平,并将PWM/SDA引脚保持低电平不少于tDDq=80ms来使 MLX90614回到POR默认模式 (通过重置 POR) ? ? ?如果EEPROM 配置为 PWM模式, (EN_PWM 为高) 在唤醒器件之后,并PWM control[2], PPODB为1,将选择PWM模式,MLX90614会通过推挽式输出PWM脉冲序列。
?退出睡眠模式
? ? ? ?在退出睡眠模式后,间隔0.25s(典型值),才输出数据。第一次测量时片上IIR滤波器被跳过。所有测量结果都会通过由EEPROM设置的嵌入式数字滤波器。嵌入式滤波器的详细介绍请参考www.melexis.com网站上的应用指南“理解MLX90614片上信号滤波器”。 ? ? ? ?将SCL 引脚置为低以降低引脚上的漏电流。 (合成齐纳二极管接于该引脚)
? ? ? ?PWM 使能 ? ? ? ?下图显示了在PWM使能情况下,切换到SMBus的方式。 (POR后MLX90614为出厂默认输出方式SMBus,,PWM 未使能)。注意SCL引脚需要保持高电平以便使用PWM。
? ? ? 如果PWM 使能, MLX90614’s 需要SMBus请求状态使PWM不使能并在开始SMBus通信之前重新配置PWM/SDA引脚。一旦PWM未使能,它只能通过切断-打开电源或是退出睡眠模式来使其使能。The MLX90614’s SMBus 请求状态需要将SCL引脚持续多于请求时间 (tREQ) >1,44ms保持为低电平。此情形下SDA线上的数据被忽略。
配置地址
#define ACK?? ? 0 #define?? ?NACK 1 #define SA?? ??? ??? ??? ?0x00 //从机地址,单个MLX90614时地址为0x00,多个时地址默认为0x5a #define RAM_ACCESS?? ??? ?0x00 //RAM access command #define EEPROM_ACCESS?? ?0x20 //EEPROM access command #define RAM_TOBJ1?? ??? ?0x07 //To1 address in the eeprom
#define SMBUS_PORT?? ? ? ?GPIOB #define SMBUS_SCK?? ??? ?GPIO_Pin_12 #define SMBUS_SDA?? ??? ?GPIO_Pin_13
#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 //读取引脚电平
配置功能
void SMBus_StartBit(void) { ? ? SMBUS_SDA_H();?? ??? ?// Set SDA line ? ? SMBus_Delay(5);?? ? ? ?// Wait a few microseconds ? ? SMBUS_SCK_H();?? ??? ?// Set SCL line ? ? SMBus_Delay(5);?? ? ? ?// Generate bus free time between Stop ? ? SMBUS_SDA_L();?? ??? ?// Clear SDA line ? ? SMBus_Delay(5);?? ? ? ?// Hold time after (Repeated) Start ? ? // Condition. After this period, the first clock is generated. ? ? //(Thd:sta=4.0us min) ? ? SMBUS_SCK_L();?? ? ? ?// Clear SCL line ? ? SMBus_Delay(5);?? ? ? ?// Wait a few microseconds }
void SMBus_StopBit(void) { ? ? SMBUS_SCK_L();?? ??? ?// Clear SCL line ? ? SMBus_Delay(5);?? ? ? ?// Wait a few microseconds ? ? SMBUS_SDA_L();?? ??? ?// Clear SDA line ? ? SMBus_Delay(5);?? ? ? ?// Wait a few microseconds ? ? SMBUS_SCK_H();?? ??? ?// Set SCL line ? ? SMBus_Delay(5);?? ? ? ?// Stop condition setup time(Tsu:sto=4.0us min) ? ? SMBUS_SDA_H();?? ??? ?// Set SDA line }
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 SDA ? ? ? ? Tx_buffer<<=1;?? ??? ??? ??? ?// Get next bit for checking ? ? }
? ? Ack_bit=SMBus_ReceiveBit();?? ??? ?// Get acknowledgment bit ? ? return?? ?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 minimum ? ? SMBUS_SCK_H();?? ??? ??? ??? ??? ?// Set SCL line ? ? SMBus_Delay(6);?? ??? ??? ??? ??? ?// High Level of Clock Pulse ? ? SMBUS_SCK_L();?? ??? ??? ??? ??? ?// Clear SCL line ? ? SMBus_Delay(3);?? ??? ??? ??? ??? ?// Low Level of Clock Pulse //?? ?SMBUS_SDA_H();?? ??? ??? ??? ? ? ?// Master release SDA line , ? ? return; }
u8 SMBus_ReceiveBit(void) { ? ? u8 Ack_bit;
? ? SMBUS_SDA_H(); ? ? ? ? ?//引脚靠外部电阻上拉,当作输入 ?? ?SMBus_Delay(2);?? ??? ??? ?// High Level of Clock Pulse ? ? SMBUS_SCK_H();?? ??? ??? ?// Set SCL line ? ? SMBus_Delay(5);?? ??? ??? ?// High Level of Clock Pulse ? ? if (SMBUS_SDA_PIN()) ? ? { ? ? ? ? Ack_bit=1; ? ? } ? ? else ? ? { ? ? ? ? Ack_bit=0; ? ? } ? ? SMBUS_SCK_L();?? ??? ??? ?// Clear SCL line ? ? SMBus_Delay(3);?? ??? ??? ?// Low Level of Clock Pulse
? ? return?? ?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_buffer ? ? ? ? ? ? RX_buffer |=0x01; ? ? ? ? } ? ? ? ? else ? ? ? ? { ? ? ? ? ? ? RX_buffer <<= 1;?? ??? ??? ?// If the bit is LOW save 0 in RX_buffer ? ? ? ? ? ? RX_buffer &=0xfe; ? ? ? ? } ? ? } ? ? SMBus_SendBit(ack_nack);?? ??? ??? ?// Sends acknowledgment bit ? ? return RX_buffer; }
void SMBus_Delay(u16 time) { ? ? u16 i, j; ? ? for (i=0; i<4; i++) ? ? { ? ? ? ? for (j=0; j<time; j++); ? ? } }
void SMBus_Init() { ? ? 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(); }
u16 SMBus_ReadMemory(u8 slaveAddress, u8 command) { ? ? u16 data;?? ??? ??? ?// Data storage (DataH:DataL) ? ? u8 Pec;?? ??? ??? ??? ?// PEC byte storage ? ? u8 DataL=0;?? ??? ??? ?// Low data byte storage ? ? u8 DataH=0;?? ??? ??? ?// High data byte storage ? ? u8 arr[6];?? ??? ??? ?// Buffer for the sent bytes ? ? u8 PecReg;?? ??? ??? ?// Calculated PEC byte storage ? ? u8 ErrorCounter;?? ?// Defines the number of the attempts for communication with MLX90614
? ? ErrorCounter=0x00;?? ??? ??? ??? ?// Initialising of ErrorCounter ?? ?slaveAddress <<= 1;?? ?//2-7位表示从机地址 ?? ? ? ? do ? ? { repeat: ? ? ? ? SMBus_StopBit();?? ??? ??? ? ? ?//If slave send NACK stop comunication ? ? ? ? --ErrorCounter;?? ??? ??? ??? ? ? ?//Pre-decrement ErrorCounter ? ? ? ? if(!ErrorCounter) ?? ??? ??? ? ? ?//ErrorCounter=0? ? ? ? ? { ? ? ? ? ? ? break;?? ??? ??? ??? ??? ? ? ?//Yes,go out from do-while{} ? ? ? ? }
? ? ? ? SMBus_StartBit();?? ??? ??? ??? ?//Start condition ? ? ? ? if(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 condition ? ? ? ? if(SMBus_SendByte(slaveAddress+1))?? ?//Send SlaveAddress 最低位Rd=1表示接下来读数据 ? ? ? ? { ? ? ? ? ? ? goto?? ?repeat; ? ? ? ? ? ? ?? ?//Repeat comunication again ? ? ? ? }
? ? ? ? DataL = SMBus_ReceiveByte(ACK);?? ?//Read low data,master must send ACK ? ? ? ? DataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACK ? ? ? ? Pec = SMBus_ReceiveByte(NACK);?? ?//Read PEC byte, master must send NACK ? ? ? ? SMBus_StopBit();?? ??? ??? ??? ?//Stop condition
? ? ? ? arr[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 CRC ? ? } ? ? while(PecReg != Pec);?? ??? ?//If received and calculated CRC are equal go out from do-while{}
?? ?data = (DataH<<8) | DataL;?? ?//data=DataH:DataL ? ? return data; }
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]; }
最后计算出温度值
float SMBus_ReadTemp(void) { ?? ?? ?return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TOBJ1)*0.02-273.15+2; } H文件
#ifndef __BSP_MLX90614_H #define __BSP_MLX90614_H
#include "stm32f10x.h"
void SMBus_StartBit(void); void SMBus_StopBit(void); void SMBus_SendBit(u8); u8 SMBus_SendByte(u8); u8 SMBus_ReceiveBit(void); u8 SMBus_ReceiveByte(u8); void SMBus_Delay(u16); void SMBus_Init(void); u16 SMBus_ReadMemory(u8, u8); u8 PEC_Calculation(u8*); float SMBus_ReadTemp(void); ? ?//获取温度值? #endif
主函数(这里使用的窜口打印)
#include "bsp-led.h" #include "bsp-usart.h" #include "bsp-mlx90614.h"
void delay(uint32_t i) { ? for(;i!=0;i--); }
int main(void) { ?? ??? ?float Temperature; ?? ??? ?USART_Config(); ? ? ? ? SMBus_Init(); ?? ??? ?while(1) ?? ??? ? { ?? ??? ??? ?Temperature=SMBus_ReadTemp(); ?? ??? ? ?printf("The Temperature is:%f\n",Temperature); ?? ??? ??? ?delay(0xffffff);
? ? ? ? ? }
? ? }
|