cancel
Showing results for 
Search instead for 
Did you mean: 

spi stm32l010c6t6 transmit data inverter

jdo
Associate II

Hi everyone! i am using stm32l0c6t6, i need use spi with register, because i need make function type: spiwriteread(uint8_t data), to write in the device Lora llcc68 and read the return register, but with hal i can´t. Then i have configurated the spi using register, but when transmit i read in the logic analyzer inverter data, example: i transmit spiwriteread(0x55); and the logic analyzer had 0XAA; i don´t know why this is ocurr because the configuration register is rigth. i going to put the complete code:

/*--------------------------------------------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------------------------------------------------------------*/

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
//uint8_t Data[]="hola";
 
char *Data = "hola";
uint8_t data1;
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
 
/* USER CODE BEGIN PFP */
void SPI_Init(void);
uint8_t SPI_TransmitData(uint8_t *data);
void SPI_TransmitString(char *str);
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  //LL_SPI_TransmitData8(SPI1,Data);
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
 
  /* USER CODE BEGIN 2 */
 
  SPI_Init();
 
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  //SPI_TransmitData(Data);
  SPI_TransmitData(0x55);
  HAL_Delay(500);
  }
  /* USER CODE END 3 */
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief GPIO Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
 
/*-----------------------------------------------------------*/
/*----------------------------------------------------------*/
 
 
void SPI_Init(void) {
    // Habilitar el reloj para el SPI y el puerto GPIO correspondiente (puerto B)
 
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
    RCC->IOPENR  |= RCC_IOPENR_GPIOBEN;
 
    // Configurar los pines SCK (PB13), MOSI (PB15) y MISO (PB14) como alternativa de función SPI
    GPIOB->MODER  &= ~(GPIO_MODER_MODE13_Msk | GPIO_MODER_MODE14_Msk | GPIO_MODER_MODE15_Msk);
    GPIOB->MODER  |= (GPIO_MODER_MODE13_1 | GPIO_MODER_MODE14_1 | GPIO_MODER_MODE15_1);
    GPIOB->AFR[1] &= ~((0xF << GPIO_AFRH_AFSEL13_Pos) | (0xF << GPIO_AFRH_AFSEL14_Pos) | (0xF << GPIO_AFRH_AFSEL15_Pos));
    GPIOB->AFR[1] |= ((0x0 << GPIO_AFRH_AFSEL13_Pos) | (0x0 << GPIO_AFRH_AFSEL14_Pos) | (0x0 << GPIO_AFRH_AFSEL15_Pos));
 
    // Configurar los registros del SPI
    //////////////////////////////////
    SPI1->CR1 = 0; // Asegúrate de deshabilitar el SPI antes de configurar
 
    // Configuración del modo de polaridad y fase
    /////////////////////////////////////////////
    SPI1->CR1 &= ~SPI_CR1_CPOL; // CPOL = 0
    SPI1->CR1 &= ~SPI_CR1_CPHA; // CPHA = 0
 
    // Configuración del formato de datos y tamaño
    //////////////////////////////////////////////
    SPI1->CR1 &= ~SPI_CR1_LSBFIRST; // MSB first
    SPI1->CR1 &= ~SPI_CR1_DFF; // 8 bits
 
    // Configuración de la velocidad (baud rate)
    // El cálculo del valor del registro depende de la frecuencia del reloj del sistema
    uint32_t systemClockFreq   = 16000000; // Frecuencia del reloj del sistema en Hz
    uint32_t desiredBaudRate   = 125000; // Baud rate deseado en bps
    uint32_t baudRatePrescaler = (systemClockFreq + (desiredBaudRate / 2)) / desiredBaudRate;
    SPI1->CR1 |= ((baudRatePrescaler - 1) << SPI_CR1_BR_Pos);
 
    // Configuración del modo master
    SPI1->CR1 |= SPI_CR1_MSTR;
 
    // Habilitar el SPI
    SPI1->CR1 |= SPI_CR1_SPE;
}
 
 
 
 
uint8_t SPI_TransmitData(uint8_t *data) {
 
data1=data;
 
    // Esperar a que el registro de transmisión esté vacío
    while (!(SPI1->SR & SPI_SR_TXE));
 
    // Enviar el dato
    *( uint8_t*)&(SPI1->DR) = data1;
 
    // Esperar a que la transmisión se complete
    while (SPI1->SR & SPI_SR_BSY);
 
    // Esperar a que el registro de recepción esté lleno
    while (!(SPI1->SR & SPI_SR_RXNE));
 
    // Leer y devolver el dato recibido
    return *((volatile uint8_t*)&SPI1->DR);
}
 
 
void SPI_TransmitString(char *str) {
    uint16_t len = strlen(str);
 
    for (uint16_t i = 0; i < len; i++) {
        SPI_TransmitData((uint8_t)str[i]);
    }
}
 
 
/*----------------------------------------------------------*/
 
/* USER CODE END 4 */
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @PAram  file: pointer to the source file name
  * @PAram  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/*-----------------------------------------------------------------------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------------------------------------------------------------------*/

7 REPLIES 7
TDK
Guru

I don't see CS signal management anywhere. How do you ensure master/slave are in sync?

Off by one bit could also suggest CPHA and CPOL settings are mismatched between logic analyzer and spi configuration. Show the logic analyzer trace for sending 0x55.

If you feel a post has answered your question, please click "Accept as Solution".

Are you sure it's inverted and not an MSB / LSB interpretation. Perhaps try a different pattern.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

my logic analyzer is configurated as: spi_conf.JPG

but i test with hal send 0x55 and similar configuration and the logic analyzer i view 0x55.

jdo
Associate II

 i send 0x55 and i view 0XAA in the logic analyzer:spi1.JPGspi_conf.JPG

"Perhaps try a different pattern" ,  i don´t understand with different pattern, but i send 0x55 with library and i view 0x55 with the similar configurattion of logic analyzer, but if i put "least significant bit first" in the logic anlyzer the spi is 0x55.spi_data2.JPGspi_conf2.JPG

jdo
Associate II

this spi is rigth because for send first MSB the logic analyzer view the bits inverter.

 

TDK
Guru

SPI is MSB first by default. Perhaps check it against other patterns that would clearly expose the difference in bit order. 0x0F, etc.

If you feel a post has answered your question, please click "Accept as Solution".