当前位置:网站首页>STM32F1读取MLX90632非接触式红外温度传感器
STM32F1读取MLX90632非接触式红外温度传感器
2022-07-30 10:38:00 【荻夜】
MLX90632 简介
MLX90632是一个小型SMD SFN封装中的非接触式红外温度传感器,可实现高精度非接触式温度测量,。该装置在出厂时使用存储在EEPROM存储器中的校准常数进行校准。环境温度和目标温度可根据这些校准常数和测量数据进行计算。
MLX90632在工厂进行校准,环境温度范围为-20至85摄氏度,目标温度范围为-20至200摄氏度。测量值是传感器视野内所有物体的平均温度。当传感器处于热平衡和恒温条件下(传感器组件之间无温差),应用程序设计者必须了解这些精度是有保证的,并且是可以实现的。
温度计的准确度可能会受到封装内温度差异的影响,原因包括(除其他外):传感器后面的热电子元件、传感器后面或旁边的加热器/冷却器,或靠近传感器的热/冷物体,不仅加热温度计中的传感元件,还加热温度计封装。
MLX90632的一个主要优点是通过内部测量算法,将传感器组件周围这些温差的测量效果降至最低。同样,局部热变化(如空气中的湍流)不会在热电堆的输出信号中产生热噪声。但是,有些极端情况会影响传感器。
MLX90632的典型电源电压为3.3V,与芯片的通信是由I 2 C在快速模式下完成的。通过I 2 C,外部微控制器可以访问以下块:用于测量数据的RAM存储器用于存储微调值、校准常数和设备/测量设置的EEPROM寄存器,以根据该数据控制传感器,外部微控制器可以计算目标温度,如果需要,还可以计算传感器温度。
传感器中集成了一个光学滤光片(长波通),可切断可见光和近红外辐射通量,以提供环境光抗扰度。该滤光片的波长通带为2~14μm。
其特性主要有:
- 高温环境下精准稳定的工作
- 采用 3mm x 3mm x 1mm DFN 封装,无需采用体积庞大的 TO 罐封装
- 消费级:测量物体温度为 -20 °C 至 200 °C,精度±1 ℃;医疗级:测量物体温度为-20 °C 至 100 °C,人体温度测量精度高达±0.2 °C
- 使用 I2C 数字接口进行出厂校准,50° 的视场角
- 工作温度范围: -20 °C 至 85 °C
MLX90632 不同型号的异同
| 型号 | MLX90632-BCB-000 | MLX90632-DCB-000 | MLX90632-DCB-100 |
|---|---|---|---|
| 准确性 | 标准精度 | 医用级精度 | 医用级精度 |
| I2C电压等级 | 3V3 | 1V8 | 1V8 |
| 电源电压范围 | 3-5V DC(模块带低压差稳压) |
|---|---|
| 能耗 | 9.2µA(典型值)12µA(最大值) |
| 温度工作范围 | -20°C - 85°C |
| 输出信号 | I2C数字接口 |
PS: 传感器型号描述:

