cancel
Showing results for 
Search instead for 
Did you mean: 

What is the proper way to send hex characters using HAL_SPI_Transmit?

SScot.3
Associate II

New to STM32s and somewhat new to C and I need a bit of advice.

I am trying to send different number of hex characters to the SPI interface.

I have used HAL_SPI_Transmit (&hspi1, (0xB8, 0x03, 0x00),3, 100);

however, I get errors. I cannot use variables as the SPI transmit data is based on keypresses.

Some transmissions will only be 1 byte and others may be up to 5 bytes.

I have searched Google, YouTube and found nothing that helps.

There is I am certain, a way to just push hex chars out of the SPI bus, but how?

I feel this is so basic that I have overlooked it somewhere, where can I go look?

Regards to All.

8 REPLIES 8
TDK
Guru

> I cannot use variables as the SPI transmit data is based on keypresses.

Why do keypresses prevent you from using variables?

uint8_t data[] = {0xB8, 0x03, 0x00};
HAL_SPI_Transmit(&hspi1, data, sizeof(data), 1000);

Sending 1 vs 5 bytes should be a straightforward task to achieve.

Edit: there are many examples in the CubeMX repository you can use as a reference, including some which use the SPI peripheral.

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

Thanks TDK. I tried your advice, and I get an error 'a label can only be part of a statement and a declaration is not a statement'.

I understand what you said and it makes sense in how you said it should work, I am just not as practiced to see what is still wrong.

I will also add the CubeMX repository to my searches along with Google and Youtube.

This has been a great resource for those who are just starting to use STM chips - used Microchip PICs for 30 years...... 32 bits beats 8 any day!

My reference to keys is some keys only need to transmit 1 hex byte while others need to transmit up to 5 perhaps 7 hex bytes.

case '4':
    uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x00};
    HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100);		//send HEX B8-03-00 out SPI - high volume
break;

It sounds like you have invalid C syntax issues. Without the full error message along with the lines around which it complains about, it’s hard to solve. Perhaps your switch case syntax is invalid.
If statements are a better way to go than switch case statements. They are cleaner, easier to read, and less likely to mess up.
If you feel a post has answered your question, please click "Accept as Solution".

Thanks. I have always used IF statements, but in my reading online, majority states that the SWITCH and use of CASE statements are better and easier to read. I also had another problem with needing more than a single digit for the CASE statements - there are 17 buttons.

I will re-write and use IF - THEN - ELSE statements. Just wanted to try something new.

I will be happy to share what I am attempting if you wish.

Here is my code - just learning.....

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

#include "stdio.h"

#include "stdint.h"

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

SPI_HandleTypeDef hspi1;

UART_HandleTypeDef huart1;

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_SPI1_Init(void);

static void MX_USART1_UART_Init(void);

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

uint8_t Snd_Tx_Data[5]; //SPI data

// uint8_t SPI_TX_BUF[8];

uint8_t Cntrl_Rx_Data[4]; //RX Data from Nextion - 4 bytes; start-page#-data-end char

int Cntrl; //used for debug

uint8_t Timer; //Var for amount of time to play the audio file selected

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

(Cntrl=Cntrl_Rx_Data[2]); //used for double-check pulling 3rd byte works - Live Expression in debug

switch (Cntrl) //use the 3rd byte in the packet to decide what we send out SPI

{

// case 0:

// Snd_Tx_Data = 0x12; //send 0x12 out SPI

// break;

// case 1:

// Snd_Tx_Data = 0x10; //send 0x10 out SPI

// break;

case 'A':

HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); //turn ON the BLUE and turn OFF the RED

HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, GPIO_PIN_SET);

break;

case 'B':

HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); //turn ON the RED and turn OFF the BLUE

HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, GPIO_PIN_SET);

break;

case 'C':

uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x00};

HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100); //send HEX B8-03-00 out SPI - high volume

break;

case 'D':

uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x80};

HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100); //send HEX B8-03-80 out SPI - med volume

break;

case 'E':

uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x40};

HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100); //send HEX B8-03-40 out SPI - low volume

break;

case 'F':

uint8_t SPI_TX_BUF[] = {0xA4,0x00,0x03, 0xFF, 0xF2};

HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100); //send HEX A4-00-03-FF-F2 out SPI - loop Audio1

break; //need to figure out how to select Audio1-4 1st......

case 'G':

uint8_t SPI_TX_BUF[] = {0xA6,0x00,0x03};

HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100);   //send HEX B8-03-00 out SPI - PLAYs Audio1

break; //need to figure out how to select Audio1-4 1st.......

case 'H':

uint8_t SPI_TX_BUF[] = {0x2A};

HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100);   //send HEX 2A out SPI - STOP

break;

case 'I':

Timer= 20; //set TIMER for 20 minutes

break;

case 'J':

Timer= 30; //set TIMER for 30 minutes

break;

case 'K':

Timer= 45; //set TIMER for 45 minutes

break;

case 'L':

Timer= 60; //set TIMER for 60 minutes

break;

default:

break;

}

HAL_UART_Receive_IT (&huart1, Cntrl_Rx_Data, 4); //restart the interrupt reception mode

}

/* USER CODE END 0 */

/**

 * @brief The application entry point.

 * @retval int

 */

int main(void)

{

 /* USER CODE BEGIN 1 */

HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, GPIO_PIN_SET); //turn OFF LEDs

HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, GPIO_PIN_SET); //turn OFF LEDs

 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

  /* Configure the system clock */

 SystemClock_Config();

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_SPI1_Init();

 MX_USART1_UART_Init();

 /* USER CODE BEGIN 2 */

 HAL_UART_Receive_IT (&huart1, Cntrl_Rx_Data, 4); //Rx data interrupt style

 /* USER CODE END 2 */

 /* Infinite loop */

 /* USER CODE BEGIN WHILE */

 while (1)

 {

 HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4); //visual to use for debug

 HAL_Delay(750);

  /* USER CODE END WHILE */

TDK
Guru

In this case (hah), you have multiple definitions of SPI_TX_BUF. Each case statement is in the same scope. If you want different scopes, you need to put them within brackets. For example:

...
    case 'C':
      {
        uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x00};
        HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100); //send HEX B8-03-00 out SPI - high volume
        break;
      }
    case 'D':
      {
        uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x80};
        HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100); //send HEX B8-03-80 out SPI - med volume
        break;
      }
...

Once I fixed that, it compiled for me without issue.

However, there are still bugs. You always send 3 characters regardless of the length of the data. Surely this is not intended.

      uint8_t SPI_TX_BUF[] = {0xA4, 0x00, 0x03, 0xFF, 0xF2};
      HAL_SPI_Transmit(&hspi1, SPI_TX_BUF, 3, 100); //send HEX A4-00-03-FF-F2 out SPI - loop Audio1

It's also odd to have an assignment statement within parentheses. But apparently it does compile fine.

(Cntrl=Cntrl_Rx_Data[2]);

Also, variables modified within IRQ handlers and also used in the main loop, or used in multiple IRQ handlers, should be declared as volatile so the compiler doesn't optimize out access. This applies to Cntrl, Timer, and Cntrl_Rx_Data at least.

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

Thanks again TDK!

I made the suggested changes and voila! I also made the byte sent - those were cut and pasted and I (hope) would've changed those before actually trying to send data.

Not sure where my parentheses came from but I wish to code in a more perfect fashion so those have also been removed.

This is a little project for a friend of mine and I thought it would be a great one on which to learn. I should've used these procs years ago! Now happily retired but can't watch TV all day so I will continue to work out freebie stuff for friends and with yours and others, I will get there.

Again, many thanks for your time and interest. I am making progress.

Next, to figure out what 'volatile' means and how to use it - hello Google........

Regards,

Steve

Add curly braces:

case '4': {
    uint8_t SPI_TX_BUF[] = {0xB8,0x03,0x00};
    HAL_SPI_Transmit (&hspi1, SPI_TX_BUF,3,100);		//send HEX B8-03-00 out SPI - high volume
}
break;

TL;DR this is limitation of C99, not existing in C++.

More to this, just eliminate the arrays altogether:

case '4':
    HAL_SPI_Transmit (&hspi1, "\xB8\x03\x00", 3,100);
break;