Please note: We are aware of an issue affecting replies on the Arm Community forums, which may not be loading as expected.

We apologize for any inconvenience and appreciate your patience while we investigate and work to resolve the issue.

Thank you for your understanding.


This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

M0 SPI outputting 16bit not 8bit

I'm using the STM32F030K6T6 M0 processor and C++ in STM32CubeIDE and no matter what I try I'm outputting 16 bits instead of 8.

I created 2 projects; One HAL and the one shown partially below.  I run them in debug and the GPIOA and SPI setting are the same.  The HAL output is 8 bit format as it should be b ut the other outputs 16 bits per transaction as shown in the logic image below.

CSpi::CSpi() {
	// Enable PA clock
	RCC->AHBENR |= (1 << 17);

	// Set PA5, PA6 and PA7 to Alt. Func.
	GPIOA->MODER &= ~(0x3F << 10);
	GPIOA->MODER |= (0x2A << 10);
	GPIOA->AFR[0] &= ~(0xFFF << 20);
}

void CSpi::SpiInit()
{
    RCC->APB2ENR |= (1 << 12);		// enable SPI1 clock

    SPI1->CR1 = 0x31C;				// Master, clk/16, SSM/SSI
    SPI1->CR2 = 0x01708;		// 8 bit
    SPI1->CR1 |= (1 << 6);          // enable SPI1 module
}

bool CSpi::ConfigureChannel(uint8_t chan, GPIO_TypeDef* port, uint16_t pin)
{
	if (chan > MAX_CHANNELS)
		return false;

	_chanInfo[chan].port = port;
	_chanInfo[chan].pin = pin;

    // TODO Figure pin and do shift
	// Set PA4 as output for CS
	port->MODER &= ~(0x03 << (pin << 1));
	port->MODER |= (1 << (pin << 1));

	return true;
}

void CSpi::SetState(uint8_t chan, BSTATE state)
{
	if (chan > MAX_CHANNELS)
		return;

	if (state)
		_chanInfo[chan].port->BSRR = (1 << _chanInfo[chan].pin);
	else
		_chanInfo[chan].port->BSRR = (1 << (_chanInfo[chan].pin + 16));
}

void CSpi::Write(uint8_t chr)
{
   while (!((SPI1->SR)&(1<<1))) {};  // wait for TXE bit to set -> This will indicate that the buffer is empty
   SPI1->DR = chr;  // load the data into the Data Registe

	while (!((SPI1->SR)&(1<<1)));  // wait for TXE bit to set -> This will indicate that the buffer is empty
	while (((SPI1->SR)&(1<<7)));  // wait for BSY bit to Reset -> This will indicate that SPI is not busy in communication
}

and in my main routine I have;

	spi.SpiInit();
	spi.ConfigureChannel(0, GPIOA, 4);
    while(1)
    {
		spi.SetState(0, LOW);
    	spi.Write(0x31);
		spi.SetState(0, HIGH);
    	delay(5);
    }

memx

Not sure what I'm doing wrong.

Any help appreciated.

  • I found the answer to the problem after 2 days of hair pulling.

    uint8_t CSpi::Write(uint8_t chr)
    {
    	while ((SPI1->SR & SPI_SR_TXE) == 0);  // wait for TXE bit to set -> This will indicate that the buffer is empty
    
        // Have to force it to output 8 bits, even though configured for 8.
    	*(volatile uint8_t *)&SPI1->DR = (uint8_t)chr;
    
    	while ((SPI1->SR & SPI_SR_RXNE) == 0);
    	while ((SPI1->SR & SPI_SR_BSY) != 0);  // wait for BSY bit to Reset
    }