cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 with an ADAFRUIT BLE SPI

Paulo971
Associate III
Hello st community,
I'm trying to set up a bleutooth communication between my phone and my stm32 with the Adafruit module in SPI communication, but I'm having a problem.

When I use my arduino and the demo code it works perfectly but when I connect to my stm32 and do my code based on the demo code I have a problem during the factory reset, the module shuts down and I can't see the ble module on my phone.

I have checked my wires 3 times and also the power supply provided by the nucleo I have the 3.3V

I use doclight to monitor uart communication for debugging

Capture d'écran 2024-12-11 120927.png

You will find my code below:

 

  */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "stdlib.h"
    #include "stdio.h"
    #include <string.h>
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    #define SPI_CS_PIN    GPIO_PIN_8
    #define SPI_CS_PORT   GPIOB
    #define SPI_IRQ_PIN   GPIO_PIN_7
    #define SPI_IRQ_PORT  GPIOB
    #define SPI_RST_PIN   GPIO_PIN_6
    #define SPI_RST_PORT  GPIOB
    
    #define BUFSIZE                        128
    #define VERBOSE_MODE                   1
    #define BLE_READPACKET_TIMEOUT         500
    
    #define FACTORYRESET_ENABLE            1
    #define BLUEFRUIT_CMD_TIMEOUT          1000
    /* 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 ---------------------------------------------------------*/
    SPI_HandleTypeDef hspi2;
    
    UART_HandleTypeDef huart2;
    
    /* USER CODE BEGIN PV */
    
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_USART2_UART_Init(void);
    static void MX_SPI2_Init(void);
    /* USER CODE BEGIN PFP */
    uint8_t ble_begin(void);
    uint8_t ble_factoryReset(void);
    void ble_echo(uint8_t enable);
    void ble_info(void);
    uint8_t sendCommand(const char* cmd, char* response, uint16_t timeout);
    void UART_Print(UART_HandleTypeDef *huart, const char *str);
    void printHex(const uint8_t *data, const uint32_t numBytes);
    uint8_t readPacket(uint16_t timeout);
    uint8_t packetbuffer[BUFSIZE];
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    void UART_SendBuffer(uint8_t *buffer, uint16_t size){
        HAL_UART_Transmit(&huart2, buffer, size, HAL_MAX_DELAY);
    }
    
    /* 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 */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_USART2_UART_Init();
      MX_SPI2_Init();
      /* USER CODE BEGIN 2 */
      UART_Print(&huart2, "Adafruit Bluefruit Command Mode Example\n");
      UART_Print(&huart2, "---------------------------------------\n");
    
      UART_Print(&huart2, "Starting ble_begin...\n");
      if (!ble_begin())
      {
          UART_Print(&huart2, "Couldn't find Bluefruit, make sure it's in Command mode & check wiring?\n");
          while (1);
      }
      UART_Print(&huart2, "OK!\n");
    
      if (FACTORYRESET_ENABLE)
      {
          UART_Print(&huart2, "Starting factory reset...\n");
          if (!ble_factoryReset())
          {
              UART_Print(&huart2, "Couldn't factory reset\n");
              while (1);
          }
          UART_Print(&huart2, "Factory reset complete\n");
          HAL_Delay(2000); // Allow the module to restart
      }
    
      UART_Print(&huart2, "Disabling echo...\n");
      ble_echo(0);
      UART_Print(&huart2, "Echo disabled\n");
    
      UART_Print(&huart2, "Requesting Bluefruit info:\n");
      ble_info();
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
          UART_Print(&huart2, "Reading packet...\n");
          uint8_t len = readPacket(BLE_READPACKET_TIMEOUT);
          if (len > 0)
          {
              UART_Print(&huart2, "Received packet: ");
              printHex(packetbuffer, len);
          }
          HAL_Delay(1000);
      }
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      /* 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_RCC_PWR_CLK_ENABLE();
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
    
      /** 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_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
      RCC_OscInitStruct.PLL.PLLM = 16;
      RCC_OscInitStruct.PLL.PLLN = 100;
      RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
      RCC_OscInitStruct.PLL.PLLQ = 7;
      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_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /**
      * @brief SPI2 Initialization Function
      * @PAram None
      * @retval None
      */
    static void MX_SPI2_Init(void)
    {
    
      /* USER CODE BEGIN SPI2_Init 0 */
    
      /* USER CODE END SPI2_Init 0 */
    
      /* USER CODE BEGIN SPI2_Init 1 */
    
      /* USER CODE END SPI2_Init 1 */
      /* SPI2 parameter configuration*/
      hspi2.Instance = SPI2;
      hspi2.Init.Mode = SPI_MODE_MASTER;
      hspi2.Init.Direction = SPI_DIRECTION_2LINES;
      hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
      hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
      hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
      hspi2.Init.NSS = SPI_NSS_SOFT;
      hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
      hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
      hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
      hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
      hspi2.Init.CRCPolynomial = 10;
      if (HAL_SPI_Init(&hspi2) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN SPI2_Init 2 */
    
      /* USER CODE END SPI2_Init 2 */
    
    }
    
    /**
      * @brief USART2 Initialization Function
      * @PAram None
      * @retval None
      */
    static void MX_USART2_UART_Init(void)
    {
    
      /* USER CODE BEGIN USART2_Init 0 */
    
      /* USER CODE END USART2_Init 0 */
    
      /* USER CODE BEGIN USART2_Init 1 */
    
      /* USER CODE END USART2_Init 1 */
      huart2.Instance = USART2;
      huart2.Init.BaudRate = 115200;
      huart2.Init.WordLength = UART_WORDLENGTH_8B;
      huart2.Init.StopBits = UART_STOPBITS_1;
      huart2.Init.Parity = UART_PARITY_NONE;
      huart2.Init.Mode = UART_MODE_TX_RX;
      huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      huart2.Init.OverSampling = UART_OVERSAMPLING_16;
      if (HAL_UART_Init(&huart2) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN USART2_Init 2 */
    
      /* USER CODE END USART2_Init 2 */
    
    }
    
    /**
      * @brief GPIO Initialization Function
      * @PAram None
      * @retval None
      */
    static void MX_GPIO_Init(void)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* USER CODE BEGIN MX_GPIO_Init_1 */
    /* USER CODE END MX_GPIO_Init_1 */
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOC_CLK_ENABLE();
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOB, SPI_RST_Pin|SPI_CS_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : B1_Pin */
      GPIO_InitStruct.Pin = B1_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
    
      /*Configure GPIO pin : LD2_Pin */
      GPIO_InitStruct.Pin = LD2_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
    
      /*Configure GPIO pins : SPI_RST_Pin SPI_CS_Pin */
      GPIO_InitStruct.Pin = SPI_RST_Pin|SPI_CS_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
      /*Configure GPIO pin : SPI_IRQ_Pin */
      GPIO_InitStruct.Pin = SPI_IRQ_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(SPI_IRQ_GPIO_Port, &GPIO_InitStruct);
    
    /* USER CODE BEGIN MX_GPIO_Init_2 */
    /* USER CODE END MX_GPIO_Init_2 */
    }
    
    /* USER CODE BEGIN 4 */
    uint8_t ble_begin(void)
    {
        UART_Print(&huart2, "Initializing SPI communication...\n");
        HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);
        // Add SPI initialization code here if necessary
        HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_SET);
        UART_Print(&huart2, "SPI communication initialized.\n");
        return 1; // Return 1 for success, 0 for failure
    }
    
    uint8_t ble_factoryReset(void)
    {
        char response[BUFSIZE];
        if (sendCommand("AT+FACTORYRESET", response, BLUEFRUIT_CMD_TIMEOUT))
        {
            UART_Print(&huart2, "Factory Reset Response: ");
            UART_Print(&huart2, response);
            UART_Print(&huart2, "\n");
            return 1; // Success
        }
        else
        {
            UART_Print(&huart2, "Factory Reset Timeout or Error\n");
            return 0; // Failure
        }
    }
    
    void ble_echo(uint8_t enable)
    {
        char response[BUFSIZE];
        if (enable)
        {
            sendCommand("ATE=1", response, BLUEFRUIT_CMD_TIMEOUT);
        }
        else
        {
            sendCommand("ATE=0", response, BLUEFRUIT_CMD_TIMEOUT);
        }
        UART_Print(&huart2, "Echo Response: ");
        UART_Print(&huart2, response);
        UART_Print(&huart2, "\n");
    }
    
    void ble_info(void)
    {
        char response[BUFSIZE];
        if (sendCommand("ATI", response, BLUEFRUIT_CMD_TIMEOUT))
        {
            UART_Print(&huart2, "Module Info: ");
            UART_Print(&huart2, response);
            UART_Print(&huart2, "\n");
        }
        else
        {
            UART_Print(&huart2, "Info Command Timeout or Error\n");
        }
    }
    
    uint8_t sendCommand(const char* cmd, char* response, uint16_t timeout)
    {
        UART_Print(&huart2, "Sending command: ");
        UART_Print(&huart2, cmd);
        UART_Print(&huart2, "\n");
    
        uint8_t cmdLength = strlen(cmd);
        HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);
    
        for (uint8_t i = 0; i < cmdLength; i++)
        {
            if (HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd[i], 1, HAL_MAX_DELAY) != HAL_OK)
            {
                UART_Print(&huart2, "SPI Transmit Error\n");
            }
        }
    
        uint8_t newline = '\n';
        if (HAL_SPI_Transmit(&hspi2, &newline, 1, HAL_MAX_DELAY) != HAL_OK)
        {
            UART_Print(&huart2, "SPI Transmit Error\n");
        }
    
        HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_SET);
    
        UART_Print(&huart2, "Command sent, waiting for response...\n");
    
        uint32_t startTick = HAL_GetTick();
        uint8_t index = 0;
    
        while ((HAL_GetTick() - startTick) < timeout)
        {
            uint8_t byte;
            if (HAL_SPI_Receive(&hspi2, &byte, 1, HAL_MAX_DELAY) == HAL_OK)
            {
                response[index++] = byte;
                if (byte == '\n')
                {
                    response[index] = '\0';
                    UART_Print(&huart2, "Received response: ");
                    UART_Print(&huart2, response);
                    UART_Print(&huart2, "\n");
                    return 1; // Success
                }
            }
        }
    
        response[index] = '\0';
        UART_Print(&huart2, "Response Timeout\n");
        return 0; // Timeout or failure
    }
    
    void UART_Print(UART_HandleTypeDef *huart, const char *str)
    {
        HAL_UART_Transmit(huart, (uint8_t*)str, strlen(str), HAL_MAX_DELAY);
    }
    
    void printHex(const uint8_t *data, const uint32_t numBytes)
    {
        char buffer[3];
        for (uint32_t i = 0; i < numBytes; i++)
        {
            snprintf(buffer, sizeof(buffer), "%02X ", data[i]);
            UART_Print(&huart2, buffer);
        }
        UART_Print(&huart2, "\n");
    }
    
    uint8_t readPacket(uint16_t timeout)
    {
        UART_Print(&huart2, "Reading packet...\n");
        uint16_t origtimeout = timeout, replyidx = 0;
        uint8_t packetbuffer[BUFSIZE] = {0};
    
        while (timeout--)
        {
            if (replyidx >= 20) break;
            if((packetbuffer[1] == 'B') && replyidx == PACKET_BUTTON_LEN)
                break;
            uint8_t byte;
            HAL_StatusTypeDef status = HAL_SPI_Receive(&hspi2, &byte, 1, HAL_MAX_DELAY);
    
            if (status == HAL_OK)
            {
                if (byte == '!')
                {
                    replyidx = 0;
                }
                packetbuffer[replyidx++] = byte;
                timeout = origtimeout; // Reset timeout after receiving a byte
    
                // If a newline character is received, end of packet
                if (byte == '\n')
                {
                    break;
                }
            }
    
            if (timeout == 0) break;
            HAL_Delay(1); // Delay to prevent CPU overload
        }
    
        packetbuffer[replyidx] = 0;
    
        if (!replyidx) return 0;
        if (packetbuffer[0] != '!') return 0;
    
        uint8_t xsum = 0;
        uint8_t checksum = packetbuffer[replyidx - 1];
    
        for (uint8_t i = 0; i < replyidx - 1; i++)
        {
            xsum += packetbuffer[i];
        }
        xsum = ~xsum;
    
        if (xsum != checksum)
        {
            UART_Print(&huart2, "Checksum mismatch in packet: ");
            printHex((const uint8_t *)packetbuffer, replyidx);
            return 0;
        }
    
        return replyidx;
    }
    
    /* 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 */

 

 

