1
\$\begingroup\$

I am trying to read temperature data from MAX31855K over SPI, using STM8S103F3 on a breakout board.

Development set up is STVD, STVP and Consmic compiler. And using STM8S Standard Peripheral library.

Here is my max31855.h:

#ifndef MAX31855_H
#define MAX31855_H

#define MAX31855_SPI_GPIO_PORT              GPIOC
#define MAX31855_SPI_SCK_PIN                GPIO_PIN_5
#define MAX31855_SPI_MISO_PIN               GPIO_PIN_7
#define MAX31855_NCS_GPIO_PORT              GPIOA /* Chip Select I/O definition */
#define MAX31855_NCS_PIN                    GPIO_PIN_3


#ifdef USE_Delay
#include "main.h"

  #define _delay_     Delay  /* !< User can provide more timing precise _delay_
                                   function (with at least 1ms time base), using
                                   Timer for example */
#else
  #define _delay_     delay      /* !< Default _delay_ function with less precise timing */
#endif


#define MAX31855_CONVERSION_POWER_UP_TIME   200    //in milliseconds

#define MAX31855_SELECT()     GPIO_WriteLow(MAX31855_NCS_GPIO_PORT, MAX31855_NCS_PIN)
#define MAX31855_DESELECT()   GPIO_WriteHigh(MAX31855_NCS_GPIO_PORT, MAX31855_NCS_PIN)

void MAX31855_Init(void);
uint8_t MAX31855_ReceiveData(void);
// uint32_t MAX31855_spiread32(void);
void MAX31855_spiread32(struct max_data* data);
int16_t MAX31855_readCelsius(void);

static void delay(__IO uint32_t nCount);

#endif /* MAX31855_H */

here is the max31855.c

#include "stm8s_gpio.h"
#include "max31855.h"
#include "stdio.h"

static void delay(__IO uint32_t nCount);

struct max_data {
    uint16_t high;
    uint16_t low;
};

#define check_bit(var,pos) ((var) & (1<<(pos)))

/**
  * @brief  SPI connection with MAX31855
  * @param  None
  * @retval None
  */
void MAX31855_Init(void)
{
  /* Enable SPI clock */
  CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, ENABLE);

  /* Configure SPI pins: SCK and MISO */
  GPIO_Init(MAX31855_SPI_GPIO_PORT, (GPIO_Pin_TypeDef)(MAX31855_SPI_SCK_PIN | MAX31855_SPI_MISO_PIN), GPIO_MODE_OUT_PP_LOW_FAST);

  /* Configure MAX31855 ChipSelect pin (NCS) in Output push-pull mode */
  GPIO_Init(MAX31855_NCS_GPIO_PORT, MAX31855_NCS_PIN, GPIO_MODE_OUT_PP_LOW_FAST);

  /* Initialize SPI */
  /* TODO: Not sure about SPI_NSS_SOFT and 0x07 */
  SPI_Init(SPI_FIRSTBIT_MSB, SPI_BAUDRATEPRESCALER_64, SPI_MODE_MASTER,
           SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_1LINE_RX,
           SPI_NSS_SOFT, 0x07);
  SPI_Cmd(ENABLE);



  /* Required to ensure proper MAX31855 display when the board is powered-on ... */
  _delay_(0x4000 * MAX31855_CONVERSION_POWER_UP_TIME); /* 0x4000 = 1ms _delay_ using Fcpu = 16Mhz*/
}

uint8_t MAX31855_ReceiveData(void) {
  while (SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);  // wait for a byte to come in; checks if the Receive register is not empty
  return SPI_ReceiveData();
}

void MAX31855_spiread32(struct max_data* data) {
  // uint32_t d = 0;
  data->high = 0;
  data->low = 0;

  MAX31855_SELECT();
  _delay_(0x4000); // 1ms

  //SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
  // SPI_Cmd(ENABLE);

  data->high = MAX31855_ReceiveData();
  data->high <<= 8;
  data->high |= MAX31855_ReceiveData();
  // d <<= 8;
  data->low |= MAX31855_ReceiveData();
  data->low <<= 8;
  data->low |= MAX31855_ReceiveData();

  // SPI.endTransaction();
  // SPI_Cmd(DISABLE);

  MAX31855_DESELECT();

  // return d;
}

int16_t MAX31855_readCelsius(void) {
  struct max_data data;
  // float centigrade = v;
  int16_t internal;

  MAX31855_spiread32(&data);
  printf("high: %d low: %d\n\r", data.high, data.low);

  // Bit 3 of low is always supposed to be 0.
    if (check_bit( data.low , 3)) {
        printf("Bit 3 is set. WRONG!\r\n");
    }

    // Bit 1 (17th bit of SPI data) of high is always supposed to be 0.
    if (check_bit(data.high, 1)) {
        printf("Bit 17 is set. WRONG!\r\n");
    return 0;
    }

    if (check_bit(data.low, 0)) {
        printf("Thermocouple is open. No connection.\r\n");
    return 0;
    }
    if (check_bit(data.low, 1)) {
        printf("Thermocouple is short circuited to ground.\r\n");
    return 0;
    }
    if (check_bit(data.low, 2)) {
        printf("Thermocouple is short circuited to VCC.\r\n");
    return 0;
    }

  internal = (data.low >> 4) / 16;
  printf("Internal: %d\n\r", internal);

  return (data.high >> 2) / 4;
}

#ifndef USE_Delay
/**
  * @brief  Inserts a delay time.
  *         The delay function implemented in this driver is not a precise one,
  *         however it allows the insertion of 1ms delay when Fcpu is 16Mhz if
  *         the passed parameter is 0x4000.
  *         Any change in system clock frequency will impact this delay duration.
  *
  *         User is given the possibility to develop a customized and accurate
  *         delay function by the mean of timers for example.
  *         Uncommenting " #define USE_Delay" line in the stm8s_eval_lcd.h file
  *         will allow the consideration of the new function by this driver.
  *
  * @param  nCount: specifies the _delay_ time length.
  * @retval None
  */
static void delay(__IO uint32_t nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {
    nCount--;
  }
}
#endif /* USE_Delay*/

And here is the main function:

void main() {
  int16_t temp;

  /* Select fCPU = 16MHz */
  CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);

    /* Initialize I/Os in Output Mode */
  GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_WriteHigh(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);

  MAX31855_Init();
  UART1_DeInit();

  /* UART1 configuration ------------------------------------------------------*/
  /* UART1 configured as follow:
        - BaudRate = 115200 baud
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Receive and transmit enabled
        - UART1 Clock disabled
  */
  UART1_Init((uint32_t)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO,
              UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);

    while (1) {
    temp = MAX31855_readCelsius();
    printf("Temperature %d\n\r", temp);
    GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);
    Delay(50);
    }
}

It already contains several printf() calls as debugging purpose.

I mostly suspect MAX31855_Init() function which initialize the SPI. I coded it for receive-only mode, however not sure if used correct values for the parameters I used for SPI_Init() function call.

Somewhere I read calling SPI_ReceiveData() is not enough and we have to check status of SPI_FLAG_RXNE flag. So created MAX31855_ReceiveData().

Here is the connection from STM8S103 => MAX31855

PC7 (SPI_MISO) => DO

PA3 (SPI_NSS) => CS

PC5 (SPI_SCK) => CLK

I also set AFR1 bit of option byte OPT2 to 1 as per datasheet. Hope i did it correct.

Overall it outputs non consistent garbage values. Thus SPI communication is not happening right.

Could somebody help me to fix the issue over SPI communication with MAX31855K?

I would be happy to hear if somebody already have code for working with MAX31855.

Thanks in advance!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.