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
    }