I want to send a data frame from my phone (like pressing a button) and receive data back to my phone (like ‘button 6 is pressed’) with the Bluetooth module.

10 REPLIES 10

Some more details would help - see the Posting Tips:

Your STM32 board details.

Show your schematic of how you have the module connected to the STM32 

Have you used an oscilloscope or logic analyser to see what's happening on the wires.

 


@Paulo971 wrote:
When I use my arduino and the demo code it works perfectly 

 


So compare & contrast what happens on the Arduino with what happens on the STM32

  • compare & contrast scope/analyser traces;
  • step each in its debugger - compare & contrast;
  • add extra diagnostic UART traces in each to see what's going on.

 

PS:

 


@Paulo971 wrote:
Adafruit module in SPI communication

Did you have a particular reason for using SPI rather than the UART version?

https://www.adafruit.com/product/2479

 

PPS:

The AT commands are described here: 

https://learn.adafruit.com/introducing-the-adafruit-bluefruit-spi-breakout/at-commands

(they don't show it, so I'm unclear whether the commands need a CR terminator - check with Adafruit)

Before jumping into a complete application, have you first tested that you can send "AT" and receive an "OK" reply?

https://learn.adafruit.com/introducing-the-adafruit-bluefruit-spi-breakout/standard-at

There's no point going any further before you have that working ...

