/** * @file MAX31865_ATY.c * * @param Project DEVICE_DRIVER_ATY_LIB * * @author ATY * * @copyright * - Copyright 2017 - 2026 MZ-ATY * - This code follows: * - MZ-ATY Various Contents Joint Statement - * * https://mengze.top/MZ-ATY_VCJS * - CC 4.0 BY-NC-SA - * * https://creativecommons.org/licenses/by-nc-sa/4.0/ * - Your use will be deemed to have accepted the terms of this statement. * * @brief functions of MAX31865 platinum resistance temperature detector for C platform * * @note SPI_POLARITY_HIGH + SPI_PHASE_2EDGE = CPOL=1, CPHA=1 = SPI Mode 3 * * @version * - 1_01_251216 > ATY * -# Preliminary version, first Release * @todo MAX31865_CONFIG_FAULTCTR and MAX31865_REG_H/LFAULT_M/LSB ******************************************************************************** */ #ifndef __MAX31865_ATY_C #define __MAX31865_ATY_C #include "MAX31865_ATY.h" #define MAX31865_ATY_TAG "\r\n[MAX31865_ATY] " /******************************* For user *************************************/ /******************************************************************************/ uint8_t wrData[2] = {0x00, 0x00}; /** * @brief Initialize MAX31865 device * * @param dev Device structure pointer * @return uint8_t Execution result */ uint8_t MAX31865_Init(struct MAX31865_ATY_Dev* dev){ __ATY_LOCK(dev); if(dev->initFlag == 0){ // Set default parameters for PT100 sensor if(dev->rtdNominal == 0) dev->rtdNominal = 100.0; if(dev->refResistor == 0) dev->refResistor = 430.0; // Configuration register settings wrData[0] = MAX31865_REG_CONFIG | 0x80; wrData[1] = 0; if(dev->filter50Hz == 1){ wrData[1] |= MAX31865_CONFIG_FILT50HZ; } if(dev->rtdWires == 3){ wrData[1] |= MAX31865_CONFIG_3WIRE; } if(dev->autoConvert == 1){ wrData[1] |= MAX31865_CONFIG_MODEAUTO; } if(dev->bias == 1){ wrData[1] |= MAX31865_CONFIG_BIAS; } // Write to configuration register dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 2, __ATY_RW_W); dev->nssSet(__ATY_HL_H); dev->initFlag = 1; __ATY_UNLOCK(dev); printf_ATY_D("%sInit config: 0x%02X", MAX31865_ATY_TAG, wrData[1]); MAX31865_ReadConfig(dev); __ATY_LOCK(dev); } __ATY_UNLOCK(dev); return 0; } /** * @brief Read configuration register * * @param dev Device structure pointer * @return uint8_t Configuration register value */ uint8_t MAX31865_ReadConfig(struct MAX31865_ATY_Dev* dev){ __ATY_LOCK(dev); wrData[0] = MAX31865_REG_CONFIG; dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData, 2, __ATY_RW_R); dev->nssSet(__ATY_HL_H); printf_ATY_D("%sRead config: 0x%02X", MAX31865_ATY_TAG, wrData[0]); __ATY_UNLOCK(dev); return wrData[0]; } /** * @brief Read raw RTD value * * @param dev Device structure pointer * @param rtd Pointer to store RTD value * @return uint8_t Execution result */ uint8_t MAX31865_ReadRTD(struct MAX31865_ATY_Dev* dev){ MAX31865_Init(dev); __ATY_LOCK(dev); wrData[0] = MAX31865_REG_RTD_MSB; wrData[1] = 0; dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData, 2, __ATY_RW_R); dev->nssSet(__ATY_HL_H); // remove last fault bit dev->rtdValue = ((wrData[0] << 8) | wrData[1]) >> 1; __ATY_UNLOCK(dev); return 0; } /** * @brief Read fault status * * @param dev Device structure pointer * @return uint8_t Fault status register value */ uint8_t MAX31865_ReadFault(struct MAX31865_ATY_Dev* dev){ __ATY_LOCK(dev); dev->faultStatus = 0; wrData[0] = MAX31865_REG_FAULT_STATUS; dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData, 1, __ATY_RW_R); dev->nssSet(__ATY_HL_H); dev->faultStatus = wrData[0]; if(dev->faultStatus != 0){ printf_ATY_D("%sFault: 0x%02X", MAX31865_ATY_TAG, dev->faultStatus); if(dev->faultStatus & MAX31865_FAULT_HIGH_THRESH){ printf_ATY_D(" HIGH_THRESHOLD"); } if(dev->faultStatus & MAX31865_FAULT_LOW_THRESH){ printf_ATY_D(" LOW_THRESHOLD"); } if(dev->faultStatus & MAX31865_FAULT_REFIN_LOW){ printf_ATY_D(" REFIN_LOW"); } if(dev->faultStatus & MAX31865_FAULT_REFIN_HIGH){ printf_ATY_D(" REFIN_HIGH"); } if(dev->faultStatus & MAX31865_FAULT_RTDIN_LOW){ printf_ATY_D(" RTDIN_LOW"); } if(dev->faultStatus & MAX31865_FAULT_OVUV){ printf_ATY_D(" OVER_UNDER_VOLTAGE"); } } __ATY_UNLOCK(dev); return wrData[0]; } /** * @brief Clear fault status * * @param dev Device structure pointer * @return uint8_t Execution result */ uint8_t MAX31865_ClearFaults(struct MAX31865_ATY_Dev* dev){ __ATY_LOCK(dev); dev->faultStatus = 0; wrData[0] = MAX31865_REG_CONFIG; // Read current configuration dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData, 1, __ATY_RW_R); dev->nssSet(__ATY_HL_H); // Set fault clear bit wrData[1] = wrData[0]; wrData[1] |= MAX31865_CONFIG_FAULTSTAT; // printf_ATY_D("\r\n0x%02X", wrData[0]); // printf_ATY_D("\r\n0x%02X", wrData[1]); wrData[0] = MAX31865_REG_CONFIG | 0x80; // Write back to configuration register dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData + 1, 1, __ATY_RW_R); dev->nssSet(__ATY_HL_H); __ATY_UNLOCK(dev); return 0; } /** * @brief Trigger one-shot conversion * * @param dev Device structure pointer * @return uint8_t Execution result */ uint8_t MAX31865_OneShot(struct MAX31865_ATY_Dev* dev){ MAX31865_Init(dev); __ATY_LOCK(dev); wrData[0] = MAX31865_REG_CONFIG; // Read current configuration dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData, 1, __ATY_RW_R); dev->nssSet(__ATY_HL_H); wrData[1] = wrData[0]; wrData[1] |= MAX31865_CONFIG_1SHOT; wrData[0] = MAX31865_REG_CONFIG | 0x80; // Write back to configuration register dev->nssSet(__ATY_HL_L); dev->spiProcess(wrData, 1, __ATY_RW_W); dev->spiProcess(wrData + 1, 1, __ATY_RW_R); dev->nssSet(__ATY_HL_H); __ATY_UNLOCK(dev); return 0; } /** * @brief Calculate resistance from RTD value * * @param dev Device structure pointer * @param rtd RTD value, if 0, use internal RTD value * @return float Resistance */ float MAX31865_CalculateResistance(struct MAX31865_ATY_Dev* dev, uint16_t rtd){ if(rtd == 0) return (float)dev->rtdValue * dev->refResistor / ((uint16_t)1 << 15); return (float)rtd * dev->refResistor / ((uint16_t)1 << 15); } /** * @brief Calculate temperature from RTD value * * @param dev Device structure pointer * @param rtd RTD value, if 0, use internal RTD value * @return float Temperature */ float MAX31865_CalculateTemperature(struct MAX31865_ATY_Dev* dev, uint16_t rtd){ return (MAX31865_CalculateResistance(dev, rtd) - dev->rtdNominal) / 0.385; } #endif /* __MAX31865_ATY_C */ /************************************ etc *************************************/ /* init // MAX31865 -------------------------------------------------------------------- #include "MAX31865_ATY.h" void MAX31865_1_NSS_SET(uint8_t level){ if(level == __ATY_HL_L) HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_RESET); else if(level == __ATY_HL_H) HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_SET); } uint8_t MAX31865_1_SPI(uint8_t* data_t, uint16_t len, uint8_t rw){ if(rw == __ATY_RW_R){ return HAL_SPI_Receive(&hspi2, (uint8_t*)data_t, len, 1000); } else{ return HAL_SPI_Transmit(&hspi2, (uint8_t*)data_t, len, 1000); } } struct MAX31865_ATY_Dev MAX31865_ATY_Dev_1 = { .nssSet = MAX31865_1_NSS_SET, .spiProcess = MAX31865_1_SPI, .initFlag = 0, .bias = 1, .autoConvert = 1, .rtdWires = 3, .faultControl = 0, .filter50Hz = 1, .rtdNominal = 100.0, .refResistor = 424.0, .rtdValue = 0, .faultStatus = 0, .lock = __ATY_UNLOCKED }; */ /* use uint8_t Max31865_errCount = 0; void MAX31865_Test(void){ MAX31865_ReadRTD(&MAX31865_ATY_Dev_1); MAX31865_ReadFault(&MAX31865_ATY_Dev_1); // (9584640.0 / MAX31865_ATY_Dev_1.refResistor) -> 500C // (2015232.0 / MAX31865_ATY_Dev_1.refResistor) -> -100C if(MAX31865_ATY_Dev_1.faultStatus != 0 || MAX31865_ATY_Dev_1.rtdValue == 32767 || MAX31865_ATY_Dev_1.rtdValue == 0 || MAX31865_ATY_Dev_1.rtdValue > (9584640.0 / MAX31865_ATY_Dev_1.refResistor) || MAX31865_ATY_Dev_1.rtdValue < (2015232.0 / MAX31865_ATY_Dev_1.refResistor)){ Max31865_errCount++; // if cycle is long like 1s, this errCount can be lower if(Max31865_errCount > 6){ Max31865_errCount = 0; MAX31865_ATY_Dev_1.initFlag = 0; // Notice: ClearFaults might make next rtd value wrong, // so wait a cycle to read value after clear fault if(MAX31865_ATY_Dev_1.faultStatus != 0) MAX31865_ClearFaults(&MAX31865_ATY_Dev_1); printf_ATY("\r\nRTD Value Abnormal - Reinitializing..."); } } // else { printf_ATY("\r\nRTD: 0x%04X, Resistance: %.2f ohm, Temperature: %.2f C", MAX31865_ATY_Dev_1.rtdValue, MAX31865_CalculateResistance(&MAX31865_ATY_Dev_1, 0), MAX31865_CalculateTemperature(&MAX31865_ATY_Dev_1, 0)); // MAX31865_ReadConfig(&MAX31865_ATY_Dev_1); } } */ /******************************************************************************/ /******************************** End Of File *********************************/