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