Hey @Andrew Neil

I'm using the STM32F401RE. Below are some images of the configuration and connection.

Paulo971_0-1734448481420.pngPaulo971_1-1734448492880.png

 

Paulo971_2-1734449034398.png

 

Unfortunately, I don't have an oscilloscope or a logic analyser.

I want to use SPI to learn how to communicate with SPI and also because it's faster than UART communication.

 

Best regard.

 

   uint8_t sendCommand(const char* cmd, char* response, uint16_t timeout)
    {
        UART_Print(&huart2, "Sending command: ");
        UART_Print(&huart2, cmd);
        UART_Print(&huart2, "\n");
    
        uint8_t cmdLength = strlen(cmd);
        HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);
    
        for (uint8_t i = 0; i < cmdLength; i++)
        {
            if (HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd[i], 1, HAL_MAX_DELAY) != HAL_OK)
            {
                UART_Print(&huart2, "SPI Transmit Error\n");
            }
        }

There's no need to send the bytes individually like that - HAL_SPI_Transmit can send a whole buffer in one go.

Also, rather than just say "Error", say what error you get:

    uint8_t sendCommand(const char* cmd, char* response, uint16_t timeout)
    {
        UART_Print(&huart2, "Sending command: ");
        UART_Print(&huart2, cmd);
        UART_Print(&huart2, "\n");
    
        HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);

        HAL_StatusTypeDef HAL_Status = HAL_SPI_Transmit(&hspi2, cmd, strlen(cmd), HAL_MAX_DELAY) 
        if( HAL_Status != HAL_OK)
        {
            printf( "SPI Transmit Error: %d\n", HAL_Status  );
        }

