目錄
模塊選擇
編程環(huán)境
?MLX90614基本原理
通信協(xié)議(SMBus通信,類IIC通信)
代碼實現(xiàn)
STM32與模塊之間接線表
1.標準庫實現(xiàn)溫度采集
2.HAL庫實現(xiàn)溫度采集
模塊選擇
? ? ? ? ·STM32F103C8T6
? ? ? ? ·MLX90614 非接觸式紅外測溫傳感器
編程環(huán)境
? ? ? ? ·KEIL5(μVision V5.30.0.0) 其它版本影響并不大
?? ? ? ? ·STM32CubeMX,版本不限
?? ? ? ? ·串口助手
?MLX90614基本原理
?引腳說明
編號 | 名稱 | 功能 |
1 | VCC | 電源正,3-5V |
2 | GND | 電源地 |
3 | SCL | 串行時鐘輸入 |
4 | SDA | 串行地址和數(shù)據(jù)輸入/輸出 |
MLX90614是一種紅外溫度計,用于非接觸式溫度測量。紅外測溫是根據(jù)被測物體的紅外輻射能量來確定物體的溫度,不與被測物體接觸,具有不影響被測物體溫度分布場,溫度分辨率高、響應速度快、測溫范圍廣、不受測溫上限的限制、穩(wěn)定性好等特點。適合于汽車空調(diào)、室內(nèi)暖氣、家用電器、手持設備以及醫(yī)療設備應用等。
MLX90614的出廠校準溫度范圍很廣:環(huán)境溫度為-40°C——125°C,目標溫度為-70°C——380°C。測量值是傳感器視場中所有物體的平均溫度。在室溫下,MLX90614的標準精確度為±0.5°C。
?MLX90614由MLX81101紅外熱電堆傳感器和包括含有穩(wěn)壓電路、低噪聲放大器、A/D轉(zhuǎn)換器、DSP單元、脈寬調(diào)制電路及邏輯控制電路的MLX90302信號處理芯片構(gòu)成。
其工作原理為:紅外熱電堆傳感器輸出的溫度信號經(jīng)過內(nèi)部低噪聲、低失調(diào)的運算放大器(OPA)放大后經(jīng)過A/D轉(zhuǎn)換器(ADC)轉(zhuǎn)換為17位數(shù)字信號通過可編程FIR及IIR低通數(shù)字濾波器(即DSP)處理后輸出,輸出結(jié)果存儲在其內(nèi)部RAM存儲單元中。
MLX90614 是由內(nèi)部狀態(tài)機控制物體溫度和環(huán)境溫度的測量和計算,進行溫度后處理,并將結(jié)果通過 PWM 或是 SMBus 模式輸出。 ASSP 支持兩個 IR 傳感器。 (MLX90614xAx 只有一個 IR 傳感器) IR 傳感器的輸出通過增益可編程的低噪聲低失 調(diào)電壓放大器放大,經(jīng)過 Sigma Delta 調(diào)制器轉(zhuǎn)換為單一比特流并反饋給 DSP 做后續(xù)的處理。信號通過可編程的 (用 EEPROM 實現(xiàn)) FIR 和 IIR 低通濾波器以進一步減低輸入信號的帶寬從而達到所需的噪聲特性和刷新率。IIR 濾波器的輸出為測量結(jié)果并存于內(nèi)部 RAM 中,其中三個單元可被用到:一個是片內(nèi)溫度傳感器(片上 PTAT 或 PTC),其余兩個為 IR 傳感器。 基于以上測量結(jié)果,計算出對應的環(huán)境溫度 Ta 和物體溫度 To,兩個溫度分辨率都為 0.01 ?C。Ta 和 To 可通過兩種方式讀?。和ㄟ^兩線接口讀取 RAM 單元,(0.02°C 分辨率,固定范圍) 或者通過 PWM 數(shù)字模式輸出。 (10 位分辨率, 范圍可配置) 測量周期的最后一步為:測量所得 Ta 和 To 被重新調(diào)節(jié)為 PWM 所需的輸出分辨率,并且該數(shù)據(jù)存在 PWM 狀態(tài) 機的寄存器中,狀態(tài)機可以產(chǎn)生固定頻率和一定占空比來表示測量的數(shù)據(jù)。
通信協(xié)議(SMBus通信,類IIC通信)
單片機與MLX90614紅外測溫模塊之間通信的方式是“類IIC”通信,意思就是通信方式跟IIC通信方式很像但又不是IIC,它有另外一個名字叫做SMBus。SMBus (System Management Bus)是 1995 年由 intel 公司提出的一種高效同步串行總線,SMBus 只有兩根信號線:雙向數(shù)據(jù)線和時鐘信號線,容許 CPU 與各種外圍接口器件以串行方式進行通信、交換信息,既可以提高傳輸速度也可以減小器件的資源占用,另外即使在沒有SMBus 接口的單片機上也可利用軟件進行模擬。
代碼實現(xiàn)
STM32與模塊之間接線表
MLX90614 | STM32F103C8T6 |
VCC | VCC |
GND | GND |
SCL | PB8 |
SDA | PB9 |
- | PA9(USART1_ TX) |
- | PA10(USART1_RX) |
1.標準庫實現(xiàn)溫度采集
主函數(shù):
int main(void)
{
float Temperature=10;
char temStr[100] = "";
int i = 0; // 循環(huán)變量
delay_init(); // 延時函數(shù)初始化配置
uart_init(115200);
USART_SendData(USART1, 'A');
Mlx96014_Configuration();
/* Infinite loop */
while (1)
{
Temperature=SMBus_ReadTemp();
sprintf(temStr,"The Temperature is:%.2f\r\n",Temperature);
for(i=0;i<strlen(temStr);i++)
{
USART_SendData(USART1, temStr[i]);
delay_ms(1);
}
delay_ms(500);
}
}
mlx90614.c
/*******************************************************************************
* 文件名 : mlx90614.c
* 作 者 :
* 版 本 :
* 日 期 : 2015-08-07
* 描 述 : mlx90614函數(shù)
*******************************************************************************/
#include "stm32f10x.h"
#include "mlx90614.h"
/*******************************************************************************
* Function Name : Mlx90614_Configuration
* Description : Mlx90614_Configuration
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void Mlx96014_Configuration(void)
{
GPIO_InitTypeDef GPIO; //聲明一個結(jié)構(gòu)體變量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
// 溫度傳感器引腳配置
GPIO.GPIO_Pin = GPIO_Pin_9;//非接觸溫度傳感器SDA 連接PB9
GPIO.GPIO_Speed = GPIO_Speed_50MHz;//管腳頻率為50MHZ
GPIO.GPIO_Mode = GPIO_Mode_Out_OD;//輸出模式為
GPIO_Init(GPIOB,&GPIO);//初始化GPIOB寄存器
GPIO.GPIO_Pin = GPIO_Pin_8;//非接觸溫度傳感器SCL 連接PB8
GPIO.GPIO_Speed = GPIO_Speed_50MHz;//管腳頻率為50MHZ
GPIO.GPIO_Mode = GPIO_Mode_Out_OD;//輸出模式為
GPIO_Init(GPIOB,&GPIO);//初始化GPIOB寄存器
SDA_H;
SCL_H; //因為SMBus是下降沿觸發(fā)
}
/*******************************************************************************
* Function Name : SMBus_StartBit
* Description : Generate START condition on SMBus
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SMBus_StartBit(void)
{
SDA_H; // Set SDA line
SMBus_Delay(1); // Wait a few microseconds
SCL_H; // Set SCK line
SMBus_Delay(5); // Generate bus free time between Stop
SDA_L; // Clear SDA line
SMBus_Delay(10); // Hold time after (Repeated) Start
// Condition. After this period, the first clock is generated.
//(Thd:sta=4.0us min)
SCL_L; // Clear SCK line
SMBus_Delay(2); // Wait a few microseconds
}
/*******************************************************************************
* Function Name : SMBus_StopBit
* Description : Generate STOP condition on SMBus
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SMBus_StopBit(void)
{
SCL_L; // Clear SCK line
SMBus_Delay(5); // Wait a few microseconds
SDA_L; // Clear SDA line
SMBus_Delay(5); // Wait a few microseconds
SCL_H; // Set SCK line
SMBus_Delay(10); // Stop condition setup time(Tsu:sto=4.0us min)
SDA_H; // Set SDA line
}
/*******************************************************************************
* Function Name : SMBus_SendByte
* Description : Send a byte on SMBus
* Input : Tx_buffer
* Output : None
* Return : None
*******************************************************************************/
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;
}
/*******************************************************************************
* Function Name : SMBus_SendBit
* Description : Send a bit on SMBus
* Input : bit_out
* Output : None
* Return : None
*******************************************************************************/
void SMBus_SendBit(u8 bit_out)
{
if(bit_out==0)
{
SDA_L;
}
else
{
SDA_H;
}
SMBus_Delay(2); // Tsu:dat = 250ns minimum
SCL_H; // Set SCK line
SMBus_Delay(10); // High Level of Clock Pulse
SCL_L; // Clear SCK line
SMBus_Delay(10); // Low Level of Clock Pulse
// SMBUS_SDA_H(); // Master release SDA line ,
return;
}
/*******************************************************************************
* Function Name : SMBus_ReceiveBit
* Description : Receive a bit on SMBus
* Input : None
* Output : None
* Return : Ack_bit
*******************************************************************************/
u8 SMBus_ReceiveBit(void)
{
u8 Ack_bit;
SDA_H; //引腳靠外部電阻上拉,當作輸入
SCL_H; // Set SCL line
SMBus_Delay(2); // High Level of Clock Pulse
if (SMBUS_SDA_PIN)
{
Ack_bit=1;
}
else
{
Ack_bit=0;
}
SCL_L; // Clear SCL line
SMBus_Delay(4); // Low Level of Clock Pulse
return Ack_bit;
}
/*******************************************************************************
* Function Name : SMBus_ReceiveByte
* Description : Receive a byte on SMBus
* Input : ack_nack
* Output : None
* Return : RX_buffer
*******************************************************************************/
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;
}
/*******************************************************************************
* Function Name : SMBus_Delay
* Description : 延時 一次循環(huán)約1us
* Input : time
* Output : None
* Return : None
*******************************************************************************/
void SMBus_Delay(u16 time)
{
u16 i, j;
for (i=0; i<4; i++)
{
for (j=0; j<time; j++);
}
}
/*******************************************************************************
* Function Name : SMBus_ReadMemory
* Description : READ DATA FROM RAM/EEPROM
* Input : slaveAddress, command
* Output : None
* Return : Data
*******************************************************************************/
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表示接下來讀數(shù)據(jù)
{
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;
}
/*******************************************************************************
* Function Name : PEC_calculation
* Description : Calculates the PEC of received bytes
* Input : pec[]
* Output : None
* Return : pec[0]-this byte contains calculated crc value
*******************************************************************************/
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];
}
/*******************************************************************************
* Function Name : SMBus_ReadTemp
* Description : Calculate and return the temperature
* Input : None
* Output : None
* Return : SMBus_ReadMemory(0x00, 0x07)*0.02-273.15
*******************************************************************************/
float SMBus_ReadTemp(void)
{
return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_Ta)*0.02-273.15;
}
/*********************************END OF FILE*********************************/
?注意:
float SMBus_ReadTemp(void)
{
return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_Ta)*0.02-273.15;
}
測的是環(huán)境溫度,如果需要測量物體表面溫度。
#define RAM_TOBJ1 0x07 //To1 address in the eeprom 表面溫度
#define RAM_Ta 0x06 //Ta address in the eeprom 環(huán)境溫度
實現(xiàn)效果:
2.HAL庫實現(xiàn)溫度采集
?因為代碼封裝的較好,移植性較好,和標準庫代碼基本相似,只需要修改部分核心代碼。
修改片段:
#define SMBUS_SCK_H() HAL_GPIO_WritePin(GPIOB, SMBus_SCL_Pin, GPIO_PIN_SET)
#define SMBUS_SCK_L() HAL_GPIO_WritePin(GPIOB, SMBus_SCL_Pin, GPIO_PIN_RESET)
#define SMBUS_SDA_H() HAL_GPIO_WritePin(GPIOB, SMBus_SDA_Pin, GPIO_PIN_SET)
#define SMBUS_SDA_L() HAL_GPIO_WritePin(GPIOB, SMBus_SDA_Pin, GPIO_PIN_RESET)
#define SMBUS_SDA_PIN() HAL_GPIO_ReadPin(GPIOB,SMBus_SDA_Pin)
基本就可以實現(xiàn)數(shù)據(jù)采集了。
注意:
float SMBus_ReadTemp(void)
{
return (SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TaA)*0.02-273.15);
}
例子中測試的是物體溫度,物體表面溫度修改:
#define RAM_TOBJ1 0x07 // 物體表面溫度
#define RAM_TaA 0x06 // 環(huán)境溫度
這里需要需要注意的地方,CubeMX生成的代碼需要修改一下,不然不能實現(xiàn)采集功能。
推挽輸出
GPIO_MODE_OUTPUT_PP
修改成 開漏輸出模式
GPIO_MODE_OUTPUT_OD
實現(xiàn)效果:
?源碼下載鏈接:
STM32實現(xiàn)MLX90614非接觸測溫串口顯示(標準庫與HAL庫實現(xiàn))資源-CSDN文庫文章來源:http://www.zghlxwxcb.cn/news/detail-595377.html
吾芯電子工作室文章來源地址http://www.zghlxwxcb.cn/news/detail-595377.html
到了這里,關于STM32實現(xiàn)MLX90614非接觸測溫串口顯示(標準庫與HAL庫實現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!