From e50cd357282e1a1dd86e29bfc8356fe26b7033d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Sat, 19 Dec 2020 00:16:37 +0100 Subject: [PATCH] sensor_max6675: add library for MAX6675 k-type thermocouple reader --- lib/sensor_max6675.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ lib/sensor_max6675.h | 19 +++++++++++ 2 files changed, 94 insertions(+) create mode 100644 lib/sensor_max6675.c create mode 100644 lib/sensor_max6675.h diff --git a/lib/sensor_max6675.c b/lib/sensor_max6675.c new file mode 100644 index 0000000..5a06deb --- /dev/null +++ b/lib/sensor_max6675.c @@ -0,0 +1,75 @@ +/** library to communication with Maxim MAX6675 K-type thermocouple to digital temperature sensor using SPI + * @file + * @author King Kévin + * @copyright SPDX-License-Identifier: GPL-3.0-or-later + * @date 2020 + * @note peripherals used: SPI @ref sensor_max6675_spi + */ +/* standard libraries */ +#include // standard integer types +#include // general utilities +#include // boolean utilities +#include // math utilities + +/* STM32 (including CM3) libraries */ +#include // Cortex M3 utilities +#include // real-time control clock library +#include // general purpose input output library +#include // SPI library + +/* own library */ +#include "global.h" // common definitions +#include "sensor_max6675.h" // own definitions + +/** @defgroup sensor_max6675_spi SPI peripheral used to communicate with the AS3935 + * @note SCK, MISO, and NSS pins are used + */ +#define SENSOR_MAX6675_SPI 1 /**< SPI peripheral */ + +void sensor_max6675_setup(void) +{ + // setup SPI + rcc_periph_clock_enable(RCC_SPI_SCK_PORT(SENSOR_MAX6675_SPI)); // enable clock for GPIO peripheral for clock signal + gpio_set_mode(SPI_SCK_PORT(SENSOR_MAX6675_SPI), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, SPI_SCK_PIN(SENSOR_MAX6675_SPI)); // set SCK as output (clock speed will be negotiated later) + rcc_periph_clock_enable(RCC_SPI_MISO_PORT(SENSOR_MAX6675_SPI)); // enable clock for GPIO peripheral for MISO signal + gpio_set_mode(SPI_MISO_PORT(SENSOR_MAX6675_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SPI_MISO_PIN(SENSOR_MAX6675_SPI)); // set MISO as input + rcc_periph_clock_enable(RCC_SPI_NSS_PORT(SENSOR_MAX6675_SPI)); // enable clock for GPIO peripheral for NSS (CS) signal + gpio_set_mode(SPI_NSS_PORT(SENSOR_MAX6675_SPI), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, SPI_NSS_PIN(SENSOR_MAX6675_SPI)); // set NSS (CS) as output + rcc_periph_clock_enable(RCC_AFIO); // enable clock for SPI alternate function + rcc_periph_clock_enable(RCC_SPI(SENSOR_MAX6675_SPI)); // enable clock for SPI peripheral + spi_reset(SPI(SENSOR_MAX6675_SPI)); // clear SPI values to default + spi_init_master(SPI(SENSOR_MAX6675_SPI), SPI_CR1_BAUDRATE_FPCLK_DIV_32, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST); // initialise SPI as master, divide clock by 64 (72E6/32=2250 kHz, max AS3935 SCK is 4.3, maximum SPI PCLK clock is 72 Mhz, depending on which SPI is used), set clock polarity to idle low (not that important), set clock phase to do bit change on falling edge (polarity depends on clock phase), use 16 bits frames , use MSb first + spi_set_unidirectional_mode(SPI(SENSOR_MAX6675_SPI)); // set simplex mode (only two wires used) + // do not set as receive only to trigger transfer (read) using write + //spi_set_receive_only_mode(SPI(SENSOR_MAX6675_SPI)); // we will only receive data + spi_enable_software_slave_management(SPI(SENSOR_MAX6675_SPI)); // control NSS (CS) manually + spi_set_nss_high(SPI(SENSOR_MAX6675_SPI)); // set NSS high (internally) so we can get input + spi_disable_ss_output(SPI(SENSOR_MAX6675_SPI)); // disable NSS output since we control CS manually + gpio_set(SPI_NSS_PORT(SENSOR_MAX6675_SPI), SPI_NSS_PIN(SENSOR_MAX6675_SPI)); // set CS high to unselect device + spi_enable(SPI(SENSOR_MAX6675_SPI)); // enable SPI +} + +void sensor_max6675_release(void) +{ + spi_reset(SPI(SENSOR_MAX6675_SPI)); + spi_disable(SPI(SENSOR_MAX6675_SPI)); + rcc_periph_clock_disable(RCC_SPI(SENSOR_MAX6675_SPI)); + gpio_set_mode(SPI_NSS_PORT(SENSOR_MAX6675_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_NSS_PIN(SENSOR_MAX6675_SPI)); + gpio_set_mode(SPI_MISO_PORT(SENSOR_MAX6675_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_MISO_PIN(SENSOR_MAX6675_SPI)); + gpio_set_mode(SPI_SCK_PORT(SENSOR_MAX6675_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_SCK_PIN(SENSOR_MAX6675_SPI)); +} + +float sensor_max6675_read(void) +{ + (void)SPI_DR(SPI(SENSOR_MAX6675_SPI)); // clear RXNE flag (by reading previously received data (not done by spi_read or spi_xref) + gpio_clear(SPI_NSS_PORT(SENSOR_MAX6675_SPI), SPI_NSS_PIN(SENSOR_MAX6675_SPI)); // set CS low to select device + const uint16_t temp = spi_xfer(SPI(SENSOR_MAX6675_SPI), 0); // read data + gpio_set(SPI_NSS_PORT(SENSOR_MAX6675_SPI), SPI_NSS_PIN(SENSOR_MAX6675_SPI)); // set CS high to unselect device + if (temp & 0x8002) { // sign and device ID bits should not be set + return NAN; + } + if (temp & 0x0004) { // thermocouple is open + return INFINITY; + } + return (temp >> 3) / 4.0; // return temperature value +} diff --git a/lib/sensor_max6675.h b/lib/sensor_max6675.h new file mode 100644 index 0000000..c682df7 --- /dev/null +++ b/lib/sensor_max6675.h @@ -0,0 +1,19 @@ +/** library to communication with Maxim MAX6675 K-type thermocouple to digital temperature sensor using SPI + * @file + * @author King Kévin + * @copyright SPDX-License-Identifier: GPL-3.0-or-later + * @date 2020 + * @note peripherals used: SPI @ref sensor_max6675_spi + */ +#pragma once + +/** setup communication to MAX6675 sensor */ +void sensor_max6675_setup(void); +/** release peripherals used to communicate with MAX6675 sensor */ +void sensor_max6675_release(void); +/** read temperature from MAX6675 sensor + * @return temperature (in °C) measured by sensor (infinity if K-thermocouple is missing, nan on error) + * @note resolution is in 0.25 °C + * @note wait 0.22 s between readings (max. time needed for a conversion) + */ +float sensor_max6675_read(void);