See here for how to direct printf to your UART, or just write yourself a little function to print a numeric value - like your printHex.

 


@Paulo971 wrote:

Unfortunately, I don't have an oscilloscope or a logic analyser.


They really are key tools for working with embedded microcontrollers like this.

Basic PC-based logic analysers are available from ebay, Amazon, et al for around $10

 


@Paulo971 wrote:

I want to use SPI to learn how to communicate with SPI


This seems a rather bizarre application for SPI; for learning, it might be better to go with a more "standard" peripheral - at least to start with.

eg, https://www.microchip.com/en-us/development-tool/pkserial-spi1 

Or any of the many SPI breakout boards from Adafruit et al.

 


@Paulo971 wrote:

also because it's faster than UART communication.


That's going to be of no benefit with a BLE module: BLE is not a high-speed protocol - a UART will be fine.

Paulo971
Associate III

@Andrew Neil  I've made the change in my code but I'm still stuck with the same ‘ Command sent, waiting for response...’ message.

 

uint8_t sendCommand(const char* cmd, char* response, uint16_t timeout)
{
    UART_Print(&huart2, "Sending command: ");
    UART_Print(&huart2, cmd);
    UART_Print(&huart2, "\n");

    //uint8_t cmdLength = strlen(cmd);
    HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);
    HAL_StatusTypeDef HAL_Status = HAL_SPI_Transmit(&hspi2, cmd, strlen(cmd), HAL_MAX_DELAY);
    if( HAL_Status != HAL_OK)
    {
    	UART_Print(&huart2 ,"SPI Transmit Error: %d\n" + HAL_Status  );
    }

    uint8_t newline = '\n';
    if (HAL_SPI_Transmit(&hspi2, &newline, 1, HAL_MAX_DELAY) != HAL_OK)
    {
        UART_Print(&huart2, "SPI Transmit Error\n");
    }

    HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_SET);

    UART_Print(&huart2, "Command sent, waiting for response...\n");

    uint32_t startTick = HAL_GetTick();
    uint8_t index = 0;

    while ((HAL_GetTick() - startTick) < timeout)
    {
        uint8_t byte;
        if (HAL_SPI_Receive(&hspi2, &byte, 1, HAL_MAX_DELAY) == HAL_OK)
        {
            response[index++] = byte;
            if (byte == '\n')
            {
                response[index] = '\0';
                UART_Print(&huart2, "Received response: ");
                UART_Print(&huart2, response);
                UART_Print(&huart2, "\n");
                return 1; // Success
            }
        }
    }

    response[index] = '\0';
    UART_Print(&huart2, "Response Timeout\n");
    return 0; // Timeout or failure
}

 

 

