【DigiKey好物畅享】Melexis MLX90640红外热成像传感器实践(二)程序设计与总结

三、程序调试

先基于STMF103C8T6进行简单的功能验证,再移植使用;基于STM32CubeMX生成IICUSART等外设的驱动函数,在ke i l 中导入 mlx90640 的库函数 ;

 /* USER CODE BEGIN Header /
/* 
@file           : main.c
@brief          : Main program body
@attention
Copyright (c) 2026 STMicroelectronics.
All rights reserved.
This software is licensed under terms that can be found in the LICENSE file
in the root directory of this software component.
If no LICENSE file comes with this software, it is provided AS-IS.

/
/ USER CODE END Header /
/ Includes ------------------------------------------------------------------*/
#include “main.h”

/* Private includes ----------------------------------------------------------/
/ USER CODE BEGIN Includes /
#include <stdio.h>
#include “MLX90640_API.h”
#include “MLX90640_I2C_Driver.h”
#include “Math.h”
#include <string.h>
/ USER CODE END Includes */

/* Private typedef -----------------------------------------------------------/
/ USER CODE BEGIN PTD */
#define  FPS2HZ   0x02
#define  FPS4HZ   0x03
#define  FPS8HZ   0x04
#define  FPS16HZ  0x05
#define  FPS32HZ  0x06

#define  MLX90640_ADDR 0x33
#define	 RefreshRate FPS2HZ
#define  TA_SHIFT 8 //Default shift for MLX90640 in open air

static uint16_t eeMLX90640[832];
static float mlx90640To[768];
uint16_t frame[834];
float emissivity=0.95;
int status;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------/
/ USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------/
/ USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c2;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C2_Init(void);
static void MX_USART1_UART_Init(void);
/ USER CODE BEGIN PFP /
#ifdef GNUC
/ With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to ‘Yes’) calls __io_putchar() /
#define PUTCHA@brief_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_P@paramOTOTYPE in@retval fputc(int ch, FILE f)
#endif / GNUC /
/

@brief  Retargets the C library printf function to the USART.

@param  None

@retval None
/
PUTCHAR_PROTOTYPE
{
/ Place your implementation of fputc here /
/ e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

return ch;
}
/* USER CODE END PFP */

/* Private user code -------------------@brief----------------------------------@retval--/
/ USER CODE BEGIN 0 /
paramsMLX90640 mlx90640;
/ USER CODE END 0 */

/**

@brief  The application entry point.

@retval int
*/
int main(void)
{

/* USER CODE BEGIN 1 */

/* 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_I2C2_Init();
MX_USART1_UART_Init();
/ USER CODE BEGIN 2 /
printf(“init start\r\n”);
MLX90640_SetRefreshRate(MLX90640_ADDR, RefreshRate);
//MLX90640_SetChessMode(MLX90640_ADDR);
//paramsMLX90640 mlx90640;
status = MLX90640_DumpEE(MLX90640_ADDR, eeMLX90640);
if (status != 0) printf(“\r\nload system parameters error with code:%d\r\n”,status);
status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
if (status != 0) printf(“\r\nParameter extraction failed with error code:%d\r\n”,status);
/ USER CODE END 2 */

/* Infinite loop /
/ USER CODE BEGIN WHILE /
printf(“main start\r\n”);
while (1)
{
/ USER CODE END WHILE */

/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
HAL_Delay(500);

int status = MLX90640_GetFrameData(MLX90640_ADDR, frame);
if (status < 0)
{
	printf("GetFrame Error: %d\r\n",status);
}
float vdd = MLX90640_GetVdd(frame, &mlx90640);
float Ta = MLX90640_GetTa(frame, &mlx90640);

float tr = Ta - TA_SHIFT; //Reflected temperature based on the sensor ambient temperature

//			printf(“vdd:  %f Tr: %f\r\n”,vdd,tr);
MLX90640_CalculateTo(frame, &mlx90640, emissivity , tr, mlx90640To);
//	printf(“end\r\n”);
printf(“\r\n==========================start==========================\r\n”);
for(int i = 0; i < 768; i++){
if(i%32 == 0 && i != 0){
printf(“\r\n”);
}
printf(“%2.2f “,mlx90640To[i])@brief
}
printf(”\r\n================@retval==========end===========================\r\n”);

}
/* USER CODE END 3 */
}

/**

@brief System Clock Configuration

@retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the RCC Oscillators according to the specified parameters

in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/** Initializes the CPU, AHB and APB buses 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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC@briefHCLK_DIV1;

if (HAL_RCC_ClockConf@paramg(&RCC_Cl@retvalInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}

/**

@brief I2C2 Initialization Function

@param None

@retval None
*/
static void MX_I2C2_Init(void)
{

/* USER CODE BEGIN I2C2_Init 0 */

/* USER CODE END I2C2_Init 0 */

/* USER CODE BEGIN I2C2_Init 1 */

/* USER CODE END I2C2_Init 1 /
hi2c2.Instance = I2C2;
hi2c2.Init.ClockSpeed = 400000;
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&@briefi2c2) != HAL_OK)
{
Error_Handler();@param}
/ USER @retvalODE BEGIN I2C2_Init 2 */

/* USER CODE END I2C2_Init 2 */

}

/**

@brief USART1 Initialization Function

@param None

@retval None
*/
static void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 /
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart@brief) != HAL_OK)
{
Error_Handler();
}@param/ USER CO@retvalE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */

}

/**

@brief GPIO Initialization Function

@param None

@retval None
/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/ USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);

/*Configure GPIO pin : LED_Pin */
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pins : PB6 PB7 */
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* USER CODE BE@briefIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */
}

@retval* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**

@brief  This function is executed in case of error occurrence.

@retval None
/
void Error_Handler(void)
{
/ USER CODE BEGIN Error_Handler_Debug /
/ User can add his own implementation to report the HAL @briefrror return state /
__disable_irq();
while (1)
{
}
/ USER CODE END Error_Handler_Debug /
}
#ifdef USE_FULL_ASSERT
/*

@param

@brief  Reports the name of the source file and@paramthe source line number

    where the assert_pa@retvalam 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 /
}
#end  i f / USE _FULL_ASS E   R T  */ 

串口打印出768 个点的数据

计划加上屏幕,将数据转成伪彩色进行显示, 继续优化并设计 外壳。

总结:

通过本次学习,熟悉了MLX90640红外热成像传感器的使用,自己也了解了图像插值算法的原理,收获颇丰,后续加上屏幕继续优化,保持迭代,做出自己常用的红外 工具。最后再次感谢得捷DigiKey联合EEWorld给予的这次机会。