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 */
    
    }
    

    结果

    串口调试助手输出温度数据:

    用上位机测试结果:

    总结

    注意:上位机在发送波特率、更新率和查询/连续等指令后最后需发送保存指令,模块断电,重新上电生效。

    作者:优信电子

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32驱动MLX90640红外测温模块详解

    发表回复