Problema con la comunicación SPI con MAX31855K de STM8S103F3

1

Estoy tratando de leer los datos de temperatura de MAX31855K sobre SPI, usando STM8S103F3 en un tablero de conexiones.

La configuración de desarrollo es STVD, STVP y el compilador de Consmic. Y utilizando la biblioteca de periféricos estándar STM8S.

Aquí está mi 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 */

aquí está el 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*/

Y aquí está la función principal:

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);
    }
}

Ya contiene varias llamadas printf() como propósito de depuración.

Sospecho que la función MAX31855_Init() inicializa el SPI. Lo codifiqué para el modo de solo recepción, sin embargo, no estoy seguro si se usaron los valores correctos para los parámetros que usé para la función SPI_Init() .

En algún lugar donde leí que llamar SPI_ReceiveData() no es suficiente y tenemos que verificar el estado de la bandera SPI_FLAG_RXNE . Así creado MAX31855_ReceiveData() .

Aquí está la conexión desde STM8S103 = > MAX31855

PC7 (SPI_MISO) = > HACER

PA3 (SPI_NSS) = > CS

PC5 (SPI_SCK) = > CLK

También configuré el bit AFR1 del byte de opción OPT2 a 1 según la hoja de datos. Espero haberlo hecho correctamente.

En general, genera valores de basura no consistentes. Por lo tanto, la comunicación SPI no está sucediendo bien.

¿Podría alguien ayudarme a solucionar el problema de la comunicación SPI con MAX31855K?

Me encantaría saber si alguien ya tiene un código para trabajar con MAX31855.

Gracias de antemano!

    
pregunta Junaid

0 respuestas

Lea otras preguntas en las etiquetas