MLX90614 系列模塊是一組通用的紅外測(cè)溫模塊。在出廠前該模塊已進(jìn)行校驗(yàn)及線性化,具有非接觸、體積小、精度高,成本低等優(yōu)點(diǎn)。被測(cè)目標(biāo)溫度和環(huán)境溫度能通過單通道輸出,并有兩種輸出接口,適合于汽車空調(diào)、室內(nèi)暖氣、家用電器、手持設(shè)備以及醫(yī)療設(shè)備應(yīng)用等。測(cè)溫方式可分為接觸式和非接觸式,接觸式測(cè)溫只能測(cè)量被測(cè)物體與測(cè)溫傳感器達(dá)到熱平衡后的溫度,所以響應(yīng)時(shí)間長(zhǎng),且極易受環(huán)境溫度的影響;而紅外測(cè)溫是根據(jù)被測(cè)物體的紅外輻射能量來確定物體的溫度,不與被測(cè)物體接觸,具有影響動(dòng)被測(cè)物體溫度分布場(chǎng),溫度分辨率高、響應(yīng)速度快、測(cè)溫范圍廣、不受測(cè)溫上限的限制、穩(wěn)定性好等特點(diǎn),所以我們選擇mlx90614來作為紅外測(cè)溫模塊。
單片機(jī)與mlx90614紅外測(cè)溫模塊之間通信的方式是“類IIC”通信,意思就是通信方式跟IIC通信方式很像但又不是IIC,它有另外一個(gè)名字叫做SMBus。SMBus (System Management Bus)是 1995 年由 intel 公司提出的一種高效同步串行總線,SMBus 只有兩根信號(hào)線:雙向數(shù)據(jù)線和時(shí)鐘信號(hào)線,容許 CPU 與各種外圍接口器件以串行方式進(jìn)行通信、交換信息,即可以提高傳輸速度也可以減小器件的資源占用,另外即使在沒有SMBus 接口的單片機(jī)上也可利用軟件進(jìn)行模擬。
1、模塊來源
模塊實(shí)物展示:
資料下載鏈接:
https://pan.baidu.com/s/1AsEBvVCiNAvTKqTeGSA60w
提取碼:g06n
工作電壓:4.5~5.5V
工作電流:1.3~2.5mA
以上信息見廠家資料文件
3、移植過程
我們的目標(biāo)是將例程移植至CW32F030C8T6開發(fā)板上【能夠測(cè)量物體溫度和環(huán)境溫度的功能】。首先要獲取資料,查看數(shù)據(jù)手冊(cè)應(yīng)如何實(shí)現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。
3.1查看資料
MLX90614中有兩個(gè)存儲(chǔ)器,分別為EEPROM和RAM。
MLX90614中共有32個(gè)字長(zhǎng)為16位的EEPROM存儲(chǔ)單元,其地址為000H—01FH。EEPROM中所有的寄存器都是可以通過SMBus進(jìn)行讀取,但只有部分寄存器是可以進(jìn)行改寫的(地址為0x00, 0x01, 0x02, 0x03, 0x04, 0x05*,0x0E, 0x0F, 0x19)。可改寫部分如下圖所示。因在出廠前模塊已進(jìn)行校驗(yàn)及線性化,所以我們直接使用默認(rèn)參數(shù),不需要修改。
MLX90614中總共有32個(gè)17位的RAM存儲(chǔ)單元,用戶不能通過RAM來寫入數(shù)據(jù),只能讀取RAM中的部分存儲(chǔ)單元讀取16位存儲(chǔ)數(shù)據(jù)。其采集的環(huán)境溫度數(shù)據(jù)保存在地址06H存儲(chǔ)單元中,采集的被測(cè)物體溫度數(shù)據(jù)存儲(chǔ)在07H存儲(chǔ)單元中。因此運(yùn)用存儲(chǔ)在RAM地址中的數(shù)據(jù),通過公式的計(jì)算,可以得到環(huán)境溫度Ta及被測(cè)物體溫度數(shù)據(jù)To。
需要注意的是數(shù)據(jù)的低8位在前面,高8位在后。
器件地址(Slave Address)在數(shù)據(jù)手冊(cè)中有說明,默認(rèn)器件地址為0X5A;
命令(Command)是根據(jù)要控制的是RAM還是eeprom來決定一個(gè)字節(jié)中的BIT7~BIT5。剩余的BIT4~BIT0由要操控的地址決定。
例如,我要讀取RAM的Ta溫度數(shù)據(jù),則命令組成見下表。其中RAM地址為000x_xxxx,Ta溫度數(shù)據(jù)地址為0x06=0000_0110,只取低5位則為xxx0_0110。
PEC是一個(gè)多項(xiàng)式為X8+X2+X1+1的CRC-8校驗(yàn)數(shù)據(jù)。
在數(shù)據(jù)手冊(cè)中舉了兩個(gè)例子。其中0xB4為器件地址左移一位后的值。
得到溫度的原始數(shù)據(jù)后,根據(jù)數(shù)據(jù)手冊(cè)的說明進(jìn)行換算即可得到溫度。
以上是手冊(cè)中舉了一個(gè)例子,如果讀取到的溫度數(shù)據(jù)是0X3AF7,其10進(jìn)制為15095,將10進(jìn)制數(shù) 除以50或者乘以0.02得到301.9,再減去273.15即可得到實(shí)際溫度。
溫度 = 溫度原始數(shù)據(jù) * 0.02 - 273.15
該溫度換算公式對(duì)To和Ta都適用。
3.2引腳選擇
模塊接線圖
3.3移植至工程
工程模板參考入門手冊(cè)的工程模板
移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_mlx90614.c與bsp_mlx90614.h。這里不再過多講述,移植完成后面修改相關(guān)代碼。
在文件bsp_mlx90614.c中,編寫如下代碼。
/* * Change Logs: * Date Author Notes * 2024-06-20 LCKFB-ALP first version */ #include "bsp_mlx90614.h" #include "stdio.h" /****************************************************************** * 函 數(shù) 名 稱:MLX90614_GPIO_Init * 函 數(shù) 說 明:MLX90614的引腳初始化 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:MLX90614是5V,而且開發(fā)板開發(fā)板的引腳輸出是3.3V, * 故設(shè)置引腳模式時(shí),必須設(shè)置為開漏模式 ******************************************************************/ void MLX90614_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結(jié)構(gòu)體 RCC_MLX90614_ENABLE(); // 使能GPIO時(shí)鐘 GPIO_InitStruct.Pins = GPIO_SCL|GPIO_SDA; // GPIO引腳 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 開漏輸出 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 輸出速度高 GPIO_Init(PORT_MLX90614, &GPIO_InitStruct); // 初始化 } /****************************************************************** * 函 數(shù) 名 稱:IIC_Start * 函 數(shù) 說 明:IIC起始時(shí)序 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Start(void) { SDA_OUT(); SDA(1); delay_us(5); SCL(1); delay_us(5); SDA(0); delay_us(5); SCL(0); delay_us(5); } /****************************************************************** * 函 數(shù) 名 稱:IIC_Stop * 函 數(shù) 說 明:IIC停止信號(hào) * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Stop(void) { SDA_OUT(); SCL(0); SDA(0); SCL(1); delay_us(5); SDA(1); delay_us(5); } /****************************************************************** * 函 數(shù) 名 稱:IIC_Send_Ack * 函 數(shù) 說 明:主機(jī)發(fā)送應(yīng)答或者非應(yīng)答信號(hào) * 函 數(shù) 形 參:0發(fā)送應(yīng)答 1發(fā)送非應(yīng)答 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Send_Ack(unsigned char ack) { SDA_OUT(); SCL(0); SDA(0); delay_us(5); if(!ack) SDA(0); else SDA(1); SCL(1); delay_us(5); SCL(0); SDA(1); } /****************************************************************** * 函 數(shù) 名 稱:I2C_WaitAck * 函 數(shù) 說 明:等待從機(jī)應(yīng)答 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:0有應(yīng)答 1超時(shí)無應(yīng)答 * 作 者:LC * 備 注:無 ******************************************************************/ unsigned char I2C_WaitAck(void) { char ack = 0; unsigned char ack_flag = 10; SCL(0); SDA(1); SDA_IN(); delay_us(5); SCL(1); delay_us(5); while( (SDA_GET()==1) && ( ack_flag ) ) { ack_flag--; delay_us(5); } if( ack_flag <= 0 ) { IIC_Stop(); return 1; } else { SCL(0); SDA_OUT(); } return ack; } /****************************************************************** * 函 數(shù) 名 稱:Send_Byte * 函 數(shù) 說 明:寫入一個(gè)字節(jié) * 函 數(shù) 形 參:dat要寫人的數(shù)據(jù) * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void Send_Byte(uint8_t dat) { int i = 0; SDA_OUT(); SCL(0);//拉低時(shí)鐘開始數(shù)據(jù)傳輸 for( i = 0; i < 8; i++ ) { SDA( (dat & 0x80) >> 7 ); delay_us(1); SCL(1); delay_us(5); SCL(0); delay_us(5); dat<=1; } } /****************************************************************** * 函 數(shù) 名 稱:Read_Byte * 函 數(shù) 說 明:IIC讀時(shí)序 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:讀到的數(shù)據(jù) * 作 者:LC * 備 注:無 ******************************************************************/ unsigned char Read_Byte(void) { unsigned char i,receive=0; SDA_IN();//SDA設(shè)置為輸入 for(i=0;i8;i++ ) { SCL(0); delay_us(5); SCL(1); delay_us(5); receive<=1; if( SDA_GET() ) { receive|=1; } delay_us(5); } SCL(0); return receive; } ///****************************************************************** // * 函 數(shù) 名 稱:PEC_Calculation // * 函 數(shù) 說 明:PEC校驗(yàn) // * 函 數(shù) 形 參:pec要校驗(yàn)的數(shù)據(jù)地址 len校驗(yàn)的長(zhǎng)度 // * 函 數(shù) 返 回:校驗(yàn)后的值 // * 作 者:LC // * 備 注:無 //******************************************************************/ //static unsigned char PEC_Calculation(unsigned char *dat , unsigned char len) //{ // unsigned char i; // unsigned char crc=0; // while( len-- ) // { // crc ^= *dat++; // for( i=0 ; i8 ; i++ ) // { // if( crc&0x80 ) // { // crc = (crc<1)^0x07; // } // else // { // crc = (crc<1); // } // } // } // return crc; //} /************************************************************ * 函數(shù)名稱:MLX90615_Read * 函數(shù)說明:讀取MLX90615的溫度 * 型 參:SlaveAddr = 器件地址 RegAddr = 要操作的寄存器地址 * 返 回 值:溫度值 * 備 注: SlaveAddr = 0X5A默認(rèn)器件地址 * RegAddr = 0X07讀取被測(cè)量物體溫度 * RegAddr = 0X06讀取環(huán)境溫度 *************************************************************/ float MLX90614_Read(unsigned char SlaveAddr, unsigned char RegAddr) { IIC_Start(); Send_Byte((SlaveAddr < 1) | 0); // 寫命令 if(I2C_WaitAck()) { IIC_Stop(); return 0.0; } Send_Byte(RegAddr); // 寄存器地址 if(I2C_WaitAck()) { IIC_Stop(); return 0.0; } // delay_ms(1); IIC_Start(); Send_Byte((SlaveAddr < 1) | 1); // 讀命令 if(I2C_WaitAck()) { IIC_Stop(); return 0.0; } uint8_t lowByte = Read_Byte(); // 低8位 IIC_Send_Ack(0); uint8_t highByte = Read_Byte(); // 高8位 IIC_Send_Ack(1); IIC_Stop(); uint16_t tempRaw = (highByte < 8) | lowByte; float temperature = (tempRaw * 0.02) - 273.15; return temperature; }
在文件bsp_mlx90614.h中,編寫如下代碼。
/* * Change Logs: * Date Author Notes * 2024-06-20 LCKFB-ALP first version */ #ifndef _BSP_MLX90614_H_ #define _BSP_MLX90614_H_ #include "board.h" //端口移植 #define RCC_MLX90614_ENABLE() __RCC_GPIOA_CLK_ENABLE() #define PORT_MLX90614 CW_GPIOA #define GPIO_SDA GPIO_PIN_1 #define GPIO_SCL GPIO_PIN_0 //設(shè)置SDA輸出模式 #define SDA_OUT() { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pins = GPIO_SDA; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_Init(PORT_MLX90614, &GPIO_InitStruct); } //設(shè)置SDA輸入模式 #define SDA_IN() { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pins = GPIO_SDA; GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_Init(PORT_MLX90614, &GPIO_InitStruct); } //獲取SDA引腳的電平變化 #define SDA_GET() GPIO_ReadPin(PORT_MLX90614, GPIO_SDA) //SDA與SCL輸出 #define SDA(x) GPIO_WritePin(PORT_MLX90614, GPIO_SDA, (x?GPIO_Pin_SET:GPIO_Pin_RESET) ) #define SCL(x) GPIO_WritePin(PORT_MLX90614, GPIO_SCL, (x?GPIO_Pin_SET:GPIO_Pin_RESET) ) void MLX90614_GPIO_Init(void); float MLX90614_Read(unsigned char SlaveAddr, unsigned char RegAddr); void IIC_Stop(void); #endif
4、移植驗(yàn)證
在自己工程中的main主函數(shù)中,編寫如下。
/* * Change Logs: * Date Author Notes * 2024-06-20 LCKFB-ALP first version */ #include "board.h" #include "stdio.h" #include "bsp_uart.h" #include "bsp_mlx90614.h" int32_t main(void) { board_init(); // 開發(fā)板初始化 uart1_init(115200); // 串口1波特率115200 MLX90614_GPIO_Init(); printf("Startrn"); while(1) { float t = MLX90614_Read(0X5A, 0X07); if( t != 0) { printf("temperature = %.2frn", t); } delay_ms(1000); } }
移植現(xiàn)象:測(cè)量手心溫度為36℃左右。
模塊移植成功案例代碼:
鏈接:https://pan.baidu.com/s/1Ts1A7Eqng7yCa2YabmI6_A?pwd=LCKF
提取碼:LCKF
審核編輯 黃宇
-
傳感器
+關(guān)注
關(guān)注
2551文章
51099瀏覽量
753568 -
CW32
+關(guān)注
關(guān)注
1文章
203瀏覽量
641
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論