5

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);
}
iter
  • 341
  • 1
  • 10
  • 4
    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. – PascalS Dec 02 '19 at 05:24
  • Possibly better: use LL libraries – Alex I Dec 02 '19 at 07:21

1 Answers1

9

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;
Jeroen3
  • 21,976
  • 36
  • 73