紅外溫度傳感器一般用于非接觸式的溫度檢測(cè)。在我們的系統(tǒng)中經(jīng)常會(huì)有這樣的需求。所以我們將其設(shè)計(jì)為通用的驅(qū)動(dòng)庫(kù)以備復(fù)用。這一篇我們將講述MLX90614紅外溫度傳感器驅(qū)動(dòng)的設(shè)計(jì)與實(shí)現(xiàn)。
1 、功能概述
MLX90614是一種紅外溫度計(jì),用于非接觸式溫度測(cè)量。紅外測(cè)溫是根據(jù)被測(cè)物體的紅外輻射能量來(lái)確定物體的溫度,不與被測(cè)物體接觸,具有不影響被測(cè)物體溫度分布場(chǎng),溫度分辨率高、響應(yīng)速度快、測(cè)溫范圍廣、不受測(cè)溫上限的限制、穩(wěn)定性好等特點(diǎn)。MLX90614被測(cè)目標(biāo)溫度和環(huán)境溫度通過(guò)IIC接口輸出,適合于汽車(chē)空調(diào)、室內(nèi)暖氣、家用電器、手持設(shè)備以及醫(yī)療設(shè)備應(yīng)用等。
1.1 、硬件描述
MLX90614 是一款無(wú)接觸式的紅外線(xiàn)溫度感應(yīng)芯片,它在同一TO-39封裝內(nèi)整合了紅外熱電堆感應(yīng)器與一款定制的信號(hào)調(diào)節(jié)芯片。MLX90614在信號(hào)調(diào)節(jié)芯片中使用了先進(jìn)的低噪音放大器,一枚17-bit ADC以及功能強(qiáng)大的DSP元件,從而實(shí)現(xiàn)高精度溫度測(cè)量。其引腳封裝及功能如下:
MLX90614的出廠(chǎng)校準(zhǔn)溫度范圍很廣:環(huán)境溫度為-40°C…125°C,目標(biāo)溫度為-70°C…380°C。測(cè)量值是傳感器視場(chǎng)中所有物體的平均溫度。在室溫下,MLX90614的標(biāo)準(zhǔn)精確度為±0.5度。有一種特殊的醫(yī)療應(yīng)用版本,在人體體溫的有限溫度范圍內(nèi)精確呈現(xiàn)±0.2恒溫。
1.2 、數(shù)據(jù)通訊
MLX90614紅外溫度傳感器具有數(shù)字PWM和SMBus(系統(tǒng)管理總線(xiàn))輸出。10位PWM作為標(biāo)準(zhǔn)配置,可以在-20…120完美呈現(xiàn)測(cè)量溫度,輸出分辨率為0.14完美呈現(xiàn)。工廠(chǎng)默認(rèn)的設(shè)置是SMBus總線(xiàn)接口。
MLX90614紅外溫度傳感器又有一個(gè)參數(shù)存儲(chǔ)EEPROM內(nèi)存。在EEPROM內(nèi)存中有限數(shù)量的地址可以由客戶(hù)更改,這些地址存儲(chǔ)著傳感器可修改配置信息。整個(gè)EEPROM都可以通過(guò)SMBus接口讀取。具體分配如下:
在這個(gè)EEPROM中,我們需要注意的有PWM控制寄存器以及配置寄存器。PWMCTRL寄存器的各位定義如下:
ConfigRegister1由控制位組成,用于配置模擬和數(shù)字部分,ConfigRegister1寄存器的各位定義如下:
MLX90614紅外溫度傳感器還擁有一個(gè)32個(gè)字的RAM。用于存儲(chǔ)一些實(shí)時(shí)更新的數(shù)據(jù),如我們的測(cè)量數(shù)據(jù)。這一部分是只讀的,其地址分配如下:
我們了解了MLX90614紅外溫度傳感器的EEPROM和RAM的地址分配,它們的地址是分別編碼的,似乎看不出差別。那我們?nèi)绾文軄?lái)區(qū)別訪(fǎng)問(wèn)它們呢?于是MLX90614紅外溫度傳感器定義有如下的功能碼:
讀寫(xiě)EEPROM和RAM的命令,前三位表示命令,后5為對(duì)應(yīng)所讀參數(shù)在EEPROM和RAM中的地址。標(biāo)志位是只讀的,MLX90614在16位數(shù)據(jù)之后返回PEC,其中只有4位是有意義的,如果MD需要它,它可以在第一個(gè)字節(jié)之后停止通信。讀數(shù)據(jù)和讀標(biāo)志的區(qū)別在于后者沒(méi)有重復(fù)的起始位。
MLX90614紅外溫度傳感器設(shè)備地址默認(rèn)為0xB4,可以通過(guò)寫(xiě)EEPROM來(lái)修改設(shè)備地址。
2 、驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)
我們已經(jīng)了解了MLX90614紅外溫度傳感器的基本情況,接下來(lái)我們將根據(jù)這些資料開(kāi)發(fā)MLX90614紅外溫度傳感器的驅(qū)動(dòng)程序。
2.1 、對(duì)象定義
在使用一個(gè)對(duì)象之前我們需要獲得一個(gè)對(duì)象。同樣的我們想要使用MLX90614紅外溫度傳感器對(duì)象就需要先定義MLX90614紅外溫度傳感器的對(duì)象。
2.1.1 、對(duì)象的抽象
我們要得到MLX90614溫度傳感器對(duì)象,需要先分析其基本特性。一般來(lái)說(shuō),一個(gè)對(duì)象至少包含兩方面的特性:屬性與操作。接下來(lái)我們就來(lái)從這兩個(gè)方面思考一下MLX90614溫度傳感器的對(duì)象。
先來(lái)考慮屬性,作為屬性肯定是用于標(biāo)識(shí)或記錄對(duì)象特征的東西。我們來(lái)考慮MLX90614紅外溫度傳感器對(duì)象屬性。作為SMBus總線(xiàn)設(shè)備需要一個(gè)設(shè)備地址,這一地址用來(lái)區(qū)分總線(xiàn)上不同設(shè)備,所以我們將設(shè)備地址作為它的一個(gè)屬性。對(duì)象的狀態(tài)標(biāo)識(shí),PWM控制寄存器、配置寄存器都只是了MLX90614紅外溫度傳感器當(dāng)前所處的狀態(tài),所以我們將它們也作為屬性。設(shè)備ID號(hào)是唯一標(biāo)識(shí)各個(gè)MLX90614紅外溫度傳感器的,我們也將其作為屬性。測(cè)量的溫度信號(hào)也表示了MLX90614紅外溫度傳感器當(dāng)前的狀態(tài),我們也將他們作為屬性。標(biāo)志寄存器在MLX90614紅外溫度傳感器中是16位的,但真正有效的只有4位,所以我們以8位表示。
接著我們還需要考慮MLX90614紅外溫度傳感器對(duì)象的操作問(wèn)題。對(duì)于MLX90614紅外溫度傳感器來(lái)說(shuō),我們需要對(duì)它進(jìn)行讀數(shù)據(jù)和寫(xiě)數(shù)據(jù),而讀寫(xiě)操作依賴(lài)于具體的硬件平臺(tái),所以我們將其作為對(duì)象的操作,以回調(diào)函數(shù)的方式使用。在操作MLX90614紅外溫度傳感器的過(guò)程中,有些時(shí)序需要控制,所以需要延時(shí)函數(shù),但延時(shí)操作依賴(lài)于具體的軟硬件平臺(tái),所以我們將其作為對(duì)象的操作,以回調(diào)函數(shù)的方式使用。
根據(jù)上述我們對(duì)MLX90614紅外溫度傳感器的分析,我們可以定義MLX90614紅外溫度傳感器的對(duì)象類(lèi)型如下:
typedef structMLXObject {
uint8_t devAddress; //對(duì)象的地址
uint8_t flags; //對(duì)象狀態(tài)標(biāo)志
uint16_t pwmctrl; //PWM控制寄存器
uint16_t ConfigRegister; //配置寄存器
uint16_t ID[4]; //對(duì)象的ID值
float tempAmbient; //溫度值
float tempObject1; //溫度值
float tempObject2; //溫度值
void (*Read)(struct MLXObject *mlx,uint8_t cmd,uint8_t *rData,uint16_trSize); //讀數(shù)據(jù)操作指針
void (*Write)(struct MLXObject *mlx,uint8_t cmd,uint8_t *wData,uint16_twSize); //寫(xiě)數(shù)據(jù)操作指針
void (*Delayus)(volatile uint32_tnTime); //延時(shí)操作指針
}MLXObjectType;
2.1.2 、對(duì)象初始化
我們知道,一個(gè)對(duì)象僅作聲明是不能使用的,我們需要先對(duì)其進(jìn)行初始化,所以這里我們來(lái)考慮MLX90614紅外溫度傳感器對(duì)象的初始化函數(shù)。一般來(lái)說(shuō),初始化函數(shù)需要處理幾個(gè)方面的問(wèn)題。一是檢查輸入?yún)?shù)是否合理;二是為對(duì)象的屬性賦初值;三是對(duì)對(duì)象作必要的初始化配置。據(jù)此我們?cè)O(shè)計(jì)MLX90614紅外溫度傳感器對(duì)象的初始化函數(shù)如下:
/* 紅外溫度傳感器對(duì)象初始化 */
void MLXInitialization(MLXObjectType*mlx, //MLX90614對(duì)象
uint8_t address, //設(shè)備地址
MLXRead read, //讀數(shù)據(jù)函數(shù)指針
MLXWrite write, //寫(xiě)數(shù)據(jù)函數(shù)指針
MLXDelayus delayus //微秒巖石函數(shù)指針
)
{
if((mlx==NULL)||(read==NULL)||(write==NULL)||(delayus==NULL))
{
return;
}
mlx->Read=read;
mlx->Write=write;
mlx->Delayus=delayus;
mlx->tempAmbient=0.0;
mlx->tempObject1=0.0;
mlx->tempObject2=0.0;
if(address>0x00)
{
mlx->devAddress=address;
}
else
{
mlx->devAddress=MLXSlaveAddress;
}
mlx->Delayus(200);
GetIDFromMLX90614(mlx);
mlx->flags=(uint8_t)ReadFlagFromMLX(mlx);
mlx->pwmctrl=ReadDataFromMLX(mlx,EEPROMAccess|PWMCTRL);
mlx->ConfigRegister=ReadDataFromMLX(mlx,EEPROMAccess|ConfigRegister1);
}
2.2 、對(duì)象操作
我們已經(jīng)完成了MLX90614紅外溫度傳感器對(duì)象類(lèi)型的定義和對(duì)象初始化函數(shù)的設(shè)計(jì)。但我們的主要目標(biāo)是獲取對(duì)象的信息,接下來(lái)我們還要實(shí)現(xiàn)面向MLX90614紅外溫度傳感器的各類(lèi)操作。
2.2.1 、讀數(shù)據(jù)操作
我們需要從MLX90614紅外溫度傳感器讀取數(shù)據(jù),不管這個(gè)數(shù)據(jù)是在EEPROM還是在RAM,我們都可以采用相同的方式讀取。我們已經(jīng)說(shuō)過(guò),操作EEPROM和RAM的命令字節(jié)由3位命令和5位地址組成。我們實(shí)現(xiàn)數(shù)據(jù)讀取函數(shù)如下:
/*讀數(shù)據(jù)操作*/
static uint16_t ReadDataFromMLX(MLXObjectType *mlx,uint8_t cmd)
{
uint8_t data[3];
uint16_t tempCode=0;
uint8_t pec[6];
mlx->Read(mlx,cmd,data,3);
pec[0]=mlx->devAddress;
pec[1]=cmd;
pec[2]=mlx->devAddress+1;
pec[3]=data[0];
pec[4]=data[1];
pec[5]=data[2];
if(PECCalculation(pec,6)==0x00)
{
tempCode=(data[1]<<8)+data[0];
}
return tempCode;
}
2.2.2 、寫(xiě)數(shù)據(jù)操作
我們需要向MLX90614紅外溫度傳感器寫(xiě)一些數(shù)據(jù)用以配置傳感器,這些可寫(xiě)的寄存器處于EEPROM之中,如配置寄存器、PWM控制信息、設(shè)備地址等。這里我們?cè)O(shè)計(jì)一個(gè)配置這些數(shù)據(jù)的操作函數(shù)。
/* 寫(xiě)數(shù)據(jù)操作 */
static void WriteDataToMLX(MLXObjectType *mlx,uint8_t cmd,uint16_t data)
{
uint8_t wData[3];
uint8_t pec[4];
pec[0]=mlx->devAddress;
pec[1]=cmd;
pec[2]=(uint8_t)data;
pec[3]=(uint8_t)(data>>8);
wData[0]=(uint8_t)data;
wData[1]=(uint8_t)(data>>8);
wData[2]=PECCalculation(pec,4);
mlx->Write(mlx,cmd,wData,3);
}
2.2.3 、操作休眠模式
有些時(shí)候在我們不使用設(shè)備時(shí),我們希望能夠讓設(shè)備休眠以節(jié)省資源,在需要時(shí)再將其喚醒投入工作。MLX90614具備有休眠的功能,這里我們看看如何使用這一功能。
/* 使設(shè)備進(jìn)入休眠模式 */
void EnterSleepModeForMLX(MLXObjectType *mlx)
{
uint8_t cmd;
static uint8_t pec;
uint8_t data[2];
cmd=EnterSLEEPMode;
data[0]=mlx->devAddress;
data[1]=cmd;
pec=PECCalculation(data,2);
mlx->Write(mlx,cmd,&pec,1);
}
3 、驅(qū)動(dòng)的使用
我們已經(jīng)設(shè)計(jì)并實(shí)現(xiàn)了MLX90614紅外溫度傳感器的驅(qū)動(dòng)程序。我們還需要對(duì)這一驅(qū)動(dòng)進(jìn)行驗(yàn)證。接下來(lái)我們將基于這一驅(qū)動(dòng)程序開(kāi)發(fā)獲取MLX90614紅外溫度傳感器數(shù)據(jù)的簡(jiǎn)單應(yīng)用。
3.1 、聲明并初始化對(duì)象
使用基于對(duì)象的操作我們需要先得到這個(gè)對(duì)象,所以我們先要使用前面定義的MLX90614紅外溫度傳感器對(duì)象類(lèi)型聲明一個(gè)MLX90614紅外溫度傳感器對(duì)象變量,具體操作格式如下:
MLXObjectTypemlx;
我們聲明了這個(gè)對(duì)象變量,但還不能立即使用。我們還需要使用驅(qū)動(dòng)中定義的初始化函數(shù)對(duì)這個(gè)對(duì)象變量進(jìn)行初始化。初始化函數(shù)有一些用于對(duì)象初始化的參數(shù)需要輸入:
MLXObjectType*mlx,MLX90614對(duì)象
uint8_t address,設(shè)備地址
MLXRead read,讀數(shù)據(jù)函數(shù)指針
MLXWrite write,寫(xiě)數(shù)據(jù)函數(shù)指針
MLXDelayusdelayus,微秒延時(shí)函數(shù)指針
對(duì)于這些參數(shù),對(duì)象變量我們已經(jīng)定義了,它正是我們需要初始化的對(duì)象。在這些參數(shù)中,我們需要注意的是幾個(gè)函數(shù)指針,我們需要在應(yīng)用中定義這幾個(gè)函數(shù),并將函數(shù)指針作為參數(shù)。這幾個(gè)函數(shù)的類(lèi)型如下:
/*定義讀MLX90614數(shù)據(jù)操作指針類(lèi)型*/
typedef void (*MLXRead)(struct MLXObject*mlx,uint8_t cmd,uint8_t *rData,uint16_t rSize);
/*定義寫(xiě)MLX90614數(shù)據(jù)操作指針類(lèi)型*/
typedef void (*MLXWrite)(structMLXObject *mlx,uint8_t cmd,uint8_t *wData,uint16_t wSize);
/*定義微秒延時(shí)操作指針類(lèi)型*/
typedef void (*MLXDelayus)(volatileuint32_t nTime);
對(duì)于這幾個(gè)函數(shù)我們根據(jù)樣式定義就可以了,具體的操作可能與使用的軟硬件平臺(tái)有關(guān)系。在這里我們使用STM32F4的第2個(gè)I2C接口及其外設(shè)庫(kù),所以具體函數(shù)定義如下:
/*從MLX90614接收數(shù)據(jù)*/
static void ReceiveFromMLX(MLXObjectType*mlx,uint8_t cmd,uint8_t *rData,uint16_t rSize)
{
HAL_I2C_Master_Transmit(&hlpti2c,mlx->devAddress,&cmd,1,1000);
HAL_I2C_Master_Receive(&hlpti2c, mlx->devAddress,rData, rSize, 1000);
}
/*向MLX90614傳送數(shù)據(jù)*/
static void TransmitToMLX(MLXObjectType*mlx,uint8_t cmd,uint8_t *tData,uint16_t tSize)
{
uint8_t data[10];
data[0]=cmd;
for(int i=0;i1]=tData[i];
}
HAL_I2C_Master_Transmit(&hlpti2c,mlx->devAddress,data,tSize+1,1000);
}
對(duì)于延時(shí)函數(shù)我們可以采用各種方法實(shí)現(xiàn)。我們采用的STM32平臺(tái)和HAL庫(kù)則可以直接使用HAL_Delay()函數(shù)。于是我們可以調(diào)用初始化函數(shù)如下:
MLXInitialization(&mlx,0xB4,ReceiveFromMLX,TransmitToMLX,HAL_Delay);
3.2 、基于對(duì)象進(jìn)行操作
我們定義了對(duì)象變量并使用初始化函數(shù)給其作了初始化。接著我們就來(lái)考慮操作這一對(duì)象獲取我們想要的數(shù)據(jù)。我們?cè)隍?qū)動(dòng)中已經(jīng)將獲取數(shù)據(jù)并轉(zhuǎn)換為轉(zhuǎn)換值的比例值,接下來(lái)我們使用這一驅(qū)動(dòng)開(kāi)發(fā)我們的應(yīng)用實(shí)例。
/*讀取溫度值*/
void GetTemperatureDataFromMLX(void)
{
float tempObject;
float tempAmbient;
GetMLXTemperature(&mlx);
tempObject=mlx.tempObject1;
tempAmbient=mlx.tempAmbient;
}
4 、應(yīng)用總結(jié)
我們?cè)O(shè)計(jì)并實(shí)現(xiàn)了MLX90614紅外溫度傳感器的驅(qū)動(dòng)程序,并在此基礎(chǔ)上設(shè)計(jì)了一個(gè)簡(jiǎn)單的應(yīng)用來(lái)驗(yàn)證之。事實(shí)上我們?cè)趯?shí)際項(xiàng)目中也是使用這一驅(qū)動(dòng)程序來(lái)實(shí)現(xiàn)應(yīng)用的,并且效果良好。
讀標(biāo)志與讀數(shù)據(jù)在時(shí)序控制上是有一些差別的,下發(fā)命令與接收數(shù)據(jù)之間沒(méi)有重啟的操作,這一點(diǎn)在操作它時(shí)需要注意。
我們?cè)谑褂抿?qū)動(dòng)時(shí),一般會(huì)選擇使用GPIO模擬的I2C收發(fā)器,這樣穩(wěn)定性更好。而使用硬件I2C接口及其庫(kù)函數(shù)實(shí)現(xiàn)時(shí),經(jīng)常會(huì)有死鎖的事情發(fā)生。我們?cè)啻斡龅?,特別是在STM32的第一路I2C接口。至于第1路I2C接口與其它的I2C接口有什么差異尚未確定。總之使用GPIO模擬I2C收發(fā)器更為穩(wěn)定。
評(píng)論