|
|
|
@@ -50,10 +50,6 @@
|
|
|
|
|
#define MAX31865_MIN_SAMPLING_TIME_MSEC 0
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef TARGET_LPC1768
|
|
|
|
|
#include <SoftwareSPI.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define DEBUG_OUT ENABLED(DEBUG_MAX31865)
|
|
|
|
|
#include "../core/debug_out.h"
|
|
|
|
|
|
|
|
|
@@ -151,24 +147,62 @@ void MAX31865::begin(max31865_numwires_t wires, float zero_res, float ref_res, f
|
|
|
|
|
digitalWrite(cselPin, HIGH);
|
|
|
|
|
|
|
|
|
|
if (sclkPin != TERN(LARGE_PINMAP, -1UL, 255))
|
|
|
|
|
softSpiBegin(SPI_QUARTER_SPEED); // Define pin modes for Software SPI
|
|
|
|
|
softSpiInit(); // Define pin modes for Software SPI
|
|
|
|
|
else {
|
|
|
|
|
DEBUG_ECHOLNPGM("Initializing MAX31865 Hardware SPI");
|
|
|
|
|
DEBUG_ECHOLNPGM("Init MAX31865 Hardware SPI");
|
|
|
|
|
SPI.begin(); // Start and configure hardware SPI
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initFixedFlags(wires);
|
|
|
|
|
|
|
|
|
|
clearFault(); // also initializes flags
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 Regs: CFG ", readRegister8(MAX31865_CONFIG_REG),
|
|
|
|
|
"|RTD ", readRegister16(MAX31865_RTDMSB_REG),
|
|
|
|
|
"|HTHRS ", readRegister16(MAX31865_HFAULTMSB_REG),
|
|
|
|
|
"|LTHRS ", readRegister16(MAX31865_LFAULTMSB_REG),
|
|
|
|
|
"|FLT ", readRegister8(MAX31865_FAULTSTAT_REG));
|
|
|
|
|
|
|
|
|
|
#if DISABLED(MAX31865_USE_AUTO_MODE) // make a proper first 1 shot read to initialize _lastRead
|
|
|
|
|
// fault detection cycle seems to initialize the sensor better
|
|
|
|
|
runAutoFaultDetectionCycle(); // also initializes flags
|
|
|
|
|
|
|
|
|
|
if (lastFault)
|
|
|
|
|
SERIAL_ECHOLNPGM("MAX31865 init fault ", lastFault);
|
|
|
|
|
|
|
|
|
|
writeRegister16(MAX31865_HFAULTMSB_REG, 0xFFFF);
|
|
|
|
|
writeRegister16(MAX31865_LFAULTMSB_REG, 0);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(MAX31865_USE_AUTO_MODE) // make a proper first read to initialize _lastRead
|
|
|
|
|
|
|
|
|
|
uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
|
|
|
|
|
|
|
|
|
|
#if MAX31865_IGNORE_INITIAL_FAULTY_READS > 0
|
|
|
|
|
rtd = fixFault(rtd);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (rtd & 1) {
|
|
|
|
|
lastRead = 0xFFFF; // some invalid value
|
|
|
|
|
lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
|
|
|
|
|
clearFault(); // also clears the bias voltage flag, so no further action is required
|
|
|
|
|
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read fault: ", rtd);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
DEBUG_ECHOLNPGM("RTD MSB:", (rtd >> 8), " RTD LSB:", (rtd & 0x00FF));
|
|
|
|
|
lastRead = rtd;
|
|
|
|
|
TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = millis());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
enableBias();
|
|
|
|
|
DELAY_US(11500);
|
|
|
|
|
DELAY_US(2000); // according to the datasheet, 10.5τ+1msec (see below)
|
|
|
|
|
oneShot();
|
|
|
|
|
DELAY_US(65000);
|
|
|
|
|
DELAY_US(63000);
|
|
|
|
|
uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
|
|
|
|
|
|
|
|
|
|
#if MAX31865_IGNORE_INITIAL_FAULTY_READS > 0
|
|
|
|
|
rtd = fixFault(rtd);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (rtd & 1) {
|
|
|
|
|
lastRead = 0xFFFF; // some invalid value
|
|
|
|
|
lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
|
|
|
|
@@ -189,7 +223,7 @@ void MAX31865::begin(max31865_numwires_t wires, float zero_res, float ref_res, f
|
|
|
|
|
TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = now);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // !MAX31865_USE_AUTO_MODE
|
|
|
|
|
#endif // MAX31865_USE_AUTO_MODE
|
|
|
|
|
|
|
|
|
|
DEBUG_ECHOLNPGM(
|
|
|
|
|
TERN(LARGE_PINMAP, "LARGE_PINMAP", "Regular")
|
|
|
|
@@ -198,7 +232,7 @@ void MAX31865::begin(max31865_numwires_t wires, float zero_res, float ref_res, f
|
|
|
|
|
" sclkPin: ", sclkPin,
|
|
|
|
|
" mosiPin: ", mosiPin,
|
|
|
|
|
" config: ", readRegister8(MAX31865_CONFIG_REG)
|
|
|
|
|
);
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -240,6 +274,29 @@ void MAX31865::oneShot() {
|
|
|
|
|
setConfig(MAX31865_CONFIG_1SHOT | MAX31865_CONFIG_BIAS, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MAX31865::runAutoFaultDetectionCycle() {
|
|
|
|
|
writeRegister8(MAX31865_CONFIG_REG, (stdFlags & 0x11) | 0x84 ); // cfg reg = 100X010Xb
|
|
|
|
|
DELAY_US(600);
|
|
|
|
|
for (int i = 0; i < 10 && (readRegister8(MAX31865_CONFIG_REG) & 0xC) > 0; i++) DELAY_US(100); // Fault det completes when bits 2 and 3 are zero (or after 10 tries)
|
|
|
|
|
readFault();
|
|
|
|
|
clearFault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set a value in the configuration register.
|
|
|
|
|
*
|
|
|
|
|
* @param config 8-bit value for the config item
|
|
|
|
|
* @param enable whether to enable or disable the value
|
|
|
|
|
*/
|
|
|
|
|
void MAX31865::setConfig(uint8_t config, bool enable) {
|
|
|
|
|
uint8_t t = stdFlags;
|
|
|
|
|
if (enable)
|
|
|
|
|
t |= config;
|
|
|
|
|
else
|
|
|
|
|
t &= ~config;
|
|
|
|
|
writeRegister8(MAX31865_CONFIG_REG, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize standard flags with flags that will not change during operation (Hz, polling mode and no. of wires)
|
|
|
|
|
*
|
|
|
|
@@ -249,12 +306,59 @@ void MAX31865::initFixedFlags(max31865_numwires_t wires) {
|
|
|
|
|
|
|
|
|
|
// set config-defined flags (same for all sensors)
|
|
|
|
|
stdFlags = TERN(MAX31865_50HZ_FILTER, MAX31865_CONFIG_FILT50HZ, MAX31865_CONFIG_FILT60HZ) |
|
|
|
|
|
TERN(MAX31865_USE_AUTO_MODE, MAX31865_CONFIG_MODEAUTO | MAX31865_CONFIG_BIAS, MAX31865_CONFIG_MODEOFF);
|
|
|
|
|
TERN(MAX31865_USE_AUTO_MODE, MAX31865_CONFIG_MODEAUTO | MAX31865_CONFIG_BIAS, MAX31865_CONFIG_MODEOFF);
|
|
|
|
|
|
|
|
|
|
if (wires == MAX31865_3WIRE)
|
|
|
|
|
stdFlags |= MAX31865_CONFIG_3WIRE;
|
|
|
|
|
else // 2 or 4 wire
|
|
|
|
|
stdFlags &= ~MAX31865_CONFIG_3WIRE;
|
|
|
|
|
stdFlags |= MAX31865_CONFIG_3WIRE; // 3 wire
|
|
|
|
|
else
|
|
|
|
|
stdFlags &= ~MAX31865_CONFIG_3WIRE; // 2 or 4 wire
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if MAX31865_IGNORE_INITIAL_FAULTY_READS > 0
|
|
|
|
|
|
|
|
|
|
inline uint16_t MAX31865::fixFault(uint16_t rtd) {
|
|
|
|
|
if (!ignore_faults || !(rtd & 1))
|
|
|
|
|
return rtd;
|
|
|
|
|
|
|
|
|
|
ignore_faults--;
|
|
|
|
|
clearFault();
|
|
|
|
|
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 ignoring fault ", (MAX31865_IGNORE_INITIAL_FAULTY_READS) - ignore_faults);
|
|
|
|
|
|
|
|
|
|
return rtd & ~1; // 0xFFFE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
inline uint16_t MAX31865::readRawImmediate() {
|
|
|
|
|
uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 RTD MSB:", (rtd >> 8), " LSB:", (rtd & 0x00FF));
|
|
|
|
|
|
|
|
|
|
#if MAX31865_IGNORE_INITIAL_FAULTY_READS > 0
|
|
|
|
|
rtd = fixFault(rtd);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (rtd & 1) {
|
|
|
|
|
lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
|
|
|
|
|
lastRead |= 1;
|
|
|
|
|
clearFault(); // also clears the bias voltage flag, so no further action is required
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read fault: ", lastFault);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
TERN_(MAX31865_USE_READ_ERROR_DETECTION, const millis_t ms = millis());
|
|
|
|
|
if (TERN0(MAX31865_USE_READ_ERROR_DETECTION, ABS((int)(lastRead - rtd)) > 500 && PENDING(ms, lastReadStamp + 1000))) {
|
|
|
|
|
// If 2 readings within 1s differ too much (~20°C) it's a read error.
|
|
|
|
|
lastFault = 0x01;
|
|
|
|
|
lastRead |= 1;
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read error: ", rtd);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
lastRead = rtd;
|
|
|
|
|
TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = ms);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rtd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -267,30 +371,13 @@ uint16_t MAX31865::readRaw() {
|
|
|
|
|
|
|
|
|
|
#if ENABLED(MAX31865_USE_AUTO_MODE)
|
|
|
|
|
|
|
|
|
|
const uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 RTD MSB:", (rtd >> 8), " LSB:", (rtd & 0x00FF));
|
|
|
|
|
|
|
|
|
|
if (rtd & 1) {
|
|
|
|
|
lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
|
|
|
|
|
lastRead |= 1;
|
|
|
|
|
clearFault(); // also clears the bias voltage flag, so no further action is required
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read fault: ", rtd);
|
|
|
|
|
}
|
|
|
|
|
#if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
|
|
|
|
|
else if (ABS(lastRead - rtd) > 500 && PENDING(millis(), lastReadStamp + 1000)) { // if two readings within a second differ too much (~20°C), consider it a read error.
|
|
|
|
|
lastFault = 0x01;
|
|
|
|
|
lastRead |= 1;
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read error: ", rtd);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else {
|
|
|
|
|
lastRead = rtd;
|
|
|
|
|
TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = millis());
|
|
|
|
|
}
|
|
|
|
|
readRawImmediate();
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
if (PENDING(millis(), nextEventStamp)) {
|
|
|
|
|
const millis_t ms = millis();
|
|
|
|
|
|
|
|
|
|
if (PENDING(ms, nextEventStamp)) {
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 waiting for event ", nextEvent);
|
|
|
|
|
return lastRead;
|
|
|
|
|
}
|
|
|
|
@@ -298,46 +385,26 @@ uint16_t MAX31865::readRaw() {
|
|
|
|
|
switch (nextEvent) {
|
|
|
|
|
case SETUP_BIAS_VOLTAGE:
|
|
|
|
|
enableBias();
|
|
|
|
|
nextEventStamp = millis() + 11; // wait at least 11msec before enabling 1shot
|
|
|
|
|
nextEventStamp = ms + 2; // wait at least 10.5*τ (τ = 100nF*430Ω max for PT100 / 10nF*4.3ΚΩ for PT1000 = 43μsec) + 1msec
|
|
|
|
|
nextEvent = SETUP_1_SHOT_MODE;
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 bias voltage enabled");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SETUP_1_SHOT_MODE:
|
|
|
|
|
oneShot();
|
|
|
|
|
nextEventStamp = millis() + 65; // wait at least 65msec before reading RTD register
|
|
|
|
|
nextEventStamp = ms + TERN(MAX31865_50HZ_FILTER, 63, 52); // wait at least 52msec for 60Hz (63msec for 50Hz) before reading RTD register
|
|
|
|
|
nextEvent = READ_RTD_REG;
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 1 shot mode enabled");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case READ_RTD_REG: {
|
|
|
|
|
const uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 RTD MSB:", (rtd >> 8), " LSB:", (rtd & 0x00FF));
|
|
|
|
|
case READ_RTD_REG:
|
|
|
|
|
|
|
|
|
|
if (rtd & 1) {
|
|
|
|
|
lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
|
|
|
|
|
lastRead |= 1;
|
|
|
|
|
clearFault(); // also clears the bias voltage flag, so no further action is required
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read fault: ", rtd);
|
|
|
|
|
}
|
|
|
|
|
#if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
|
|
|
|
|
else if (ABS(lastRead - rtd) > 500 && PENDING(millis(), lastReadStamp + 1000)) { // if two readings within a second differ too much (~20°C), consider it a read error.
|
|
|
|
|
lastFault = 0x01;
|
|
|
|
|
lastRead |= 1;
|
|
|
|
|
DEBUG_ECHOLNPGM("MAX31865 read error: ", rtd);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else {
|
|
|
|
|
lastRead = rtd;
|
|
|
|
|
TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = millis());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(rtd & 1)) // if clearFault() was not invoked, need to clear the bias voltage and 1-shot flags
|
|
|
|
|
if (!(readRawImmediate() & 1)) // if clearFault() was not invoked, need to clear the bias voltage and 1-shot flags
|
|
|
|
|
resetFlags();
|
|
|
|
|
|
|
|
|
|
nextEvent = SETUP_BIAS_VOLTAGE;
|
|
|
|
|
nextEventStamp = millis() + MAX31865_MIN_SAMPLING_TIME_MSEC; // next step should not occur within less than MAX31865_MIN_SAMPLING_TIME_MSEC from the last one
|
|
|
|
|
} break;
|
|
|
|
|
nextEventStamp = ms + (MAX31865_MIN_SAMPLING_TIME_MSEC); // next step should not occur within less than MAX31865_MIN_SAMPLING_TIME_MSEC from the last one
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
@@ -411,21 +478,17 @@ float MAX31865::temperature(float rtd_res) {
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// private:
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set a value in the configuration register.
|
|
|
|
|
*
|
|
|
|
|
* @param config 8-bit value for the config item
|
|
|
|
|
* @param enable whether to enable or disable the value
|
|
|
|
|
* MAX31865 SPI Timing constants
|
|
|
|
|
* See MAX31865 datasheet (https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf)
|
|
|
|
|
* All timings in nsec, minimum values.
|
|
|
|
|
*/
|
|
|
|
|
void MAX31865::setConfig(uint8_t config, bool enable) {
|
|
|
|
|
uint8_t t = stdFlags;
|
|
|
|
|
if (enable) t |= config; else t &= ~config;
|
|
|
|
|
writeRegister8(MAX31865_CONFIG_REG, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define MAX31865_SPI_TIMING_TCC 400 // CS to SCLK setup
|
|
|
|
|
#define MAX31865_SPI_TIMING_TDC 35 // Data to SCLK setup
|
|
|
|
|
#define MAX31865_SPI_TIMING_TCL 100 // SCK half period
|
|
|
|
|
#define MAX31865_SPI_TIMING_TCCH 100 // SCK to CS hold
|
|
|
|
|
#define MAX31865_SPI_TIMING_TCWH 400 // CS inactive time (min)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read a single byte from the specified register address.
|
|
|
|
@@ -459,18 +522,10 @@ uint16_t MAX31865::readRegister16(uint8_t addr) {
|
|
|
|
|
* @param n the number of bytes to read
|
|
|
|
|
*/
|
|
|
|
|
void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
|
|
|
|
|
|
|
|
|
|
addr &= 0x7F; // make sure top bit is not set
|
|
|
|
|
if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
|
|
|
|
|
SPI.beginTransaction(spiConfig);
|
|
|
|
|
else
|
|
|
|
|
digitalWrite(sclkPin, LOW);
|
|
|
|
|
|
|
|
|
|
digitalWrite(cselPin, LOW);
|
|
|
|
|
|
|
|
|
|
#ifdef TARGET_LPC1768
|
|
|
|
|
DELAY_CYCLES(spiSpeed);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
spiBeginTransaction();
|
|
|
|
|
spiTransfer(addr);
|
|
|
|
|
|
|
|
|
|
while (n--) {
|
|
|
|
@@ -478,10 +533,15 @@ void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
|
|
|
|
|
buffer++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
|
|
|
|
|
SPI.endTransaction();
|
|
|
|
|
spiEndTransaction();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
digitalWrite(cselPin, HIGH);
|
|
|
|
|
void MAX31865::writeRegister16(uint8_t addr, uint16_t data) {
|
|
|
|
|
spiBeginTransaction();
|
|
|
|
|
spiTransfer(addr | 0x80); // make sure top bit is set
|
|
|
|
|
spiTransfer(data >> 8);
|
|
|
|
|
spiTransfer(data & 0xFF);
|
|
|
|
|
spiEndTransaction();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -491,22 +551,31 @@ void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
|
|
|
|
|
* @param data the data to write
|
|
|
|
|
*/
|
|
|
|
|
void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
|
|
|
|
|
spiBeginTransaction();
|
|
|
|
|
spiTransfer(addr | 0x80); // make sure top bit is set
|
|
|
|
|
spiTransfer(data);
|
|
|
|
|
spiEndTransaction();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MAX31865::spiBeginTransaction() {
|
|
|
|
|
digitalWrite(sclkPin, LOW); // ensure CPOL0
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TCWH); // ensure minimum time of CS inactivity after previous operation
|
|
|
|
|
digitalWrite(cselPin, LOW);
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TCC);
|
|
|
|
|
|
|
|
|
|
if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
|
|
|
|
|
SPI.beginTransaction(spiConfig);
|
|
|
|
|
else
|
|
|
|
|
digitalWrite(sclkPin, LOW);
|
|
|
|
|
|
|
|
|
|
digitalWrite(cselPin, LOW);
|
|
|
|
|
|
|
|
|
|
#ifdef TARGET_LPC1768
|
|
|
|
|
DELAY_CYCLES(spiSpeed);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
spiTransfer(addr | 0x80); // make sure top bit is set
|
|
|
|
|
spiTransfer(data);
|
|
|
|
|
digitalWrite(sclkPin, HIGH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MAX31865::spiEndTransaction() {
|
|
|
|
|
if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
|
|
|
|
|
SPI.endTransaction();
|
|
|
|
|
else
|
|
|
|
|
digitalWrite(sclkPin, LOW);
|
|
|
|
|
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TCCH);
|
|
|
|
|
|
|
|
|
|
digitalWrite(cselPin, HIGH);
|
|
|
|
|
}
|
|
|
|
@@ -521,42 +590,30 @@ void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
|
|
|
|
|
* @return the 8-bit response
|
|
|
|
|
*/
|
|
|
|
|
uint8_t MAX31865::spiTransfer(uint8_t x) {
|
|
|
|
|
|
|
|
|
|
if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
|
|
|
|
|
return SPI.transfer(x);
|
|
|
|
|
|
|
|
|
|
#ifdef TARGET_LPC1768
|
|
|
|
|
|
|
|
|
|
return swSpiTransfer(x, spiSpeed, sclkPin, misoPin, mosiPin);
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
uint8_t reply = 0;
|
|
|
|
|
for (int i = 7; i >= 0; i--) {
|
|
|
|
|
digitalWrite(sclkPin, HIGH); DELAY_NS_VAR(spiDelay);
|
|
|
|
|
reply <<= 1;
|
|
|
|
|
digitalWrite(mosiPin, x & _BV(i)); DELAY_NS_VAR(spiDelay);
|
|
|
|
|
if (digitalRead(misoPin)) reply |= 1;
|
|
|
|
|
digitalWrite(sclkPin, LOW); DELAY_NS_VAR(spiDelay);
|
|
|
|
|
}
|
|
|
|
|
return reply;
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
uint8_t reply = 0;
|
|
|
|
|
for (int i = 7; i >= 0; i--) {
|
|
|
|
|
digitalWrite(mosiPin, x & _BV(i));
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TDC);
|
|
|
|
|
digitalWrite(sclkPin, LOW);
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TCL - MAX31865_SPI_TIMING_TDC);
|
|
|
|
|
reply <<= 1;
|
|
|
|
|
if (digitalRead(misoPin)) reply |= 1;
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TDC);
|
|
|
|
|
digitalWrite(sclkPin, HIGH);
|
|
|
|
|
DELAY_NS_VAR(MAX31865_SPI_TIMING_TCL - MAX31865_SPI_TIMING_TDC);
|
|
|
|
|
}
|
|
|
|
|
return reply;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MAX31865::softSpiBegin(const uint8_t spi_speed) {
|
|
|
|
|
void MAX31865::softSpiInit() {
|
|
|
|
|
DEBUG_ECHOLNPGM("Initializing MAX31865 Software SPI");
|
|
|
|
|
|
|
|
|
|
#ifdef TARGET_LPC1768
|
|
|
|
|
swSpiBegin(sclkPin, misoPin, mosiPin);
|
|
|
|
|
spiSpeed = swSpiInit(spi_speed, sclkPin, mosiPin);
|
|
|
|
|
#else
|
|
|
|
|
spiDelay = (100UL << spi_speed) / 3; // Calculate delay in ns. Top speed is ~10MHz, or 100ns delay between bits.
|
|
|
|
|
pinMode(sclkPin, OUTPUT);
|
|
|
|
|
digitalWrite(sclkPin, LOW);
|
|
|
|
|
pinMode(mosiPin, OUTPUT);
|
|
|
|
|
pinMode(misoPin, INPUT);
|
|
|
|
|
#endif
|
|
|
|
|
pinMode(sclkPin, OUTPUT);
|
|
|
|
|
digitalWrite(sclkPin, LOW);
|
|
|
|
|
pinMode(mosiPin, OUTPUT);
|
|
|
|
|
pinMode(misoPin, INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // HAS_MAX31865 && !USE_ADAFRUIT_MAX31865
|
|
|
|
|