/** * @file MAX31865_ATY.c * * @param Project DEVICE_GENERAL_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 * * @version * - 1_01_251216 > ATY * -# Preliminary version, first Release * * @todo MAX31865_CONFIG_FAULTCTR and MAX31865_REG_H/LFAULT_M/LSB * * @note SPI_POLARITY_HIGH + SPI_PHASE_2EDGE = CPOL=1, CPHA=1 = SPI Mode 3 ******************************************************************************** */ #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){ __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){ __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, // .rtdWires = 3, // .filter50Hz = 1, // .autoConvert = 1, // .bias = 1, // .faultControl = 0, // .rtdNominal = 100.0, // .refResistor = 424.0, // .lock = __ATY_UNLOCKED // }; /* use */ // uint8_t Max31865_errCount = 0; // void MAX31865_Test(void){ // MAX31865_Init(&MAX31865_ATY_Dev_1); // 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 *********************************/