5
\$\begingroup\$

I'm trying to send SPI data to a MAX7219 from an STM32F042 (the protocol is one-way without MISO). I must be missing something very obvious. With the code below, the only visible side effect is the GPIO nCS line wiggling. Neither clock nor MOSI show any activity.

What am I missing?

enter image description here

#include "stm32f0xx.h"

int main(void)
{
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
  RCC->AHBENR |= RCC_AHBENR_GPIOBEN;

  // SCK
  GPIOB->MODER |= GPIO_MODER_MODER3_1;  // alternate function
  // GPIOB->OTYPER default push-pull
  // GPIOB->AFR[] default AF 0: SPI1_SCK,

  // MOSI
  GPIOB->MODER |= GPIO_MODER_MODER5_1;  // alternate function

  // soft nCS
  GPIOB->MODER |= GPIO_MODER_MODER4_0;  // GPO
  GPIOB->ODR = GPIO_ODR_4;              // deselect

  // SPI configuration
  SPI1->CR1 |= SPI_CR1_MSTR;            // master mode
  SPI1->CR1 |= SPI_CR1_BR_1;            // spi_sck = SystemCoreClock / 8 = 6 MHz
  SPI1->CR1 |= SPI_CR1_SSI;             // software CS
  SPI1->CR2 |= SPI_CR2_DS_3 | SPI_CR2_DS_2 |
    SPI_CR2_DS_1 | SPI_CR2_DS_0;        // 16 bit format

  SPI1->CR1 |= SPI_CR1_SPE;             // SPI Enable

  // transmit test packet
  while(!(SPI1->SR & SPI_SR_TXE));      // make sure TX buffer is empty
  while(SPI1->SR & SPI_SR_BSY);         // make sure SPI isn't busy

  GPIOB->ODR &= ~GPIO_ODR_4;            // chip select
  uint16_t data = 0xAAAA;               // test packet
  SPI1->DR = data;
  while(!(SPI1->SR & SPI_SR_TXE));      // make sure TX buffer is empty
  while(SPI1->SR & SPI_SR_BSY);         // make sure SPI isn't busy
  GPIOB->ODR |= GPIO_ODR_4;              // deselect

  while(1);
}
\$\endgroup\$
  • 4
    \$\begingroup\$ Why do you not use HAL libraries for the first try? If you don't want to you them in production code, you can eliminate them afterwards. Give STM32CubeMX a try for initializing your SPI bus. \$\endgroup\$ – PascalS Dec 2 '19 at 5:24
  • \$\begingroup\$ Possibly better: use LL libraries \$\endgroup\$ – Alex I Dec 2 '19 at 7:21
9
\$\begingroup\$

Enable SPI_CR1_SSM.
The output now remains high-z since chip select is low.

Aside from clock setup and gpio, this is minimal init for SPI:

SPI2->CR1 |= SPI_CR1_SSM;
SPI2->CR1 |= SPI_CR1_SSI;
SPI2->CR1 |= SPI_CR1_MSTR | SPI_CR1_SPE;
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Thank you! Now I'm getting clock and data out. \$\endgroup\$ – iter Dec 2 '19 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.