I already have my print uart function

 

void UART_Print(UART_HandleTypeDef *huart, const char *str)
{
    HAL_UART_Transmit(huart, (uint8_t*)str, strlen(str), HAL_MAX_DELAY);
}
void printHex(const uint8_t *data, const uint32_t numBytes)
{
    char buffer[3];
    for (uint32_t i = 0; i < numBytes; i++)
    {
        snprintf(buffer, sizeof(buffer), "%02X ", data[i]);
        UART_Print(&huart2, buffer);
    }
    UART_Print(&huart2, "\n");
}

 

 

@Andrew Neil when i try to debug i stop at Hardfault_Handler that return to function sendCommand inside the while ((HAL_GetTick() - startTick) < timeout)

    uint32_t startTick = HAL_GetTick();
    uint8_t index = 0;

    while ((HAL_GetTick() - startTick) < timeout)
    {
        uint8_t byte;
        if (HAL_SPI_Receive(&hspi2, &byte, 1, HAL_MAX_DELAY) == HAL_OK)
        {
            response[index++] = byte;
            if (byte == '\n')
            {
                response[index] = '\0';
                UART_Print(&huart2, "Received response: ");
                UART_Print(&huart2, response);
                UART_Print(&huart2, "\n");
                return 1; // Success
            }
        }
    }

@Paulo971 wrote:

I already have my print uart function


sure - you can use them.


@Paulo971 wrote:

when i try to debug i stop at Hardfault_Handler ...

So your code is crashing - with a Hard Fault.

On debugging Hard Faults - both Cortex-M in general, and STM32 in particular:

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/tac-p/708193/highlight/true#M51

 


@Paulo971 wrote:

... that return to function sendCommand inside the while


The Hard Fault handler wouldn't usually return at all ?

@Andrew Neil i mean when im in the debug its stop at the hardfault function and the IDE show me that on the left 

Paulo971_0-1734457218038.png