#include “mbed.h”
const bool DEBUG = false;
// The I2C address of the MLX90381 is hardcoded to 0x32.
const char i8_I2Caddress = 0x32 << 1;
// I2C baud rate. Adapt timing in function of the output capacitor.
int i16_BaudRate = 25000;
// Half clock time
int i16_delay_Inst = 5;
int i16_delay_BR;
// Memory Access Key Register Mode
char i8_I2CSensorMode = 0;
// Write 0x944C in the i2c_cmd_register to allow starting SIN/COS generation
// in normal application mode.
const char NormApplMode = 1;
// Write 0x544E in the i2c_cmd_register to allow entering calibration mode.
const char CalibrationMode = 2;
// Write 0x744C in the i2c_cmd_register to allow starting SIN/COS generation
// in calibration mode.
const char CalApplMode = 4;
char i8_MTPSensorMode = 0;
// Write 0x0077 in the ee_shell_ctrl _register to get out of MTP standby mode
// and enter MTP write mode.
const char MTPwriteMode = 16;
// Write 0x0007 in the ee_shell_ctrl _register to get out of MTP standby mode
// and enter MTP read mode.
const char MTPreadMode = 32;
// Write 0x0006 in the ee_shell_ctrl _register to deactivate
// MTP and reset write mode.
const char MTPresetMode = 64;
// Sequence
char i8_readbyte; // Read register of sendbyte sequence .
int i16_data[8]; // Register of WriteRegister and WriteMTP sequence.
char I2Cstatus; // Status of the I2C.
// Instructions
int i16_MemoryWrite[8];// Contains new content for sensor register or MTP memory.
int i16_MemoryRead[8]; // Copy of sensors MTP memory.
char PTCentry();
char ReadMemory(int StartAddr, char NbWords);
char WriteRegister(int StartAddr, char NbWords);
char WriteMTP(int StartAddr, char NbWords);
void Print_Acknowledge(char I2Cstatus);
void Measure_Outputs();
void Print_Message(char Message);
void Release_Outputs();
Serial mySerial(USBTX, USBRX, 115200); // tx, rx
int main()
{
if(DEBUG) {
mySerial.printf(“==================================================================\n”);
mySerial.printf(“filename: MLX90381_PTC_HW_I2C_GUI/main.cpp\n”);
mySerial.printf(“I2C Master for MLX90381AA.\n\n”);
mySerial.printf("Description:\n");
mySerial.printf("- Uses the Wire.h library to implement I2C master for MLX90381AA.\n");
mySerial.printf("- This software uses the Hardware I2C lines of the microcontroler.\n");
mySerial.printf("- Implementes the activation sequence for MLX90381.\n\n");
mySerial.printf("NOTE: You can not use an Mbed development board that has"
"that has I2C pull-up resistors assampled on the PCB."
"The MLX90381 has internal pull-up resistors on the output"
"pins that are activated when the I2C communications is entered.\n\n");
mySerial.printf("Instructions:\n");
mySerial.printf("S: Program register.\n");
mySerial.printf("C: Check register data.\n");
mySerial.printf("P: Program MTP.\n");
mySerial.printf("R: Read MTP.\n");
mySerial.printf("L: Program MEMLOCK.\n");
mySerial.printf("Note: MEMLOCK is a permanet LOCK of the MTP.\n");
mySerial.printf("W: Enter new data to program address by address.\n");
mySerial.printf("M: Measure outputs in MTP application mode.\n\n");
mySerial.printf("I: Identifiy firmware Mbed.\n\n");
mySerial.printf("version history:\n");
mySerial.printf("2021/06/11 Release v1.0: Initial version v1.0\n");
mySerial.printf("==================================================================\n\n");
}
// Delay in microseconds for the I2C baud rate.
if (1000000 / i16_BaudRate / 2 - i16_delay_Inst > 0)
i16_delay_BR = 1000000 / i16_BaudRate / 2 - i16_delay_Inst;
else
i16_delay_BR = 5;
// Dummy information can be filled with preprogramd configuration.
i16_MemoryWrite[0] = 0x0101; //Fill Memory
i16_MemoryWrite[1] = 0x0101; //Fill Memory
i16_MemoryWrite[2] = 0x00D1; //Fill Memory
i16_MemoryWrite[3] = 0x0014; //Fill Memory
i16_MemoryWrite[4] = 0x0019; //Fill Memory
i16_MemoryWrite[5] = 0x001F; //Fill Memory
i16_MemoryWrite[6] = 0x0000; //Fill Memory
i16_MemoryWrite[7] = 0x0000; //Fill Memory
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFF) {
// Deactivate MTP and reset write mode.
if(DEBUG) Print_Message(4);
i16_data[0] = 0x0006;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPresetMode;
// Enter application mode with MTP configuration after write.
if(DEBUG) Print_Message(5);
i16_data[0] = 0x944C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = NormApplMode;
}
Release_Outputs();
if (I2Cstatus != 0) {
Print_Acknowledge(I2Cstatus);
}
char i;
int a;
char incomingByte;
char NbByteWrite = 6;
char incomingChar[10];
int incomingInt;
// Instruction Loop. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
while(1) {
// Get instruction.
incomingByte = mySerial.getc();
switch ( incomingByte) {
case 'A':
Print_Acknowledge(I2Cstatus);
break;
case 'S':
// Program register. -------------------------------------------
// This instruction programs the volatile register of the sensor
// with the data in the short i16_Memory[8].
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFE) {
Print_Acknowledge(I2Cstatus);
break;
}
if ((i8_I2CSensorMode != CalibrationMode) & (i8_I2CSensorMode != CalApplMode)) {
// Enter calibration mode.
if(DEBUG) Print_Message(2);
i16_data[0] = 0x544E;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalibrationMode;
}
// Program customer register.
if(DEBUG) Print_Message(6);
memcpy (i16_data, i16_MemoryWrite, sizeof(i16_data));
I2Cstatus = WriteRegister(0x0020, NbByteWrite);
if (NbByteWrite != 6) {
// Enter application mode keeping calibration mode valid
// with register configuration.
if(DEBUG) Print_Message(7);
i16_data[0] = 0x744C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalApplMode;
}
Release_Outputs();
if (I2Cstatus == 0) {
Measure_Outputs();
} else {
Print_Acknowledge(I2Cstatus);
}
break;
case 'C':
// Check register data. ----------------------------------------
// This instruction reads the volatile register of the sensor
// and stores the data in the short i16_MTPread[8].
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFE) {
Print_Acknowledge(I2Cstatus);
break;
}
if ((i8_I2CSensorMode != CalibrationMode) & (i8_I2CSensorMode != CalApplMode)) {
// Enter calibration mode.
if(DEBUG) Print_Message(2);
i16_data[0] = 0x544E;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalibrationMode;
}
// Read Customer Register.
if(DEBUG) Print_Message(9);
memset(i16_MemoryRead, 0, sizeof(i16_MemoryRead));
I2Cstatus = ReadMemory(0x0020, 8);
for ( i = 0; i < 8; i++ ) {
mySerial.printf("%X", 32 + i * 2);
mySerial.printf(" ");
mySerial.printf("%X",i16_MemoryRead[i]);
mySerial.printf(" ");
}
mySerial.printf("\n");
// Enter application mode keeping calibration mode valid with
// register configuration.
if(DEBUG) Print_Message(7);
i16_data[0] = 0x744C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalApplMode;
Release_Outputs();
if (I2Cstatus != 0) {
Print_Acknowledge(I2Cstatus);
}
break;
case 'P':
// Program MTP. ------------------------------------------------
// This instruction programs the MTP memory of the sensor with
// the data in the short Memory[8].
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFE) {
Print_Acknowledge(I2Cstatus);
break;
}
if ((i8_I2CSensorMode != CalibrationMode) & (i8_I2CSensorMode != CalApplMode)) {
// Enter calibration mode.
if(DEBUG) Print_Message(2);
i16_data[0] = 0x544E;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalibrationMode;
}
// Enter MTP write mode.
if(DEBUG) Print_Message(3);
i16_data[0] = 0x0077;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPwriteMode;
// Program Customer MTP.
if(DEBUG) Print_Message(8);
memcpy (i16_data, i16_MemoryWrite, sizeof(i16_data));
I2Cstatus = WriteMTP(0x0000, 8);
// Deactivate MTP and reset write mode.
if(DEBUG) Print_Message(4);
i16_data[0] = 0x0006;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPresetMode;
// Enter application mode with MTP configuration after write.
if(DEBUG) Print_Message(5);
i16_data[0] = 0x944C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = NormApplMode;
Release_Outputs();
Print_Acknowledge(I2Cstatus);
break;
case 'R':
// Read MTP. ---------------------------------------------------
// This instruction reads the MTP memory of the sensor and
// stores the data in the short i16_MTPread[8].
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFE) {
Print_Acknowledge(I2Cstatus);
break;
}
if ((i8_I2CSensorMode != CalibrationMode) & (i8_I2CSensorMode != CalApplMode)) {
// Enter calibration mode.
if(DEBUG) Print_Message(2);
i16_data[0] = 0x544E;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalibrationMode;
}
i16_data[0] = 0x0007;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPreadMode;
memset(i16_MemoryRead, 0, sizeof(i16_MemoryRead));
I2Cstatus = ReadMemory(0x0000, 8);
for ( i = 0; i < 8; i++ ) {
mySerial.printf("%X",i * 2);
mySerial.printf(" ");
mySerial.printf("%X",i16_MemoryRead[i]);
mySerial.printf(" ");
}
memset(i16_MemoryRead, 0, sizeof(i16_MemoryRead));
I2Cstatus = ReadMemory(0x0010, 8);
for ( i = 0; i < 8; i++ ) {
mySerial.printf("%X", 16 + i * 2);
mySerial.printf(" ");
mySerial.printf("%X",i16_MemoryRead[i]);
mySerial.printf(" ");
}
mySerial.printf("\n");
// Deactivate MTP and reset write mode.
if(DEBUG) Print_Message(4);
i16_data[0] = 0x0006;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPresetMode;
i16_data[0] = 0x944C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = NormApplMode;
Release_Outputs();
if (I2Cstatus != 0) {
Print_Acknowledge(I2Cstatus);
}
break;
case 'L':
// Program MEMLOCK. --------------------------------------------
// This instruction sets the memory lock bit of the sensor.
// Once this bit is set, the MTP content can no longer be over
// written.
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFE) {
Print_Acknowledge(I2Cstatus);
break;
}
if ((i8_I2CSensorMode != CalibrationMode) & (i8_I2CSensorMode != CalApplMode)) {
// Enter calibration mode.
if(DEBUG) Print_Message(2);
i16_data[0] = 0x544E;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = CalibrationMode;
}
// Enter MTP write mode.
if(DEBUG) Print_Message(3);
i16_data[0] = 0x0077;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPwriteMode;
// Program MTP Lock.
if(DEBUG) Print_Message(11);
i16_data[0] = 0x0003;
I2Cstatus = WriteMTP(0x000C, 1);
// Deactivate MTP and reset write mode.
if(DEBUG) Print_Message(4);
i16_data[0] = 0x0006;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPresetMode;
// Enter application mode with MTP configuration after MEMLOCK.
if(DEBUG) Print_Message(12);
i16_data[0] = 0x944C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = NormApplMode;
Release_Outputs();
Print_Acknowledge(I2Cstatus);
break;
case 'W':
// Load MemoryWrite[8]. ----------------------------------------
// This instruction loads the data entered manually in the
// short i16_MemoryWrite[8].
for ( i = 0; i < 8; i++ ) {
a = 0;
mySerial.printf("ADD ");
mySerial.printf("%d\n", 32 + i * 2);
do {
incomingChar[a] = mySerial.getc();
a++;
if( a > 4)
break;
} while(incomingByte != '\n' && incomingByte != '\r');
sscanf(incomingChar,"%d",&incomingInt);
i16_MemoryWrite[i] = incomingInt;
mySerial.printf("%d", i16_MemoryWrite[i]);
mySerial.printf("\n");
do {
incomingByte = mySerial.getc();
} while (incomingByte != 'n' && incomingByte != 'y' && incomingByte != 'a');
if (incomingByte == 'n')
i = i - 1;
if (incomingByte == 'a')
break;
}
break;
case 'M':
// Measure outputs in application mode with MTP configuration. -
if (i8_MTPSensorMode != MTPresetMode || i8_I2CSensorMode != NormApplMode) {
// Activate I2C interface.
if(DEBUG) Print_Message(1);
I2Cstatus = PTCentry();
if (I2Cstatus == 0xFF) {
// Deactivate MTP and reset write mode.
if(DEBUG) Print_Message(4);
i16_data[0] = 0x0006;
I2Cstatus = WriteRegister(0x0046, 1);
i8_MTPSensorMode = MTPresetMode;
// Enter application mode with MTP configuration after
// write.
if(DEBUG) Print_Message(5);
i16_data[0] = 0x944C;
I2Cstatus = WriteRegister(0x0044, 1);
i8_I2CSensorMode = NormApplMode;
}
Release_Outputs();
wait_ms(3);
}
if (I2Cstatus == 0) {
Measure_Outputs();
} else {
Print_Acknowledge(I2Cstatus);
}
break;
case 'I':
mySerial.printf("90381\n");
break;
}
}
}
// PTC Entry. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// This sequence sends the PTC entry command to the sensor to activate
// the I2C communication.
char PTCentry()
{
char readACK = false;
char readStart;
char readdummy;
char i;
DigitalIn pinSCL(D15, PullDown);
// Short SDA to enter PTC. -------------------------------------------------
DigitalOut pinSDA(D14, 0);
wait_us(i16_delay_BR * 2);
// Check SCL line if OUTPUT drivers are switched OFF. ----------------------
i = 0;
do {
// 100kOhm pull-downs on sensor pins should pull line low when the
// output drivers are switched OFF.
readStart = pinSCL;
i++;
// The drivers should switch off within 250 microseconds.
if (i > 25)
return false;
wait_us(i16_delay_BR);
} while (readStart != 0);
// Send 8 clocks. ----------------------------------------------------------
if (readStart == 0) {
// 100kOhm pull downs on sensor pins should keep the SDA line low.
DigitalOut pinSCL(D15, 0);
pinSCL = 0;
DigitalIn pinSDA(D14, PullNone);
wait_us(i16_delay_BR);
for (i = 0; i < 8; i++) {
pinSCL = 1;
wait_us(i16_delay_BR);
// dummy to keep clock length.
readdummy = pinSDA;
pinSCL = 0;
wait_us(i16_delay_BR);
// dummy to keep clock length.
readdummy = pinSDA;
}
// Check !ACK of the sensor. -------------------------------------------
pinSCL = 1;
wait_us(i16_delay_BR);
i = 0;
do {
// internal 10kOhm pull-up on sensor pins will be set if 8 clocks
// are received well.
readACK = pinSDA;
i++;
// The internal 10kOhm pull-up should switch on within
// 50 microseconds.
if (i > 10) {
wait_us(i16_delay_BR * 10);
DigitalIn pinSDA(D14, PullNone);
DigitalIn pinSCL(D15, PullNone);
return 0xFE;
}
} while (readACK == 0);
pinSCL = 0;
wait_us(i16_delay_BR);
// Send STOP. ----------------------------------------------------------
if (readACK == 1) {
pinSCL = 1;
wait_us(i16_delay_BR);
DigitalOut pinSDA(D14, 1);
wait_us(i16_delay_BR);
}
// Put lines to input to verify if sensor output drivers are in high-Z.
// This is for DEBUG purpose only.
// Internal 10kOhm pull up on sensor pins should keep line high.
//pinSCL.input();
// Internal 10kOhm pull up on sensor pins should keep line high.
//pinSDA.input();
}
wait_us(i16_delay_BR);
return 0xFF; //readACK - 2;
}
// Read Memory. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// This sequence sets the read memory instruction on the I2C lines.
char ReadMemory(int StartAddr, char NbWords)
{
// Selected I2C lines for hardware I2C.
I2C myI2C(I2C_SDA, I2C_SCL); //(D14, D15);
myI2C.frequency (i16_BaudRate);
char I2CACK = 0;
char i, j;
char cmd[2];
char data[12];
// Send Register Start Address. --------------------------------------------
// Write MSB Start Address.
cmd[0] = ((StartAddr >> 8) & 0xFF);
// Write LSB Start Address.
cmd[1] = ( StartAddr & 0xFF);
I2CACK = myI2C.write(i8_I2Caddress, cmd, 2, true);
// Stop transmition without I2C stop!!
i = 0;
j = 0;
// Request 6 bytes from MLX90381 slave device. -----------------------------
I2CACK = myI2C.read(i8_I2Caddress, data, NbWords*2, false);
while (j < NbWords*2) {
// Read data starting with Start Address. ------------------------------
if ((j & 0x01) == 0x01) {
i16_MemoryRead[i] = i16_MemoryRead[i] + (int)(data[j] & 0x00FF);
i++;
} else {
i16_MemoryRead[i] = i16_MemoryRead[i] + (int)(data[j] << 8) & 0xFF00;
}
j++;
}
return I2CACK;
}
// Write Register. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// This sequence sets the Write Register instruction on the I2C lines.
// This is a write without a >10ms delay.
char WriteRegister(int StartAddr, char NbWords)
{
// Selected I2C lines for hardware I2C.
I2C myI2C(I2C_SDA, I2C_SCL); //(D14, D15);
myI2C.frequency (i16_BaudRate);
char I2CACK = 0;
char i;
char cmdr[14];
// Write only Register!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (StartAddr >= 0x20) {
// Send Register Start Address. ----------------------------------------
// Write MSB Start Address.
cmdr[0] = ((StartAddr >> 8) & 0xFF);
// Write LSB Start Address.
cmdr[1] = ( StartAddr & 0xFF);
// Write data starting with Start Address. -----------------------------
for (i = 0; i < NbWords; i++) {
// MSB data Start Address + i.
cmdr[i*2+2] = ((i16_data[i] >> 8) & 0xFF);
// LSB data Start Address + i.
cmdr[i*2+3] = ( i16_data[i] & 0xFF);
}
I2CACK = myI2C.write(i8_I2Caddress, cmdr, NbWords*2+2, false);
}
return I2CACK;
}
// Write MTP +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// This sequence sets the Write MTP memory instruction on the I2C lines.
// This is a write instruction with a >10ms delay.
// Minimum 10 milliseconds are required to erase and write the MTP cells
// of one address!!!
char WriteMTP(int StartAddr, char NbWords)
{
// Selected I2C lines for hardware I2C.
I2C myI2C(I2C_SDA, I2C_SCL); //(D14, D15);
myI2C.frequency (i16_BaudRate);
char I2CACK;
char i;
char cmd[4];
// Write only MTP!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (StartAddr < 0x20) {
for (i = 0; i < NbWords; i++) {
// Send i16_Memory MTP Address. ------------------------------------
// Write MSB Start Address.
cmd[0] = ((StartAddr + (i * 2) >> 8) & 0xFF);
// Write LSB Start Address.
cmd[1] = ( StartAddr + (i * 2) & 0xFF);
// Write data starting for MTP Address -----------------------------
// MSB data Start Address + i.
cmd[2] = ((i16_data[i] >> 8) & 0xFF);
cmd[3] = (i16_data[i] & 0xFF);
I2CACK = myI2C.write(i8_I2Caddress, cmd, 4, false);
// Write MTP Cells. ------------------------------------------------
// Minimum 10 milliseconds are required to erase and write the MTP
// cells of one address!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
wait_ms(11);
}
}
return I2CACK;
}
// Print Acknowledge. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// DEBUG function.
void Print_Acknowledge(char I2Cstatus)
{
switch (I2Cstatus) {
case 0xFE:
mySerial.printf(" FE: I2C interface activation fail\n");
break;
case 0xFF:
mySerial.printf(" FF: I2C interface activation success\n");
break;
case 0:
mySerial.printf(" 0 : success ACK\n");
break;
case 1:
mySerial.printf(" 1 : Received NACK\n");
break;
default:
mySerial.printf(" ? : Unknown\n");
break;
}
}
// Measure Outputs. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Measure_Outputs()
{
// Perform measurements output.
if(DEBUG) Print_Message(10);
AnalogIn valOUT1(A4);
AnalogIn valOUT2(A5);
// Wait for 2000 to 3000uS to allow the drivers of the sensors to switch on.
wait_us(3000);
mySerial.printf(" OUT1 ");
mySerial.printf("%d ", valOUT1.read_u16());
mySerial.printf(" OUT2 ");
mySerial.printf("%d ", valOUT2.read_u16());
mySerial.printf("\n");
}
// Print Message. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// DEBUG function.
void Print_Message(char Message)
{
switch (Message) {
case 1:
mySerial.printf(“Activate I2C interface.\n”);
break;
case 2:
mySerial.printf(“Enter calibration mode.\n”);
break;
case 3:
mySerial.printf(“Enter MTP write mode.\n”);
break;
case 4:
mySerial.printf(“Deactivate MTP and reset write mode.\n”);
break;
case 5:
mySerial.printf(“Enter application mode with MTP configuration.\n”);
break;
case 6:
mySerial.printf(“Program customer register.\n”);
break;
case 7:
mySerial.printf(“Enter application mode keeping calibration mode valid with register configuration.\n”);
break;
case 8:
mySerial.printf(“Program Customer MTP.\n”);
break;
case 9:
mySerial.printf(“Read Customer Register.\n”);
break;
case 10:
mySerial.printf(“Perform measurements output.\n”);
break;
case 11:
mySerial.printf(“Program MTP Lock.\n”);
break;
case 12:
mySerial.printf(“Enter application mode with MTP configuration after MEMLOCK.\n”);
break;
default:
mySerial.printf("Message unknown\n");
break;
}
}
// Release Outputs. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Release_Outputs()
{
DigitalInOut pinSCL(D15);
DigitalInOut pinSDA(D14);
// Switch I2C lines to input
pinSCL.input();
pinSDA.input();
}
【无标题】MLX90381
于 2024-10-09 09:59:38 首次发布