STM32驱动MLX90640红外测温模块详解
STM32驱动MLX90640红外测温模块
简介
GYMCU90640 是一款低成本非接触红外点阵测温模块。其工作原理,是黑体辐射定律, 物体的温度越高,所发出的红外辐射 能力越强,经过芯片处理得到温度数据。此模块,有两种方式读取数据,即 串口(TTL 电平)或者 I2C(芯片本身)通信方式。该产品测温点阵数量多,像素高。能在一般的环境分辨出人体型。串口的波特率有 9600bps 115200bps和 460800bps,有连续输出与询问输出两种方式,可适应不同的工作环境。与所有的单片机及电脑连接。改模块还保留了MLX90640 芯片本身的 I2C 接口,把模块 PS 接 GND 或者 SET 点焊 接上,模块本身 MCU 不工作,可以经过 I2C 直接操作 MLX90640。
电气参数
测量范围 -40°~ 300°
分辨率0.1°
测量精度 ±2 °
重复精度 ±2 °
响应频率 8 HZ(460800bps)
工作电压 3~5 V
工作电流 42mA
工作温度 -20°~ 85°
储存温度 -40°~ 125°
串口通讯协议
(1)、串口通信参数(默认波特率值 115200 bps,可通过软件设定)
波特率:9600 bps 校验位:N 数据位:8 停止位:1
波特率:115200 bps 校验位:N 数据位:8 停止位:1
波特率:460800 bps 校验位:N 数据位:8 停止位:1
(2)、模块输出格式,每帧包含 1544 个字节(十六进制):
①.Byte 0: 0x5A 帧头标志
②.Byte 1: 0x5A 帧头标志
③.Byte 2: 0x02 数据量低 8 位
④.Byte 3: 0x06 数据量高 8 位
⑤.Byte 4: 0x00~0xFF 目标温度数据 1 低 8 位
⑥.Byte 5: 0x00~0xFF 目标温度数据 1 高 8 位
⑦.Byte 6: 0x00~0xFF 目标温度数据 2 低 8 位
⑧.Byte 7: 0x00~0xFF 目标温度数据 2 高 8 位
⑨.Byte xx: 0x00~0xFF 目标温度数据 xx 低 8 位
⑩.Byte xx: 0x00~0xFF 目标温度数据 xx 高 8 位
⑪.Byte1540: 0x00~0xFF MLX90640 自身温度低 8 位
⑫.Byte1541: 0x00~0xFF MLX90640 自身温度高 8 位
⑬. Byte1542: 0x00~0xFF 校验和低 8 位
⑭. Byte1543: 0x00~0xFF 检验和高 8 位
数据放大倍数:
温度均为放大 100 倍后输出;
数据解析:
例如一帧数据
<5A5A-0206-6E0E-690E-5A0E-XXXX-050E-8D0E-D540>
Byte0~ Byte1—0x5A0x5A 表示帧头;
Byte2~ Byte3—0x0206 表示数据量=0x06*256+0x02=1538 个温度数据(包括目
标数据和 MLX90640 自身温度数据)
Byte4~ Byte1539—表示上图中 768 个点的温度数据,输出顺序一次为
(Col 1,Row 1)—(Col 32,Row 1)— (Col 1,Row 2)—(Col 32,Row 2)—
(Col 1,Row XX)—(Col 32,Row XX)—(Col 1,Row 24)—(Col 32,Row 24)
注:(Col 1,Row 1)为上图中右上角开始
例子数据计算:
一帧数据
Byte1542— Byte1543 表示 前 771 个字的累加和,每个字为 16bit。
字 1=0x5A5A
字 2=0x0602(即数据量)
字 3=0x0E6E(即点 1 的温度数据)
⋮
字 770=0x0E05(即点 768 的温度数据)
字 771=0x0E8D(即 MLX90640 的温度数据)
则
校验和=字 1+字 2+字 3+字 XX+字 700+字 771= Byte1543*256+ Byte1542
具体参见附件的例程。
(4)、指令字节,由外部控制器发送至模块(十六进制)
发给模块的指令为四字节:
波特率设置指令:
9600 设置指令————0xA5+0x15+0x01+0xBB
115200 设置指令———0xA5+0x15+0x02+0xBC
460800 设置指令———0xA5+0x15+0x03+0xBD
模块更新频率设置指令:
0.5hz 设置指令———–0xA5+0x25+0x00+0xCA
1hz 设置指令———–0xA5+0x25+0x01+0xCB
2hz 设置指令———–0xA5+0x25+0x02+0xCC
4hz 设置指令———–0xA5+0x25+0x03+0xCD
8hz 设置指令———–0xA5+0x25+0x04+0xCE
自动/查询设置指令:
查询输出数据指令——-0xA5+0x35+0x01+0xDB
自动输出数据指令——-0xA5+0x35+0x02+0Xdc
发射率设置指令:0xA5 +0x45 +0xXX+sum(8bit 校验和)
例如:人体的发射率一般为 0.95,0xXX 为 0.95 的 100 倍,即 95=0x5f,
则责令为:0xA5+0x45+0x5F+0x49;
注:发射率最大为 1;即 0xXX 最大为 100=0x64;发射后,模块立即按照设
置的发射率计算目标温度。如需保存在 flash,请发送保存指令;
发射率查询指令:0xA5 +0x55+ 0x01+0xFB
模块返回帧:0x5A+0x5A+0xXX+sum(8bit 校验和)
0xXX 即为模块采用的发射率;
例如返回[5A5A5F13],则 0xXX=0x5F=95,即发射率为 95/100=0.95;
保存设置指令:
保存设置指令————-0xA5+0x65+0x01+0x0B
保存设置指令:表示将当前的波特率设置、模块更新频率设置、自动/查询
和发射率设置保存到 flash 中,重启后按照保存的设置运行。
接线
STM32 | USB-TTL | MLX90640 |
---|---|---|
3.3V | 3.3V | 3.3V |
GND | GND | GND |
PA3 | – | TX |
PA9 | RX | – |
代码
#include "main.h"
#include "stm32f4xx_hal.h"
#include "usart.h"
#include "gpio.h"
void SystemClock_Config(void);
uint8_t data_buf[1544];
int fputc(int ch,FILE *f)
{
uint8_t temp[1]= {ch};
HAL_UART_Transmit(&huart1,temp,1,2);
}
float myMap(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
int main(void)
{
/* USER CODE BEGIN 1 */
int16_t temp=0,rest_count=0;
float Temperature=0;
float min_temp=500,max_temp=0;
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2 , (uint8_t *)receive_buf,1544);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(stata!=1)
continue ;
stata =0;
if(CHeck(data_buf))
{
for(int i=0; i<768;)
{
temp=((int16_t)data_buf[i*2+1+4]<<8|data_buf[i*2+4]);
Temperature=(float)temp/100;
printf(" %.2f", Temperature);
i++;
if((i%32)==0&&i>0)
printf(" \r\n");
}
printf("\r\n");
for(uint16_t y=0; y<24; y++)
{
for(uint16_t x=4; x<64+4; x=x+2)
{
temp=((int16_t)data_buf[x+1+64*y]<<8|data_buf[x+64*y]);
Temperature=(float)temp/100;
if(Temperature>max_temp)
max_temp=Temperature;
if(Temperature<min_temp)
min_temp=Temperature;
if(rest_count>20)
{
min_temp=500;
max_temp=0;
rest_count=0;
}
float inv= myMap(Temperature,min_temp,max_temp,0.5,1);
if(inv>0.75)
printf("**");
else
printf("--");
}
printf("\r\n");
}
rest_count++;
printf("\r\n");
}
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
void _Error_Handler(char * file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
结果
串口调试助手输出温度数据:
用上位机测试结果:
总结
注意:上位机在发送波特率、更新率和查询/连续等指令后最后需发送保存指令,模块断电,重新上电生效。
作者:优信电子