STM32CubeMX配置读取MLX90614(GY

您所在的位置:网站首页 mlx90614介绍 STM32CubeMX配置读取MLX90614(GY

STM32CubeMX配置读取MLX90614(GY

2023-11-23 06:34| 来源: 网络整理| 查看: 265

STM32F103单片机通过IIC控制MLX90614红外温度传感器

**MLX90614(gy906-BAA)**非接触红外温度传感器是一款性能和精度都较高的温度测量产品,在医疗,工业等领域应用较多;有四个引脚,使用SMBus协议,通过控制SDA、SCL引脚进行数据读取。工作电压为3.3V。 *

完整工程下载 产品配图

在这里插入图片描述

stm32cubemax 配置

在这里插入图片描述

串口温度测试:

在这里插入图片描述

电路连接说明: SDA引脚连接STM32F103c8t6单片机PB7,SCL引脚连接PB6引脚。 VCC连接3.3V引脚,GND连接单片机的3.3V对应的GND引脚。 因为IIC使用的是软模拟实现的引脚功能,所以用到了网上下载的标准库MLX90614.c与MLX90614.h文件 移植到stm32cubemax生成的工程里去,节省大家时间。

main.c 文件展示:

#include "main.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "mlx90614.h" #include "stdio.h" 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_USART1_UART_Init(); /* USER CODE BEGIN 2 */ printf("START"); mlx90614_init(); HAL_Delay(1000); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_Delay(1000); printf("%f",mlx90614_read_temp()); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }

MLX90614.h 文件展示:

#ifndef __MLX90614_H #define __MLX90614_H //#include "sys.h" #include "main.h" //==============================================MLX90614硬件接口================================================== #define MLX90614_IIC_CLK RCC_APB2Periph_GPIOB #define MLX90614_IIC_PORT GPIOB #define MLX90614_IIC_PIN_SCL GPIO_PIN_6 #define MLX90614_IIC_PIN_SDA GPIO_PIN_7 #define MLX90614_IIC_SCL PBout(6) #define MLX90614_IIC_SDA PBout(7) #define MLX90614_READ_SDA PBin(7) //输入SDA //==============================================MLX90614函数接口================================================== void mlx90614_init(void); float mlx90614_read_temp(void); void delay_usssss(int n); //==============================================MLX90614寄存器================================================== #define RAM 0x00 #define EEPROM 0x20 #define MODE 0x60 #define EXITMODE 0x61 #define READFLAG 0xf0 #define SLEEP 0xff #define RD 0x01 #define WR 0x00 #define AMBITEMPADDR 0x03 #define IR1ADDR 0x04 #define IR2ADDR 0x05 #define ENVITEMPADDR 0x06 #define OBJ1TEMPADDR 0x07 #define OBJ2TEMPADDR 0x08 #define TOBJMAXADDR 0x00 #define TOBJMINADDR 0x01 #define PWMCTRLADDR 0x02 #define TARANGEADDR 0x03 #define KEADDR 0x04 #define CONFIGADDR 0x05 #define SMBUSADDR 0x0e #define RES1ADDR 0x0f #define RES2ADDR 0x19 #define ID1ADDR 0x1c #define ID2ADDR 0x1d #define ID3ADDR 0x1e #define ID4ADDR 0x1f #define ACK_SUCCESS 0x01 #define ACK_FAIL 0x00 #define N 5 #endif

/--------------------- MLX90614.c 文件展示:

/*================================================================================================ // 文件功能:MlX90614的驱动文件 // 文件说明: // 文件类型: //------------------------------------------------------------------------------------------------ // 硬件平台:STM32F103C8T6 -cubemax // 软件平台:KEIL5 MDK //------------------------------------------------------------------------------------------------ // 开发组织: // 开发作者:heyque // 官方商城: //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // 更新时间:2021-05-12 //----------------------------------------------------------------------------------------------- // 待完善内容: ================================================================================================*/ #include "mlx90614.h" /*================================================================================================ // @函数名称: // @函数功能:SDA输出配置 // @函数说明: //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-07-11 heyque 新建 //==============================================================================================*/ /*================================================================================================ // @函数名称: // @函数功能:产生通讯开始信号 // @函数说明:MLX90614在SCK=1时,检测到SDA由1到0表示通信开始 //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_iic_start(void) { MLX90614_SDA_OUT(); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_SET); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_RESET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); delay_weimiao(5); } /*================================================================================================ // @函数名称: // @函数功能:产生通讯停止信号 // @函数说明:MLX90614在SCK=1时,检测到SDA由0到1表示通信结束 //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_iic_stop(void) { MLX90614_SDA_OUT(); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_RESET); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_SET); delay_weimiao(5); } /*================================================================================================ // @函数名称: // @函数功能:产生ACK应答 // @函数说明: //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_iic_ack(void) { HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); MLX90614_SDA_OUT(); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_RESET); delay_weimiao(2); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); } /*================================================================================================ // @函数名称: // @函数功能:产生NACK非应答 // @函数说明: //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_iic_no_ack(void) { HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); MLX90614_SDA_OUT(); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_SET); delay_weimiao(2); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); } /*================================================================================================ // @函数名称: // @函数功能:等待应答信号到来 // @函数说明: //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 1,接收应答失败 0,接收应答成功 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ uint8_t mlx90614_iic_wait_ack(void) { uint8_t tempTime=0; MLX90614_SDA_IN(); //SDA设置为输入 HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_SET); delay_weimiao(1); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); delay_weimiao(1); while(HAL_GPIO_ReadPin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA)==1) { tempTime++; if(tempTime>250) { mlx90614_iic_stop(); return 1; } } HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET);//时钟输出0 return 0; } /*================================================================================================ // @函数名称: // @函数功能:从RAM/EEPROM中读取一个字节数据 // @函数说明:从MLX90614中的指定地址读取一个字节数据,高位在前,低位在后 //------------------------------------------------------------------------------------------------ // @参数值: ack_nack:主机应答信号 // @返回值: dat: 读取的数据 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ uint8_t mlx90614_iic_read_byte(uint8_t ack) { uint8_t i,receive=0; MLX90614_SDA_IN();//SDA设置为输入 for(i=0;i uint8_t t; uint8_t s_ack=0; MLX90614_SDA_OUT(); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET);//拉低时钟开始数据传输 for(t=0;t s_ack = ACK_FAIL; } else { s_ack = ACK_SUCCESS; } return s_ack; } /*================================================================================================ // @函数名称: // @函数功能:mlx90614初始化 // @函数说明: //------------------------------------------------------------------------------------------------ // @参数值: 无 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin : PB7 */ GPIO_InitStruct.Pin = MLX90614_IIC_PIN_SCL|MLX90614_IIC_PIN_SCL; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA|MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); HAL_GPIO_Init(MLX90614_IIC_PORT, &GPIO_InitStruct); } /*================================================================================================ // @函数名称: // @函数功能:计算PEC包裹校验码,根据接收的字节计算PEC码 // @函数说明:计算传入数据的PEC码 //------------------------------------------------------------------------------------------------ // @参数值: pec[]:传入的数据 // n:传入数据个数 // @返回值: pec[0]:计算得到的PEC值 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ static uint8_t pec_cal(uint8_t pec[],uint16_t n) { unsigned char crc[6]; unsigned char Bitposition=47; unsigned char shift; unsigned char i; unsigned char j; unsigned char temp; do{ crc[5]=0; //载入 CRC数值 0x000000000107 crc[4]=0; crc[3]=0; crc[2]=0; crc[1]=0x01; crc[0]=0x07; Bitposition=47; //设置Bitposition的最大值为47 shift=0; //在传送的字节中找出第一个“1” i=5; //设置最高标志位 (包裹字节标志) j=0; //字节位标志,从最低位开始 while((pec[i]&(0x80>>j))==0 && (i>0)) { Bitposition--; if(j j=0x00; i--; } }//while语句结束,并找出Bitposition中为“1”的最高位位置 shift=Bitposition-8; //得到CRC数值将要左移/右移的数值“shift” //对CRC数据左移“shift”位 while(shift) { for(i=5;i //是 - 当前字节 + 1 temp=1; //否 - 当前字节 + 0 } //实现字节之间移动“1” else { temp=0; } crc[i] HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); delay_weimiao(1500); //大于1.44ms HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); } /*================================================================================================ // @函数名称: // @函数功能:退出睡眠模式 // @函数说明:保持SCK高电平后,SDA持续至少33ms低电平, // 在退出睡眠模式后需要间隔250ms(典型值)才输出数据。 //------------------------------------------------------------------------------------------------ // @参数值:无 // @返回值:无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void eixt_sleep(void) { HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_SET); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_SET); delay_weimiao(5); HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_RESET); HAL_Delay(35); //大于33ms退出睡眠模式 HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SDA, GPIO_PIN_SET); HAL_Delay(260); //大于250ms开始输出数据 } /*================================================================================================ // @函数名称: // @函数功能:清除EEPROM指定单元的数据 // @函数说明:在向EEPROM中写入数据之前必须先清除内存单元中的数据,也就是全部写入0 //------------------------------------------------------------------------------------------------ // @参数值: saddr:从机地址 // cmd:发送命令 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_clear_eeprom(uint8_t saddr,uint8_t cmd) { uint8_t retry = 10; //失败重复次数 uint8_t s_ack = 0; HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); while(retry--) { mlx90614_iic_start(); //发送起始位 s_ack = mlx90614_iic_write_byte((saddr s_ack = 0; s_ack = mlx90614_iic_write_byte(0x00); //发送低字节 if(s_ack == ACK_SUCCESS) { s_ack = 0; s_ack = mlx90614_iic_write_byte(0x00); //发送高字节 if(s_ack == ACK_SUCCESS) { s_ack = 0; s_ack = mlx90614_iic_write_byte(0x6f); //发送PEC字节 if(s_ack == ACK_SUCCESS) { mlx90614_iic_stop(); //发送停止位 break; //退出循环 } else goto stop_ce; } else goto stop_ce; } else goto stop_ce; } else goto stop_ce; } else goto stop_ce; stop_ce: mlx90614_iic_stop(); //发送停止位,芯片接收失败 } HAL_Delay(5); //擦除完成至少等待5ms } /*================================================================================================ // @函数名称: // @函数功能:读EEPROM指定单元的数据 // @函数说明:从指定从机读取指定EEPROM地址的数据 //------------------------------------------------------------------------------------------------ // @参数值: saddr:从机地址 // cmd:读取EEPROM地址 // @返回值: Data:读取数据 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ uint16_t mlx90614_read_eeprom(uint8_t saddr,uint8_t cmd) { uint8_t retry = 10; uint8_t s_ack; uint16_t Data; uint8_t DataL; //接收数据低字节 uint8_t DataH; //接收数据高字节 uint8_t PEC; //接收的PEC值 uint8_t Pecreg; //计算的PEC值 uint8_t buf[6]; //存储已接收数据的缓存 while(retry--) { mlx90614_iic_start(); //发送起始位 s_ack = mlx90614_iic_write_byte((saddr s_ack = 0; mlx90614_iic_start(); //重新发送起始位 s_ack = mlx90614_iic_write_byte((saddr break; } } else goto stop_re; } else goto stop_re; } else goto stop_re; stop_re: mlx90614_iic_stop(); } Data = (DataH mlx90614_iic_start(); //发送起始位 s_ack = mlx90614_iic_write_byte((saddr s_ack = 0; s_ack = mlx90614_iic_write_byte(DataL); //发送低字节 if(s_ack == ACK_SUCCESS) { s_ack = 0; s_ack = mlx90614_iic_write_byte(DataH); //发送高字节 if(s_ack == ACK_SUCCESS) { s_ack = 0; s_ack = mlx90614_iic_write_byte(Pecreg); //发送PEC码 if(s_ack == ACK_SUCCESS) { mlx90614_iic_stop(); //发送停止位 break; //退出循环 } else goto stop_we; } else goto stop_we; } else goto stop_we; } else goto stop_we; } else goto stop_we; stop_we: mlx90614_iic_stop(); } HAL_Delay(5); //写入之后等待5ms } /*================================================================================================ // @函数名称: // @函数功能:设定MLX90614器件地址 // @函数说明:器件从地址可以通过向EEPROM的SMBus地址0x0E中写入来进行设定。为了给从器件设定地址,必 // 须先以0x00+Wr当作从地址开始,当主机发送此命令,MLX90614总是会反馈并忽略掉内部芯片 // 编码信息。向EEPROM写入数据前需要清除原来的数据,就是向修改单元写入0x0000,擦除之后 // 需要等待5ms才可以重新写入数据,修改地址时写入的地址高字节MLX90614会忽略.修改之后需 // 要重新将MLX90614的电源断开重启。 //------------------------------------------------------------------------------------------------ // @参数值: soaddr:从机旧地址 // snaddr:从机新地址 // @返回值: 无 //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 heyque 新建 //==============================================================================================*/ void mlx90614_set_addr(uint8_t soaddr,uint8_t snaddr) { // uint8_t cmd = EEPROM|SMBUSADDR; // uint8_t DataL = snaddr; // uint8_t DataH = 0x00; // EEPROM_WRITE(snaddr,cmd,0x00,0x00); // EEPROM_WRITE(snaddr,cmd,DataL,DataH); } /*================================================================================================ // @函数名称: // @函数功能:读MLX90614的RAM中内容 // @函数说明:主要读取三个,环境温度,物体温度1,物体温度2 // 器件从地址可以通过向EEPROM的SMBus地址0x0E中写入来进行设定。 //------------------------------------------------------------------------------------------------ // @参数值: saddr:从机地址,7位地址,任何MLX90614都会对0x00地址作出反应 // cmd:存放温度的寄存器地址 // @返回值: Data:读取出来的数值。SA(write) - Command - SA(read) - LSByte - MSByte - PEC //------------------------------------------------------------------------------------------------ // @修改日志:2021-05-12 冯奇 新建 //==============================================================================================*/ static uint16_t mlx90614_read_ram(uint8_t saddr,uint8_t cmd) { uint16_t Data; uint8_t DataL; //接收数据低字节 uint8_t DataH; //接收数据高字节 uint8_t PEC; uint8_t retry = 10; //失败重复次数 uint8_t s_ack = 0; uint8_t Pecreg; //计算的PEC值 uint8_t buf[6]; //存储已接收数据的缓存 HAL_GPIO_WritePin(MLX90614_IIC_PORT, MLX90614_IIC_PIN_SCL, GPIO_PIN_RESET); while(retry--) { mlx90614_iic_start(); //发送起始位 s_ack = mlx90614_iic_write_byte((saddr s_ack = 0; mlx90614_iic_start(); //重新发送起始位 s_ack = mlx90614_iic_write_byte((saddr break; //退出循环 } } else goto stop_rr; } else goto stop_rr; } else goto stop_rr; stop_rr: mlx90614_iic_stop(); //发送停止位,芯片接收失败 } PEC = PEC+1; Data = (DataH


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3