Electronic – STM32F0 SPI–what am I missing

cmsisspistm32

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);
}

Best Answer

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;