使用STM32F1单片机驱动MLX90632
- bsp_mlx90632.c 文件
/******************************************************************************* * Filename: bsp_mlx90632.c * Revised: All copyrights reserved to Roger. * Date: 2020-10-17 * Revision: v1.0 * Writer: Roger-WY. * * Description: 非接触式红外温度传感器模块驱动(数字式) * * * Notes: https://www.melexis.com/zh/product/MLX90632/MLX90632 * All copyrights reserved to Roger-WY *******************************************************************************/
#include "bsp_mlx90632.h"
#include <math.h>
//----------------------------------------------------------------------------//
#define MLX90632_I2C_SCL_RCC RCC_APB2Periph_GPIOC
#define MLX90632_I2C_SCL_PIN GPIO_Pin_4 /* 连接到SCL时钟线的GPIO */
#define MLX90632_I2C_SCL_PORT GPIOC
#define MLX90632_I2C_SDA_RCC RCC_APB2Periph_GPIOC
#define MLX90632_I2C_SDA_PIN GPIO_Pin_5 /* 连接到SDA数据线的GPIO */
#define MLX90632_I2C_SDA_PORT GPIOC
/* 定义读写SCL和SDA的宏 */
#define MLX90632_I2C_SCL_1() MLX90632_I2C_SCL_PORT->BSRR = MLX90632_I2C_SCL_PIN /* SCL = 1 */
#define MLX90632_I2C_SCL_0() MLX90632_I2C_SCL_PORT->BRR = MLX90632_I2C_SCL_PIN /* SCL = 0 */
#define MLX90632_I2C_SDA_1() MLX90632_I2C_SDA_PORT->BSRR = MLX90632_I2C_SDA_PIN /* SDA = 1 */
#define MLX90632_I2C_SDA_0() MLX90632_I2C_SDA_PORT->BRR = MLX90632_I2C_SDA_PIN /* SDA = 0 */
#define MLX90632_I2C_SDA_READ() ((MLX90632_I2C_SDA_PORT->IDR & MLX90632_I2C_SDA_PIN) != 0) /* 读SDA口线状态 */
#define MLX90632_I2C_SCL_READ() ((MLX90632_I2C_SCL_PORT->IDR & MLX90632_I2C_SCL_PIN) != 0) /* 读SCL口线状态 */
#define MLX90632_DELAY_MS(a) bsp_DelayNms(a);
//----------------------------------------------------------------------------//
#define POW10 10000000000LL
/* 灵敏度 */
static double emissivity = 0.0;
stMlx90632CalibraParTypeDef stMlxCalibraPar;
//============================================================================//
/* ******************************************************************************** * 函 数 名: Mlx90632_i2c_Delay * 功能说明: I2C总线位延迟,最快400KHz * 形 参: 无 * 返 回 值: 无 ******************************************************************************** */
static void Mlx90632_i2c_Delay(void)
{
volatile uint8_t i;
for(i = 0; i < 50; i++);
}
static void Mlx90632_i2c_Start(void)
{
/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
MLX90632_I2C_SDA_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SDA_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_0();
// Mlx90632_i2c_Delay();
}
/******************************************************************************* * 名 称: i2c_Stop * 功 能: CPU发起I2C总线停止信号 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: 停止时序 * SCL _____/ˉˉˉˉˉˉˉ * SDA _________/ˉˉˉˉˉ * | | * STOP *******************************************************************************/
static void Mlx90632_i2c_Stop(void)
{
/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SDA_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SDA_1();
// Mlx90632_i2c_Delay();
}
/******************************************************************************* * 名 称: i2c_WaitAck * 功 能: CPU产生一个时钟,并读取器件的ACK应答信号 * 入口参数: 无 * 出口参数: 返回0表示正确应答,1表示无器件响应 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static uint8_t Mlx90632_i2c_WaitAck(void)
{
uint8_t re;
uint8_t TimeOutCnt = 20; /* 超时计数器 */
MLX90632_I2C_SDA_1(); /* CPU释放SDA总线 */
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
Mlx90632_i2c_Delay();
while(TimeOutCnt --)
{
if(MLX90632_I2C_SDA_READ()) /* CPU读取SDA口线状态 */
{
re = 1;
}
else
{
re = 0;
}
}
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
return re;
}
/******************************************************************************* * 名 称: i2c_Ack * 功 能: CPU产生一个ACK信号 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static void Mlx90632_i2c_Ack(void)
{
MLX90632_I2C_SDA_0(); /* CPU驱动SDA = 0 */
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1(); /* CPU产生1个时钟 */
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SDA_1(); /* CPU释放SDA总线 */
}
/******************************************************************************* * 名 称: i2c_NAck * 功 能: CPU产生1个NACK信号 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static void Mlx90632_i2c_NAck(void)
{
MLX90632_I2C_SDA_1(); /* CPU驱动SDA = 1 */
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1(); /* CPU产生1个时钟 */
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
}
/******************************************************************************* * 名 称: bsp_InitI2C * 功 能: 配置I2C总线的GPIO,采用模拟IO的方式实现 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2018-06-29 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static void Mlx90632_InitI2C(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(MLX90632_I2C_SCL_RCC | MLX90632_I2C_SDA_RCC, ENABLE); /* 打开GPIO时钟 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出模式 */
GPIO_InitStructure.GPIO_Pin = MLX90632_I2C_SCL_PIN;
GPIO_Init(MLX90632_I2C_SCL_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = MLX90632_I2C_SDA_PIN;
GPIO_Init(MLX90632_I2C_SDA_PORT, &GPIO_InitStructure);
/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
Mlx90632_i2c_Stop();
}
/******************************************************************************* * 名 称: i2c_SendByte * 功 能: CPU向I2C总线设备发送8bit数据 * 入口参数: _ucByte : 等待发送的字节 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static void Mlx90632_i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先发送字节的高位bit7 */
for(i = 0; i < 8; i++)
{
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
if(_ucByte & 0x80)
{
MLX90632_I2C_SDA_1();
}
else
{
MLX90632_I2C_SDA_0();
}
_ucByte <<= 1; /* 左移一个bit */
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
}
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
}
/******************************************************************************* * 名 称: Mlx90632_i2c_ReadByte * 功 能: CPU从I2C总线设备读取8bit数据 * 入口参数: 无 * 出口参数: 读到的数据 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static uint8_t Mlx90632_i2c_ReadByte(void)
{
uint8_t i;
uint8_t value;
/* 读到第1个bit为数据的bit7 */
value = 0;
for(i = 0; i < 8; i++)
{
value <<= 1;
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
if(MLX90632_I2C_SDA_READ())
{
value++;
}
}
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
return value;
}
//============================================================================//
/******************************************************************************* * 名 称: bsp_Mlx90632Init * 功 能: Mlx90632传感器的初始化 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY. * 创建日期: 2018-08-08 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632Init(void)
{
int8_t ucError = 0;
Mlx90632_InitI2C();
bsp_Mlx90632ReadCalibraParInit(&stMlxCalibraPar);
ucError = bsp_Mlx90632ReadCalibraParFromEeprom(&stMlxCalibraPar);
return (ucError);
}
/******************************************************************************* * 名 称: bsp_Mlx90632WriteReg * 功 能: 对寄存器写值 * 入口参数: devAddr:设备地址 regAddr:寄存器地址 data:写入寄存器的值 * 出口参数: 读到的数据 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632WriteReg(uint8_t devAddr, uint16_t regAddr, uint16_t data)
{
uint8_t ucAck = 0;
uint8_t sendBuffer[5] = {
0}; //used to save the data to send
sendBuffer[0] = devAddr << 1;
sendBuffer[1] = (uint8_t)(regAddr >> 8);
sendBuffer[2] = (uint8_t)regAddr;
sendBuffer[3] = (uint8_t)(data >> 8);
sendBuffer[4] = (uint8_t)data;
Mlx90632_i2c_Start();
for(uint8_t i = 0; i < 5; i ++)
{
Mlx90632_i2c_SendByte(sendBuffer[i]);
ucAck = Mlx90632_i2c_WaitAck();
if(ucAck) /* 如果Mlx90632,没有应答 */
{
goto cmd_fail; /* 器件无应答 */
}
}
/* 发送I2C总线停止信号 */
Mlx90632_i2c_Stop();
return 0; /* 执行成功 */
cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
Mlx90632_i2c_Stop();
return -1;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadReg * 功 能: 从寄存器里读值 * 入口参数: devAddr:设备地址 regAddr:寄存器地址 ppBuf:读取寄存器值的缓存区 nBytes:读取寄存器的字节数 * 出口参数: 读到的数据 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632ReadReg(uint8_t devAddr, uint16_t regAddr, uint8_t* ppBuf, uint8_t nBytes)
{
uint8_t ucAck = 0;
uint8_t ValBuf[6] = {
0};
uint8_t prcRegVal = 0;
uint8_t i = 0;
ValBuf[0] = devAddr << 1;
ValBuf[1] = (uint8_t)(regAddr >> 8);
ValBuf[2] = (uint8_t)regAddr;
ValBuf[3] = (devAddr << 1) | 0x01;
Mlx90632_i2c_Start();
for(i = 0; i < 3; i++)
{
Mlx90632_i2c_SendByte(ValBuf[i]);
ucAck = Mlx90632_i2c_WaitAck();
if(ucAck) /* 如果没有应答 */
{
goto cmd_fail; /* 器件无应答 */
}
}
//------------------------------------------------------------------------//
Mlx90632_i2c_Start();
Mlx90632_i2c_SendByte(ValBuf[3]);
ucAck = Mlx90632_i2c_WaitAck();
if(ucAck) /* 如果没有应答 */
{
goto cmd_fail; /* 器件无应答 */
}
while(nBytes)
{
*ppBuf = Mlx90632_i2c_ReadByte();
if(nBytes == 1)
Mlx90632_i2c_NAck();
else
Mlx90632_i2c_Ack();
nBytes--;
ppBuf++;
}
/* 发送I2C总线停止信号 */
Mlx90632_i2c_Stop();
return 0;
cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
Mlx90632_i2c_Stop();
return -1;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadWord * 功 能: 从寄存器里读一个字(16-bit) * 入口参数: regAddr:寄存器地址 value:读取寄存器值的缓存区 * 出口参数: 0:读取成功 其他值,读取失败 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632ReadWord(uint16_t regAddr, uint16_t* value)
{
int8_t ret = 0;
uint8_t buf[2] = {
0};
ret = bsp_Mlx90632ReadReg(MLX90632_ADDR, regAddr, buf, 2);
*value = buf[1] | (buf[0] << 8);
return ret;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadDoubleWord * 功 能: 从寄存器里读双字(32-bit) * 入口参数: regAddr:寄存器地址 value:读取寄存器值的缓存区 * 出口参数: 0:读取成功 其他值,读取失败 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632ReadDoubleWord(uint16_t regAddr, uint32_t* value)
{
int8_t ret = 0;
uint8_t buf[4] = {
0};
ret = bsp_Mlx90632ReadReg(MLX90632_ADDR, regAddr, buf, 4);
*value = buf[2] << 24 | buf[3] << 16 | buf[0] << 8 | buf[1];
return ret;
}
/******************************************************************************* * 名 称: bsp_Mlx90632WriteWord * 功 能: 往寄存器里写入一个字(16-bit) * 入口参数: regAddr:寄存器地址 value:读取寄存器值的缓存区 * 出口参数: 0:读取成功 其他值,读取失败 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632WriteWord(uint16_t regAddr, uint16_t data)
{
int8_t ret = 0;
ret = bsp_Mlx90632WriteReg(MLX90632_ADDR, regAddr, data) ;
return (ret);
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadCalibraParInit * 功 能: 校准参数初始化,如果eeprom的校准参数读出来为空,就是使用此默认值 * 入口参数: pPar:校准参数结构体指针 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
void bsp_Mlx90632ReadCalibraParInit(stMlx90632CalibraParTypeDef* pPar)
{
pPar->PR = 0x00587f5b;
pPar->PG = 0x04a10289;
pPar->PT = 0xfff966f8;
pPar->PO = 0x00001e0f;
pPar->Ea = 4859535;
pPar->Eb = 5686508;
pPar->Fa = 53855361;
pPar->Fb = 42874149;
pPar->Ga = -14556410;
pPar->Ha = 16384;
pPar->Hb = 0;
pPar->Gb = 9728;
pPar->Ka = 10752;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadCalibraParFromEeprom * 功 能: 从传感器内部EEPROM中读取校准参数 * 入口参数: pPar:校准参数结构体指针 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Mlx90632ReadCalibraParFromEeprom(stMlx90632CalibraParTypeDef* pPar)
{
int8_t ret = 0;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_R, (uint32_t*)&pPar->PR);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_G, (uint32_t*)&pPar->PG);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_O, (uint32_t*)&pPar->PO);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_T, (uint32_t*)&pPar->PT);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Ea, (uint32_t*)&pPar->Ea);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Eb, (uint32_t*)&pPar->Eb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Fa, (uint32_t*)&pPar->Fa);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Fb, (uint32_t*)&pPar->Fb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Ga, (uint32_t*)&pPar->Ga);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Gb, (uint16_t*)&pPar->Gb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Ha, (uint16_t*)&pPar->Ha);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Hb, (uint16_t*)&pPar->Hb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Ka, (uint16_t*)&pPar->Ka);
if(ret < 0)
return ret;
return 0;
}
/******************************************************************************* * 名 称: bsp_Mlx90632StartMeasurement * 功 能: 触发传感器开始测量,但是只是触发测量周期,等待数据准备就绪,它不读取任何内容,只是触发并等待完成。 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: 此处超时等待是阻塞的 *******************************************************************************/
int bsp_Mlx90632StartMeasurement(void)
{
int ret, tries = 100;
uint16_t reg_status;
ret = bsp_Mlx90632ReadWord(MLX90632_REG_STATUS, ®_status);
if(ret < 0)
return ret;
ret = bsp_Mlx90632WriteWord(MLX90632_REG_STATUS, reg_status & (~MLX90632_STAT_DATA_RDY));
if(ret < 0)
return ret;
while(tries-- > 0)
{
ret = bsp_Mlx90632ReadWord(MLX90632_REG_STATUS, ®_status);
if(ret < 0)
return ret;
if(reg_status & MLX90632_STAT_DATA_RDY)
break;
/* minimum wait time to complete measurement * should be calculated according to refresh rate * atm 10ms - 11ms */
//usleep(10000, 11000);
MLX90632_DELAY_MS(10); //提供延时函数,此处延时10ms左右
}
if(tries < 0)
{
// data not ready
return -ETIMEDOUT;
}
return (reg_status & MLX90632_STAT_CYCLE_POS) >> 2;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ChannelNewSelect * 功 能: 根据 bsp_Mlx90632StartMeasurement 的返回值,获取通道的顺序。 * 入口参数: ret:bsp_Mlx90632StartMeasurement 的返回值 *channel_new:指向存储新通道值的内存位置的指针 *channel_new:指向存储旧通道值的内存位置的指针 * 出口参数: 0:正常 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: 如果返回值不是1/2 则不分配通道序列 *******************************************************************************/
int32_t bsp_Mlx90632ChannelNewSelect(int32_t ret, uint8_t* channel_new, uint8_t* channel_old)
{
switch(ret)
{
case 1:
*channel_new = 1;
*channel_old = 2;
break;
case 2:
*channel_new = 2;
*channel_old = 1;
break;
default:
return -EINVAL;
}
return 0;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadTempAmbientRaw * 功 能: 读取环境原始旧值和新值 * 入口参数: ambient_new_raw:原始环境温度新值 ambient_old_raw:原始环境温度旧值 * 出口参数: 0:正常 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int32_t bsp_Mlx90632ReadTempAmbientRaw(int16_t* ambient_new_raw, int16_t* ambient_old_raw)
{
int32_t ret;
uint16_t read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_3(1), &read_tmp);
if(ret < 0)
return ret;
*ambient_new_raw = (int16_t)read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_3(2), &read_tmp);
if(ret < 0)
return ret;
*ambient_old_raw = (int16_t)read_tmp;
return ret;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadTempObjectRaw * 功 能: 读取对象原始温度新值和旧值 * 入口参数: start_measurement_ret: 返回值 object_new_raw:物体原始温度新值 object_old_raw:物体原始温度旧值 * 出口参数: 0:正常 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int32_t bsp_Mlx90632ReadTempObjectRaw(int32_t start_measurement_ret,
int16_t* object_new_raw, int16_t* object_old_raw)
{
int32_t ret;
uint16_t read_tmp;
int16_t read;
uint8_t channel, channel_old;
ret = bsp_Mlx90632ChannelNewSelect(start_measurement_ret, &channel, &channel_old);
if(ret != 0)
return -EINVAL;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_2(channel), &read_tmp);
if(ret < 0)
return ret;
read = (int16_t)read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_1(channel), &read_tmp);
if(ret < 0)
return ret;
*object_new_raw = (read + (int16_t)read_tmp) / 2;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_2(channel_old), &read_tmp);
if(ret < 0)
return ret;
read = (int16_t)read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_1(channel_old), &read_tmp);
if(ret < 0)
return ret;
*object_old_raw = (read + (int16_t)read_tmp) / 2;
return ret;
}
/******************************************************************************* * 名 称: bsp_Mlx90632ReadTempRaw * 功 能: 读取温度原始值 * 入口参数: ambient_new_raw:环境原始温度新值 ambient_old_raw:环境原始温度旧值 * object_new_raw:物体原始温度新值 object_old_raw:物体原始温度旧值 * 出口参数: 0:正常 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int32_t bsp_Mlx90632ReadTempRaw(int16_t* ambient_new_raw, int16_t* ambient_old_raw,
int16_t* object_new_raw, int16_t* object_old_raw)
{
int32_t ret, start_measurement_ret;
// trigger and wait for measurement to complete
start_measurement_ret = bsp_Mlx90632StartMeasurement();
if(start_measurement_ret < 0)
return start_measurement_ret;
/** Read new and old **ambient** values from sensor */
ret = bsp_Mlx90632ReadTempAmbientRaw(ambient_new_raw, ambient_old_raw);
if(ret < 0)
return ret;
/** Read new and old **object** values from sensor */
ret = bsp_Mlx90632ReadTempObjectRaw(start_measurement_ret, object_new_raw, object_old_raw);
return ret;
}
/* DSPv5 */
double bsp_Mlx90632PreprocessTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int16_t Gb)
{
double VR_Ta, kGb;
kGb = ((double)Gb) / 1024.0;
VR_Ta = ambient_old_raw + kGb * (ambient_new_raw / (MLX90632_REF_3));
return ((ambient_new_raw / (MLX90632_REF_3)) / VR_Ta) * 524288.0;
}
double bsp_Mlx90632PreprocessTempObject(int16_t object_new_raw, int16_t object_old_raw,
int16_t ambient_new_raw, int16_t ambient_old_raw,
int16_t Ka)
{
double VR_IR, kKa;
kKa = ((double)Ka) / 1024.0;
VR_IR = ambient_old_raw + kKa * (ambient_new_raw / (MLX90632_REF_3));
return ((((object_new_raw + object_old_raw) / 2) / (MLX90632_REF_12)) / VR_IR) * 524288.0;
}
double bsp_Mlx90632CalcTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int32_t P_T,
int32_t P_R, int32_t P_G, int32_t P_O, int16_t Gb)
{
double Asub, Bsub, Ablock, Bblock, Cblock, AMB;
AMB = bsp_Mlx90632PreprocessTempAmbient(ambient_new_raw, ambient_old_raw, Gb);
Asub = ((double)P_T) / (double)17592186044416.0;
Bsub = (double)AMB - ((double)P_R / (double)256.0);
Ablock = Asub * (Bsub * Bsub);
Bblock = (Bsub / (double)P_G) * (double)1048576.0;
Cblock = (double)P_O / (double)256.0;
return Bblock + Ablock + Cblock;
}
/******************************************************************************* * 名 称: bsp_Mlx90632CalcTempObjectIteration * 功 能: 物体温度的迭代计算 * 入口参数: prev_object_temp: 上次计算的物体温度值,如果没有,默认为25.0摄氏度 * object: 通过 bsp_Mlx90632PreprocessTempObject 函数获取的物体温度值 * 剩余的参数都是校正值 * 出口参数: 0:正常 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static double bsp_Mlx90632CalcTempObjectIteration(double prev_object_temp, int32_t object, double TAdut,
int32_t Ga, int32_t Fa, int32_t Fb, int16_t Ha, int16_t Hb,
double emissivity)
{
double calcedGa, calcedGb, calcedFa, TAdut4, first_sqrt;
// temp variables
double KsTAtmp, Alpha_corr;
double Ha_customer, Hb_customer;
Ha_customer = Ha / ((double)16384.0);
Hb_customer = Hb / ((double)1024.0);
calcedGa = ((double)Ga * (prev_object_temp - 25)) / ((double)68719476736.0);
KsTAtmp = (double)Fb * (TAdut - 25);
calcedGb = KsTAtmp / ((double)68719476736.0);
Alpha_corr = (((double)(Fa * POW10)) * Ha_customer * (double)(1 + calcedGa + calcedGb)) /
((double)70368744177664.0);
calcedFa = object / (emissivity * (Alpha_corr / POW10));
TAdut4 = (TAdut + 273.15) * (TAdut + 273.15) * (TAdut + 273.15) * (TAdut + 273.15);
first_sqrt = sqrt(calcedFa + TAdut4);
return sqrt(first_sqrt) - 273.15 - Hb_customer;
}
void bsp_Mlx90632SetEmissivity(double value)
{
emissivity = value;
}
double bsp_mlx90632GetEmissivity(void)
{
if(emissivity == 0.0)
{
return 1.0;
}
else
{
return emissivity;
}
}
double bsp_Mlx90632CalcTempObject(int32_t object, int32_t ambient,
int32_t Ea, int32_t Eb, int32_t Ga, int32_t Fa, int32_t Fb,
int16_t Ha, int16_t Hb)
{
double kEa, kEb, TAdut;
double temp = 25.0;
double tmp_emi = bsp_mlx90632GetEmissivity();
int8_t i;
kEa = ((double)Ea) / ((double)65536.0);
kEb = ((double)Eb) / ((double)256.0);
TAdut = (((double)ambient) - kEb) / kEa + 25;
//iterate through calculations
for(i = 0; i < 5; ++i)
{
temp = bsp_Mlx90632CalcTempObjectIteration(temp, object, TAdut, Ga, Fa, Fb, Ha, Hb, tmp_emi);
}
return temp;
}
/***************************** (END OF FILE) **********************************/
- bsp_mlx90632.h 文件
/******************************************************************************* * Filename: bsp_mlx90632.h * Revised: All copyrights reserved to Roger. * Date: 2022-05-02 * Revision: v1.0 * Writer: Roger-WY. * * Description: 非接触式红外温度传感器模块驱动(数字式) 头文件 *******************************************************************************/
#ifndef __BSP_MLX90632_H__
#define __BSP_MLX90632_H__
#include "stm32f10x.h"
#include "bsp_timer.h"
#define MLX90632_TEMP_READ_ERR_CODE -99
/* Solve errno not defined values */
#ifndef ETIMEDOUT
#define ETIMEDOUT 110 /**< From linux errno.h */
#endif
#ifndef EINVAL
#define EINVAL 22 /**< From linux errno.h */
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT 93 /**< From linux errno.h */
#endif
typedef struct __mlx90632calibrationpar
{
int32_t PR;
int32_t PG;
int32_t PO;
int32_t PT;
int32_t Ea;
int32_t Eb;
int32_t Fa;
int32_t Fb;
int32_t Ga;
int16_t Gb;
int16_t Ha;
int16_t Hb;
int16_t Ka;
}stMlx90632CalibraParTypeDef;
/* MLX90632 内部寄存器地址定义 */
/* Private defines -----------------------------------------------------------*/
/* Definition of I2C address of MLX90632 */
#define MLX90632_ADDR 0x3A
#define MLX90632_ADDR_WR (MLX90632_ADDR << 1)
#define BITS_PER_LONG 32
/* BIT, GENMASK and ARRAY_SIZE macros are imported from kernel */
#ifndef BIT
#define BIT(x) (1UL << (x))
#endif
#ifndef GENMASK
#ifndef BITS_PER_LONG
#warning "Using default BITS_PER_LONG value"
#define BITS_PER_LONG 64 /**< Define how many bits per long your CPU has */
#endif
#define GENMASK(h, l) \ (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) /**< Return number of elements in array */
#endif
/* Memory sections addresses */
#define MLX90632_ADDR_RAM 0x4000 /**< Start address of ram */
#define MLX90632_ADDR_EEPROM 0x2480 /**< Start address of user eeprom */
/* EEPROM addresses - used at startup */
#define MLX90632_EE_CTRL 0x24d4 /**< Control register initial value */
#define MLX90632_EE_CONTROL MLX90632_EE_CTRL /**< More human readable for Control register */
#define MLX90632_EE_I2C_ADDRESS 0x24d5 /**< I2C address register initial value */
#define MLX90632_EE_VERSION 0x240b /**< EEPROM version reg - assumed 0x101 */
#define MLX90632_EE_P_R 0x240c /**< Calibration constant ambient reference register 32bit */
#define MLX90632_EE_P_G 0x240e /**< Calibration constant ambient gain register 32bit */
#define MLX90632_EE_P_T 0x2410 /**< Calibration constant ambient tc2 register 32bit */
#define MLX90632_EE_P_O 0x2412 /**< Calibration constant ambient offset register 32bit */
#define MLX90632_EE_Aa 0x2414 /**< Aa calibration const register 32bit */
#define MLX90632_EE_Ab 0x2416 /**< Ab calibration const register 32bit */
#define MLX90632_EE_Ba 0x2418 /**< Ba calibration const register 32bit */
#define MLX90632_EE_Bb 0x241a /**< Bb calibration const register 32bit */
#define MLX90632_EE_Ca 0x241c /**< Ca calibration const register 32bit */
#define MLX90632_EE_Cb 0x241e /**< Cb calibration const register 32bit */
#define MLX90632_EE_Da 0x2420 /**< Da calibration const register 32bit */
#define MLX90632_EE_Db 0x2422 /**< Db calibration const register 32bit */
#define MLX90632_EE_Ea 0x2424 /**< Ea calibration constant register 32bit */
#define MLX90632_EE_Eb 0x2426 /**< Eb calibration constant register 32bit */
#define MLX90632_EE_Fa 0x2428 /**< Fa calibration constant register 32bit */
#define MLX90632_EE_Fb 0x242a /**< Fb calibration constant register 32bit */
#define MLX90632_EE_Ga 0x242c /**< Ga calibration constant register 32bit */
#define MLX90632_EE_Gb 0x242e /**< Ambient Beta calibration constant 16bit */
#define MLX90632_EE_Ka 0x242f /**< IR Beta calibration constant 16bit */
#define MLX90632_EE_Ha 0x2481 /**< Ha customer calibration value register 16bit */
#define MLX90632_EE_Hb 0x2482 /**< Hb customer calibration value register 16bit */
/* Register addresses - volatile */
#define MLX90632_REG_I2C_ADDR 0x3000 /**< Chip I2C address register */
/* Control register address - volatile */
#define MLX90632_REG_CTRL 0x3001 /**< Control Register address */
#define MLX90632_CFG_SOC_SHIFT 3 /**< Start measurement in step mode */
#define MLX90632_CFG_SOC_MASK BIT(MLX90632_CFG_SOC_SHIFT)
#define MLX90632_CFG_PWR_MASK GENMASK(2, 1) /**< PowerMode Mask */
/* PowerModes statuses */
#define MLX90632_PWR_STATUS(ctrl_val) (ctrl_val << 1)
#define MLX90632_PWR_STATUS_HALT MLX90632_PWR_STATUS(0) /**< Pwrmode hold */
#define MLX90632_PWR_STATUS_SLEEP_STEP MLX90632_PWR_STATUS(1) /**< Pwrmode sleep step*/
#define MLX90632_PWR_STATUS_STEP MLX90632_PWR_STATUS(2) /**< Pwrmode step */
#define MLX90632_PWR_STATUS_CONTINUOUS MLX90632_PWR_STATUS(3) /**< Pwrmode continuous*/
/* Device status register - volatile */
#define MLX90632_REG_STATUS 0x3fff /**< Device status register */
#define MLX90632_STAT_BUSY BIT(10) /**< Device busy indicator */
#define MLX90632_STAT_EE_BUSY BIT(9) /**< Device EEPROM busy indicator */
#define MLX90632_STAT_BRST BIT(8) /**< Device brown out reset indicator */
#define MLX90632_STAT_CYCLE_POS GENMASK(6, 2) /**< Data position in measurement table */
#define MLX90632_STAT_DATA_RDY BIT(0) /**< Data ready indicator */
/* RAM_MEAS address-es for each channel */
#define MLX90632_RAM_1(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num)
#define MLX90632_RAM_2(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 1)
#define MLX90632_RAM_3(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 2)
/* Timings (ms) */
#define MLX90632_TIMING_EEPROM 100 /**< Time between EEPROM writes */
/* Magic constants */
#define MLX90632_EEPROM_VERSION 0x105 /**< EEPROM DSP version for constants */
#define MLX90632_EEPROM_WRITE_KEY 0x554C /**< EEPROM write key 0x55 and 0x4c */
#define MLX90632_RESET_CMD 0x0006 /**< Reset sensor (address or global) */
#define MLX90632_MAX_MEAS_NUM 31 /**< Maximum number of measurements in list */
#define MLX90632_EE_SEED 0x3f6d /**< Seed for the CRC calculations */
#define MLX90632_REF_12 12.0 /**< ResCtrlRef value of Channel 1 or Channel 2 */
#define MLX90632_REF_3 12.0 /**< ResCtrlRef value of Channel 3 */
/* MLX90632 供外部调用函数 */
int8_t bsp_Mlx90632Init(void);
int8_t bsp_Mlx90632ReadCalibraParFromEeprom(stMlx90632CalibraParTypeDef *pPar);
void bsp_Mlx90632ReadCalibraParInit(stMlx90632CalibraParTypeDef *pPar);
int bsp_Mlx90632StartMeasurement(void);
int32_t bsp_Mlx90632ChannelNewSelect(int32_t ret, uint8_t *channel_new, uint8_t *channel_old);
int32_t bsp_Mlx90632ReadTempAmbientRaw(int16_t *ambient_new_raw, int16_t *ambient_old_raw);
void bsp_Mlx90632SetEmissivity(double value);
double bsp_Mlx90632CalcTempObject(int32_t object, int32_t ambient,
int32_t Ea, int32_t Eb, int32_t Ga, int32_t Fa, int32_t Fb,
int16_t Ha, int16_t Hb);
double bsp_Mlx90632CalcTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int32_t P_T,
int32_t P_R, int32_t P_G, int32_t P_O, int16_t Gb);
double bsp_Mlx90632PreprocessTempObject(int16_t object_new_raw, int16_t object_old_raw,
int16_t ambient_new_raw, int16_t ambient_old_raw,
int16_t Ka);
double bsp_Mlx90632PreprocessTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int16_t Gb);
int32_t bsp_Mlx90632ReadTempRaw(int16_t *ambient_new_raw, int16_t *ambient_old_raw,
int16_t *object_new_raw, int16_t *object_old_raw);
extern stMlx90632CalibraParTypeDef stMlxCalibraPar;
#endif
/***************************** (END OF FILE) **********************************/
- main 函数读取温度
/******************************************************************************* * Filename: main.c * Revised: All copyrights reserved to Roger-WY. * Revision: v1.0 * Writer: Roger-WY. * * Description: 主函数模块 * * Notes: * E-mail:[email protected] * *******************************************************************************/
/***************************头文件声明区***************************************/
#include "includes.h"
#include "app_var.h"
#include "bsp_mlx90632.h"
/********************************宏定义区**************************************/
/* 定义例程名和例程发布日期 */
#define EXAMPLE_NAME "STM32F103XXX_MLX90632_Demo"
#define EXAMPLE_DATE "2022-05-02"
#define DEMO_VER "1.0.0"
/***************************变量定义及声明区***********************************/
double pre_ambient, pre_object, ambient, object;
stMlx90632CalibraParTypeDef stmlxCalibraPar = {
0};
/***************************函数定义及声明区***********************************/
void app_SeggerRttInit(void);
static void app_ShowPowerOnInfo(void);
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/******************************************************************************* * 名 称: main * 功 能: 主函数 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY. * 创建日期: 2015-06-25 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int main(void)
{
int16_t ambient_new_raw;
int16_t ambient_old_raw;
int16_t object_new_raw;
int16_t object_old_raw;
/*********************************************** * 描述: 初始化硬件设备 */
bsp_Init(); /* 为了是main函数看起来更简洁些,将硬件初始化的代码封装到这个函数 */
bsp_Mlx90632Init();
/*********************************************** * 描述:打印上电信息 */
app_SeggerRttInit();
app_ShowPowerOnInfo();
/*********************************************** * 描述: 创建软定时器 */
bsp_StartAutoTimer( 0,1000 ); /* 启动自动重载软定时器0 用于1S定时任务 */
/*********************************************** * 描述: 进入主程序循环体 */
while(1)
{
/*********************************************** * 描述:用户可以在此函数内执行CPU休眠和喂狗等 * 这个函数在bsp.c 中定义。 */
bsp_Idle(); /* 调用MODS_Poll() */
/* 用户执行的任务 */
/* 1S定时到 */
if(bsp_CheckTimer(0)) {
bsp_LedToggle(1); /* 翻转LED1 */
/* Get raw data from MLX90632 */
bsp_Mlx90632ReadTempRaw(&ambient_new_raw, &ambient_old_raw, &object_new_raw, &object_old_raw);
/* Pre-calculations for ambient and object temperature calculation */
pre_ambient = bsp_Mlx90632PreprocessTempAmbient(ambient_new_raw, ambient_old_raw, stMlxCalibraPar.Gb);
pre_object = bsp_Mlx90632PreprocessTempObject(object_new_raw, object_old_raw, ambient_new_raw, ambient_old_raw, stMlxCalibraPar.Ka);
/* Set emissivity = 1 */
bsp_Mlx90632SetEmissivity(1.0);
/* Calculate ambient and object temperature */
ambient = bsp_Mlx90632CalcTempAmbient(ambient_new_raw, ambient_old_raw, stMlxCalibraPar.PT, stMlxCalibraPar.PR, stMlxCalibraPar.PG, stMlxCalibraPar.PO, stMlxCalibraPar.Gb);
object = bsp_Mlx90632CalcTempObject(pre_object, pre_ambient, stMlxCalibraPar.Ea, stMlxCalibraPar.Eb, stMlxCalibraPar.Ga, stMlxCalibraPar.Fa, stMlxCalibraPar.Fb, stMlxCalibraPar.Ha, stMlxCalibraPar.Hb);
printf("MLX90632 Measure Object Temp:%f ℃,Ambient Temp:%f\n",object,ambient);
}
}
}
void app_SeggerRttInit(void)
{
/*********************************************** * 描述: RTT使用配置 */
/* 配置通道0,上行配置*/
SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
/* 配置通道0,下行配置*/
SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
}
/******************************************************************************* * 名 称: app_ShowPowerOnInfo * 功 能: 上电打印相关信息 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY. * 创建日期: 2015-06-25 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static void app_ShowPowerOnInfo(void)
{
/*********************************************** * 描述: 通过RTT打印信息 */
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0,"\n\r");
SEGGER_RTT_printf(0,"*************************************************************\n\r");
SEGGER_RTT_printf(0,"* 例程名称 : %s\r\n", EXAMPLE_NAME); /* 打印例程名称 */
SEGGER_RTT_printf(0,"* 例程版本 : %s\r\n", DEMO_VER); /* 打印例程版本 */
SEGGER_RTT_printf(0,"* 发布日期 : %s\r\n", EXAMPLE_DATE); /* 打印例程日期 */
/* 打印ST固件库版本,这3个定义宏在stm32f10x.h文件中 */
SEGGER_RTT_printf(0,"* 固件库版本 : V%d.%d.%d (STM32F10x_StdPeriph_Driver)\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
__STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);
SEGGER_RTT_printf(0,"* \r\n"); /* 打印一行空格 */
SEGGER_RTT_printf(0,"* Email : [email protected]yigroup.cn \r\n");
SEGGER_RTT_printf(0,"* 淘宝店: zhisheng.taobao.com\r\n");
SEGGER_RTT_printf(0,"* 技术支持QQ群 : 539041646 \r\n");
SEGGER_RTT_printf(0,"* Copyright www.zhiyigroup.cn 至一电子科技\r\n");
SEGGER_RTT_printf(0,"*************************************************************\n\r");
/*********************************************** * 描述: 通过串口打印信息 */
printf("\n\r");
printf("*************************************************************\n");
printf("* 例程名称 : %s\r\n", EXAMPLE_NAME); /* 打印例程名称 */
printf("* 例程版本 : %s\r\n", DEMO_VER); /* 打印例程版本 */
printf("* 发布日期 : %s\r\n", EXAMPLE_DATE); /* 打印例程日期 */
printf("* --------------------------\r\n"); /* */
printf("* 接线方式 \r\n"); /* 接线方式 */
printf("* VCC ---- 3.3VDC~5VDC \r\n"); /* 接线方式 */
printf("* GND ---- GND \r\n"); /* 接线方式 */
printf("* SCL ---- PC4 \r\n"); /* 接线方式 */
printf("* SDA ---- PC5 \r\n"); /* 接线方式 */
printf("* 串口使用 UASRT1(PA9/PA10) \r\n"); /* */
printf("* --------------------------\r\n"); /* 接线方式 */
/* 打印ST固件库版本,这3个定义宏在stm32f10x.h文件中 */
printf("* 固件库版本 : V%d.%d.%d (STM32F10x_StdPeriph_Driver)\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
__STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);
printf("* \r\n"); /* 打印一行空格 */
printf("* Email : [email protected] \r\n");
printf("* 淘宝店: zhisheng.taobao.com\r\n");
printf("* 技术支持QQ群 : 539041646 \r\n");
printf("* Copyright www.zhiyigroup.cn 至一电子科技\r\n");
printf("*************************************************************\n\r");
}
完整的工程
STM32F1 使用标准库函数读取MLX90632非接触式温度传感器的完整工程可点击此处下载(有积分或者是会员的小伙伴可以支持一下!)
PS:鉴于积分实在有点糟心,所以我把工程上传到 Gitee|Github 上了,没有积分的小伙伴可以直接去下载
结束语
如果觉得文章对您有帮助,请关注、点赞,谢谢!
边栏推荐
猜你喜欢

