cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32F412] SPI issue with MAX7219

MB.2
Associate II

I am trying to transmit through SPI to a MAX7219 chip on my STM32F412G-Discovery board. The system clock is running at 100 MHz. I am using a level shifter to handle the 3.3V -> 5V voltage changing. I have used this IC on an arduino so I do know it works.

I am trying to transmit through HAL_SPI_Transmit and manually controlling the CS line through GPIO.

I am transmitting SPI with this code:

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
uint16_t spiData = 0x0C00;
HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
 
spiData = 0x0C01;
HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
 
spiData = 0x0900;
HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
 
spiData = 0x0303;
HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

PA4 -> CS (set up as manual GPIO)

PA5 -> SCK

PA7 -> MOSI

My SPI1 init code is:

static void MX_SPI1_Init(void)
{
 
 /* SPI1 parameter configuration*/
 hspi1.Instance = SPI1;
 hspi1.Init.Mode = SPI_MODE_MASTER;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
 hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
 hspi1.Init.NSS = SPI_NSS_SOFT;
 hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi1.Init.CRCPolynomial = 10;
 
 if (HAL_SPI_Init(&hspi1) != HAL_OK)
 {
  Error_Handler();
 }
}
 

I checked my logic analyzer and all the waves looked fine. I feel like I am probably missing something simple that's going to make me feel stupid.

1 ACCEPTED SOLUTION

Accepted Solutions
MB.2
Associate II

I appreciate your help. Thanks a lot.

I have it working now.

The issue was that the clock has to go high after each packet. I may have also been sending the wrong packets for it to work. 

To work with an 8x8 LED matrix, I sent the following packets:

Display test 0x0F00

Scan Limit  0x0B07

Intensity  0x0A07

Decode Mode 0x0900

Clear all the LEDs in the display 0x0i00 where i is an integer from 1 to 8 inclusive

Display Off 0x0C00

Display On  0x0C01

Then output your LEDs. I tried the 4 corner points and sent:

0x0181

0x0881

View solution in original post

8 REPLIES 8
TDK
Guru

You don't state what the problem is.

> uint16_t spiData = 0x0C00;

> HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);

You're sending 1 byte (0x00) of a 2-byte value (0x00 0x0C). Is that intentional?

Actually, pretty sure the code as written won't compile, since you're passing a (uint16_t *) value instead of a (uint8_t *).

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

The problem is that the MAX7219 chip doesn't work (change state at all). I've tried several of the LED displays I have with this chip and none work. It doesn't even turn on or accept any of the commands, it seems. I tested the same commands on an Arduino SPI and it worked fine. So it's something I am doing wrong with the SPI on this STM32 chip.

The example compiles and if I write 2 as an argument instead of 1, then it outputs 32 bits instead of 16. I have verified that with both a logic analyzer and oscilloscope.

The example below shows where I send 1 byte. The clock pulses 16 times and it does send the full packet each time.

0693W000003OlSgQAK.png

If I change it to 2 bytes, then I get 32 clock pulses and it sends invalid data. 0693W000003OlT0QAK.png

MB.2
Associate II

According to this post here: https://community.st.com/s/question/0D50X00009kKdg5/halspitransmit-size-is-it-defined-as-a-byte-or-a-word, it looks like that byte is unit counts. So since I have the SPI_DATASIZE_16BIT defined, it is a word count which makes sense according to my post below with the waveforms.

TDK
Guru

> it looks like that byte is unit counts. So since I have the SPI_DATASIZE_16BIT defined, it is a word count which makes sense according to my post below with the waveforms.

Agreed. I missed that.

> So it's something I am doing wrong with the SPI on this STM32 chip.

Your SCK line should be idle low according to the datasheet, but the logic analyzer shows it high as you lower CS for the first time. Transmit a dummy byte with CS high first to get it into the correct state, then do CS low and send the commands you care about.

Data should be latched on the rising edge according to the datasheet. Your logic analyzer is latching data on the falling edge.

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

I tried that but it seems to have no effect. The latching issue seems to have been from the clock not being low when CS goes low.

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
  uint16_t dummyData = 0x0101;
  HAL_SPI_Transmit(&hspi1, &dummyData, 1, HAL_MAX_DELAY);
 
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  uint16_t spiData = 0x0C00;
  HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
  while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
  spiData = 0x0C01;
  HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
  while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
  spiData = 0x0900;
  HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
  while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
  spiData = 0x0303;
  HAL_SPI_Transmit(&hspi1, &spiData, 1, HAL_MAX_DELAY);
  while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

0693W000003OlhgQAC.png

Keep trying.
If the signal sent on the SPI lines is correct, but the chip doesn't respond, it's not an STM32 problem.
Look at the signals sent by the Arduino to see a difference.
Take an analog capture to check for signal integrity.
Gotta be an answer somewhere.
*> while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);*
Since HAL_SPI_Transmit is blocking, this is not needed. It should be READY
as soon as the function returns.
If you feel a post has answered your question, please click "Accept as Solution".
MB.2
Associate II

I appreciate your help. Thanks a lot.

I have it working now.

The issue was that the clock has to go high after each packet. I may have also been sending the wrong packets for it to work. 

To work with an 8x8 LED matrix, I sent the following packets:

Display test 0x0F00

Scan Limit  0x0B07

Intensity  0x0A07

Decode Mode 0x0900

Clear all the LEDs in the display 0x0i00 where i is an integer from 1 to 8 inclusive

Display Off 0x0C00

Display On  0x0C01

Then output your LEDs. I tried the 4 corner points and sent:

0x0181

0x0881

SSimi.1
Associate II

Hi,

can your show me your code? It would be a nice inspiration, because I have a project, that is like this.

Thanks and best regards.