Files
arduino-libs/arduino-cli/libraries/Bluebit/DuinoplusMLX90615.cpp
2024-07-20 22:09:06 +08:00

471 lines
8.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* MLX90615.cpp
MLX90615读写驱动
驱动使用:
1、调用begin()函数初始化。
2、调用getTemp()获取温度值。
对EERPOM的写操作只能通过地址0(?),写之前要擦除
*/
#include "Wire.h"
#include "DuinoplusMLX90615.h"
MLX90615::MLX90615(MODE rwMode)
{
}
MLX90615::~MLX90615()
{
}
/* begin()
设备初始化
输入参数:
*/
void MLX90615::begin(void)
{
Wire.begin();
//Wire.setClock(50000); //IIC速度为50K
device_addr = getAddr();
}
/* getAddr()
获得地址前可能预先不知器件地址所以用地址0获取设备地址
输入参数:
返回值:设备地址
*/
uint8_t MLX90615::getAddr(void)
{
uint8_t temp[2];
device_addr = 0; //从地址0读
//device_addr = 0x5B; //从地址0读
read(ADDRESS, temp);
device_addr = temp[0];
return temp[0];
}
/* setAddr()
设置地址通过地址0设置
输入参数:
uint8_t dat_L数据低字节
uint8_t dat_H数据高字节
*/
void MLX90615::setAddr(uint8_t addr_L, uint8_t addr_H)
{
write(ADDRESS, addr_L, addr_H);
device_addr = addr_L; //保存读到的地址
}
/* getEmissivity()
获取红外测温修正系数
输入参数:
返回值:修正系数
*/
float MLX90615::getEmissivity(void)
{
uint8_t temp[2];
uint16_t tmp;
float tmp1;
read(EMISSIVITY, temp);
//Serial.write(temp[0]);
//Serial.write(temp[1]);
tmp = temp[1];
tmp = (tmp << 8) + temp[0];
tmp1 = ((float)tmp) / 16384;
return tmp1;
}
/* setEmissivity()
设置红外测温修正系数
输入参数:
float e修正系数
返回值:
*/
void MLX90615::setEmissivity(float e)
{
uint8_t temp[2];
uint16_t tmp;
float tmp1 = e;
tmp = tmp1 * 16384;
temp[0] = (uint8_t)(tmp & 0xFF);
temp[1] = (uint8_t)((tmp & 0xFF00) >> 8);
//Serial.write(temp[0]);
//Serial.write(temp[1]);
write(EMISSIVITY, temp[0], temp[1]);
}
/* getPWM_T_min()
获得最小温度值只适用PWM方式
输入参数:
返回值:最小温度值 单位:度
*/
float MLX90615::getPWM_T_min(void)
{
uint8_t temp[2];
uint16_t tmp;
float tmp1;
read(PWM_T_MIN, temp);
//Serial.write(temp[0]);
//Serial.write(temp[1]);
tmp = temp[1];
tmp = (tmp << 8) + temp[0];
tmp1 = ((float)tmp)*0.02 - 273.15;
return tmp1;
}
/* setPWM_T_min()
设置最小温度值只适用PWM方式
输入参数:最小温度值 单位:度
返回值:
*/
void MLX90615::setPWM_T_min(float dat)
{
uint8_t temp[2];
uint16_t tmp;
float tmp1 = dat;
if (tmp1 == 0)
{
temp[0] = 0x5B;
temp[1] = 035;
}
else
{
tmp = (tmp1 + 273.15) * 50;
temp[0] = (uint8_t)(tmp & 0xFF);
temp[1] = (uint8_t)((tmp & 0xFF00) >> 8);
}
//Serial.write(temp[0]);
//Serial.write(temp[1]);
write(PWM_T_MIN, temp[0], temp[1]);
device_addr = temp[0];
}
/* getPWM_T_range()
获得测温范围只适用PWM方式
输入参数:
返回值:测温范围值 单位:度
*/
float MLX90615::getPWM_T_range(void)
{
uint8_t temp[2];
uint16_t tmp;
float tmp1;
read(PWM_T_RANGE, temp);
//Serial.write(temp[0]);
//Serial.write(temp[1]);
tmp = temp[1];
tmp = (tmp << 8) + temp[0];
tmp1 = ((float)tmp)*0.02;
return tmp1;
}
/* setPWM_T_range()
设置测温范围只适用PWM方式
输入参数:测温范围值 单位:度
返回值:
*/
void MLX90615::setPWM_T_range(float dat)
{
uint8_t temp[2];
uint16_t tmp;
float tmp1 = dat;
tmp = tmp1 * 50;
temp[0] = (uint8_t)(tmp & 0xFF);
temp[1] = (uint8_t)((tmp & 0xFF00) >> 8);
//Serial.write(temp[0]);
//Serial.write(temp[1]);
write(PWM_T_RANGE, temp[0], temp[1]);
}
/* setConfig()
设置config寄存器
配置前应把原来的值读出3-11位的工厂设置是不能修改的。
可选配置参数如下,各参数可或组合:
1、通信方式 可选值: PWMPWM 通信方式) IICSMBus 通信方式)
2、PWM高低频选择 可选值: PWM_L 低频 PWM_H 高频
3、PWM通信方式下测温目标选择 可选值: PWM_TEMP_TA 芯片 PWM_TEMP_TO 被测物体
4、数字滤波参数选择 可选值: IIR_1 IIR_10 IIR_18 IIR_24 IIR_31 IIR_38 IIR_45
输入参数:寄存器值
返回值:
*/
void MLX90615::setConfig(uint16_t dat)
{
uint16_t configVal, tempVal;
uint8_t temp[2];
uint8_t i;
configVal = getConfig();
tempVal = configVal; //保存好工厂设置
tempVal &= 0x0FF8;
for (i = 0; i < 16; i++)
{
if (dat & (1 << i)) //对dat按位测试判断其为0还是1
{
configVal |= (1 << i); //为1把相应位置1
}
else
{
configVal &= ~((uint16_t)(1 << i));
}
}
configVal &= 0xF007; //恢复工厂设置位,确保中厂设置不被修改
configVal |= tempVal;
// configVal |= 0x04E0;
temp[0] = (uint8_t)(configVal & 0xFF);
temp[1] = (uint8_t)((configVal & 0xFF00) >> 8);
Serial.write(temp[0]);
Serial.write(temp[1]);
write(CONFIG, temp[0], temp[1]);
}
/* getConfig()
设置config寄存器的值
输入参数:
返回值:寄存器值
*/
uint16_t MLX90615::getConfig(void)
{
uint8_t temp[2];
uint16_t tmp;
read(CONFIG, temp);
//Serial.write(temp[0]);
//Serial.write(temp[1]);
tmp = temp[1];
tmp = (tmp << 8) + temp[0];
return tmp;
}
/* getIIR()
获取数字滤波值
输入参数:
返回值:数字滤波值
*/
uint8_t MLX90615::getIIR(void)
{
}
/* setIIR()
设置数字滤波值
输入参数:
uint16_
返回值:
*/
uint8_t MLX90615::setIIR(uint16_t )
{
}
/* getID()
获取产品ID号共4字节
返回值ID号
*/
uint32_t MLX90615::getID(void)
{
uint32_t id;
return id;
}
/* getTemp()
获得温度值,单位:度
两种通信方式从设备读取温度值IIC和PWM
输入参数:
uint8_t cmd命令
uint8_t dat_L数据低字节
uint8_t dat_H数据高字节
*/
float MLX90615::getTemp(TEMP temp)
{
uint16_t a;
float tmp;
uint8_t tmp1[2];
if (rwMode == IIC_MODE) //IIC通信方式
{
if (temp == OBJ_TEMP)
read(TEMP_TO, tmp1);
else if (temp == CHIP_TEMP)
read(TEMP_TA, tmp1);
//Serial.write(tmp1[0]);
//Serial.write(tmp1[1]);
a = tmp1[1];
a = (a << 8) + tmp1[0];
tmp = (float)a*0.02 - 273.15;
}
else if (rwMode == PWM_MODE) //PWM通雠方式
{
}
return tmp;
}
/* sleep()
进入/退出睡眠模式
输入参数:
boolean sleepFlag模式选择
*/
void MLX90615::sleep(boolean sleepFlag)
{
boolean flag = sleepFlag;
if (flag == SLEEP_ON) //进入睡眠
{
}
else //退出睡眠
{
}
}
/* PWM2IIC()
PWM模式切换到IIC模式
输入参数:
*/
void MLX90615::PWM2IIC(void)
{
pinMode(A5, OUTPUT);
digitalWrite(A5, HIGH);
delay(1000);
digitalWrite(A5, LOW);
delay(30);
digitalWrite(A5, HIGH);
delay(200);
}
/* erase()
擦除,EEPROM数据更新时通常先要执行擦除操作,即先把要修改的字清0
输入参数:
uint8_t cmd擦除地址对就相应命令
*/
void MLX90615::erase(uint8_t cmd)
{
write(cmd, 0, 0); //通过写0擦除
delay(200);
}
/* write()
把数据写入EEPROMRAM通常只读所以不会用到本函数
数据的写入格式参照datasheet的Bus Protocol一章
输入参数:
uint8_t cmd命令
uint8_t dat_L数据低字节
uint8_t dat_H数据高字节
*/
void MLX90615::write(uint8_t cmd, uint8_t dat_L, uint8_t dat_H)
{
uint8_t i;
uint8_t buff[5];
uint8_t tmp;
tmp = device_addr;
device_addr = 0; //擦、写操作只能通过地址0
//Serial.println(device_addr);
/*写之前先擦除*/
buff[0] = device_addr;
buff[1] = cmd;
buff[2] = 0;
buff[3] = 0;
buff[4] = crc8(buff, 4);
Wire.beginTransmission(device_addr);
Wire.write(cmd);
Wire.write(0); //擦除就是写0
Wire.write(0);
Wire.write(buff[4]);
Wire.endTransmission();
delay(1000); //注意加点延时,等待擦除完成
/*擦除后写入数据*/
buff[0] = device_addr;
buff[1] = cmd;
buff[2] = dat_L;
buff[3] = dat_H;
buff[4] = crc8(buff, 4);
//for (i = 0; i < 5; i++) //测试
//{
// Serial.write(buff[i]);
//}
Wire.beginTransmission(device_addr);
Wire.write(cmd);
Wire.write(dat_L);
Wire.write(dat_H);
Wire.write(buff[4]);
Wire.endTransmission();
delay(1000); //注意加点延时,等待写完成
device_addr = tmp;
}
/* read()
把数据从EEPRO或RAM中读出来数据是16位的。
输入参数:
uint8_t cmd命令地址
uint8_t *buffer读出数据缓存
*/
uint8_t MLX90615::read(uint8_t cmd, uint8_t *buffer)
{
uint8_t buff[6];
uint8_t i = 0;
buff[0] = device_addr << 1;
buff[1] = cmd;
buff[2] = (device_addr << 1) + 1;
Wire.beginTransmission(device_addr);
Wire.write(cmd);
Wire.endTransmission(0); // stop transmitting
Wire.requestFrom(device_addr, 3); //从设备读3个字节第1个字节为设备地址第三个字节为CRC8校验。
while (Wire.available()) {
buff[i + 3] = Wire.read(); //设备地址码
i++;
}
//for (i = 0; i < 6; i++) //测试
//{
// Serial.write(buff[i]);
//}
if (buff[5] == crc8(buff, 5)){
*buffer = buff[3];
*(buffer + 1) = buff[4];
return 1;
}
else
return 0;
}
/* crc8()
CRC8校验
输入参数:
uint8_t *buf待校验数据缓存
uint8_t len待校验字节数
*/
uint8_t MLX90615::crc8(uint8_t *buf, uint8_t len)
{
uint8_t i, l;
uint16_t crc = 0;
for (l = 0; l<len; l++)
{
crc ^= (buf[l] * 0x100);
for (i = 0; i<8; i++)
{
if (crc & 0x8000)
{
crc ^= 0x8380;
}
crc *= 2;
}
}
return(crc / 0x100);
}