第1章 Kali与靶机系统

第2章 常用安全工具

第3章 信息收集

【HMS core】【Analytics Kit】【FAQ】如何解决华为分析付费分析中付款金额显示为0的问题?

WARN: Establishing SSL connection without server's identity verification is not recommended when connecting to mysql

Still using Swagger?I recommend this interface management artifact with zero code intrusion

真正懂经营管理的CIO具备哪些特质

Beyond Stream Processing!The 4th real-time computing Flink challenge is launched, and 490,000 prizes are waiting for you!

Re19: Read the paper Paragraph-level Rationale Extraction through Regularization: A case study on European Court

Security Thought Project Summary
随机推荐
Neural Network Study Notes 4 - Autoencoder (including sparse, stacked) (updated)
TestNg整合Retry代码
【梦想起航】
高手云集、丰富活动,斩获佳绩,超过2万名开发者参与的AI社团邀你加入!
(BUG record) No module named PIL
208. 实现 Trie (前缀树)
MySQL installation tutorial [installation version]
第2章 常用安全工具
4、yolov5-6.0 ERROR: AttributeError: ‘Upsample‘ object has no attribute ‘recompute_scale_factor‘ 解决方案
基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
Drools 规则引擎一文读懂
log4j中appender的简介说明
Js array operating mobile for encapsulation
MySQL之数据库维护
图像去噪——Neighbor2Neighbor: Self-Supervised Denoising from Single Noisy Images
梅科尔工作室-看鸿蒙设备开发实战笔记七——网络应用开发
鸿湖万联扬帆富设备开发板正式合入OpenHarmony主干
Basemap and Seaborn
Security Thought Project Summary
Detailed explanation of @RequestBody and @ResponseBody