cancel
Showing results for 
Search instead for 
Did you mean: 

No clock signal on PA5 bit(SPI1-SCK)

PPopo
Senior

Hello,

I'm learning to use the SPI module. I'm using an STM32F446RET development board. I want to configure the SPI1 module and send some message 'out into the world'(this means I only have one master devices which sends some bytes and no slave to recieve them).

I have configured the pins in this fasion:

  • PA5: Alternate function(5-SPI1_SCK), push-pull, fast speed, no PUPD
  • PA6: Alternate function(5-SPI1_MOSI), same configuration as PA5
  • PA7(MISO) and PA4(NSS) I have not configured as I'm not using any slaves

I have written a code that's supposed to send 1's continuously.

main.c(please ignore my comments at the end :D)

#include "init_functions.h" 
#include<string.h>
 
void SPI_SendData(uint8_t *strbuff, uint32_t len)
{
  while(len > 0)
	{
	  while( !(SPI1->SR & 2) ); // wait untill tx buffer is not empty
		SPI1->DR = *strbuff;
		len--;
		strbuff++; // point to next byte
	}
}
 
void SPI_SendOnes()
{
	while( (SPI1->SR & 2) == 0 ); // wait untill tx buffer is not empty
	SPI1->DR = 1;
	int a = SPI1->DR;
}
 
int main()
{
 char user_data[] = "Hello world";
	
 init_GPIOS_SPI1();
 config_SPI1();
 
 while(1)
 {
  // send data
	SPI_SendOnes();
  while( (SPI1->SR & (1 << 7)) ) // wait till SPI is not busy
	{
	
	}
	
  // disable spi
  //SPI1->CR1 &= ~( 1 << 6 );
	
 }
 return 0;
}
 
//SPI1->SR[bit 7] -> busy flag(0 - not busy; 1 - SPI (or I2S) is busy in communication or Tx buffer is not empty ). set/cleared by hw	
//SPI1->SR[bit 1] -> transmit buffer empty(1 - tx buffer empty; 0 not empty)
//SPI1->SR[bit 0] -> recieve buffer...
//SPI1->DR -> data register(data recieved or to be transmitted). A write to the data register will write into the Tx buffer and a read 
// from the data register will return the value held in the Rx buffer.

int_functions.c

#include "init_functions.h"
 
void init_GPIOS_SPI1(void)
{
 /* 
	SPI1 - APB2(90Mhz)
	Address range SPI_1: 0x4001 3000 - 0x4001 33FF 
  PA4 - SPI1_NSS
  PA5 - SPI1_SCK
  PA6 - SPI1_MISO
  PA7 - SPI1_MOSI	
 */
	
 /* Enable GPIOA bus clock */ 
 RCC->AHB1ENR |= 1;
 
 /* Configure SPI pins */
 //SCLK(PA5)
 GPIOA->MODER |= ( 1 << 11 );     // af mode
 GPIOA->MODER &= ~( 1 << 10 );
 
 GPIOA->OTYPER &= ~( 1 << 5 );    // push-pull
 
 GPIOA->OSPEEDR |= ( 1 << 11 );   // fast speed
 GPIOA->OSPEEDR &= ~( 1 << 10 );
 
 GPIOA->PUPDR &= ~( 1 << 10 );    // no pull up/down
 GPIOA->PUPDR &= ~( 1 << 11 );
 
 GPIOA->AFR[0] |= ( 1 << 22 );    // AF5(SPI1_SCK)
 GPIOA->AFR[0] |= ( 1 << 20 );
	
	
	
 //MOSI(PA6)
 GPIOA->MODER |= ( 1 << 13 );     // af mode
 GPIOA->MODER &= ~( 1 << 12 );
 
 GPIOA->OTYPER &= ~( 1 << 6 );    // push-pull
 
 GPIOA->OSPEEDR |= ( 1 << 13 );   // fast speed
 GPIOA->OSPEEDR &= ~( 1 << 12 );
 
 GPIOA->PUPDR &= ~( 1 << 12 );    // no pull up/down
 GPIOA->PUPDR &= ~( 1 << 13 );
 
 GPIOA->AFR[0] |= ( 1 << 26 );    // AF5(SPI1_MOSI)
 GPIOA->AFR[0] |= ( 1 << 24 );
	
 //MISO(PA7)
 
 //NSS(PA4)
}
 
void config_SPI1(void)
{
	RCC->APB2ENR |= ( 1 << 12 ); //SPI1 clock enable
	SPI1->CR1 |= ( 1 << 15 );    // 1 line bidirectional mode selected
	SPI1->CR1 |= ( 1 << 14 );    // output enabled: transmit only mode
	SPI1->CR1 &= ~( 1 << 11 );   // 8-bit data frame format for transmission/reception
	SPI1->CR1 &= ~( 1 << 7 );    // MSB transmitted first
	SPI1->CR1 |= ( 1 << 6 );     // SPI1 enabled
	SPI1->CR1 |= ( 1 << 2 );     // master configuration
  SPI1->CR1 |= ( 1 << 1 );     // CK to 1 when idle
  SPI1->CR1 &= ~( 1 << 0 );	   // first clock transition is the first data capture edge
}

I have checked with an oscilloscope and expected to see a continous clock signal as the application is supposed to continously send 1's to the outside world. I have put the probe on the PA5(CLK) pin but it just stays low.

I then inspected the code and I have discovered that the code halts when it gets to this line the second time:

while( (SPI1->SR & 2) == 0 ); // wait untill tx buffer is not empty

Which means the data I want to send gets put into the transmit/recieve buffer but then it does not get put into the TX buffer to get transmited through the bus into the 'world'.

I cannot see what I've configured wrong. Please if possible help me correct this. Thanks.

15 REPLIES 15
turboscrew
Senior III

It tends to be that if the SPI drives the NSS-line, and it's driven in different state than the SPI tries to drive it, the SPI makes mode error and becomes a slave.

Just programming the pin output is not enough, because the SPI still listens to it. So, you might want to use the software slave management (SSM in CR1 = 1) and tell the SPI to stay master (SSI in CR1 = 1) and disable NSS output (SSOE in CR2 = 0) and handle the NSS by SW using a plain GPIO.

That is: IF there is a mode error (check the status register).

PPopo
Senior

Hello,

I have configured the NSS pin as some people said and now it works.

You don't need to configure NSS *pin*. It's enough to set both SSM=1 and SSI=1, as turboscrew wrote above.

JW

PPopo
Senior

thank you all for the quick and good answers :folded_hands:

rlamb.1
Associate

I have the same SPI1 PA5 problems on stm32f730 and read the old thread on " STM32F7: SPI1 does not assert RXNE or RXDMA-request with the same settings SPI2 and SPI4 do." Conclusion was: "Some progress here: if I (in GPIO config) move SCK from PA5 to PB3, RXNE gets asserted! Any ideas what could be wrong with PA5? "

The "solution" was using PB3 instead of PA5 for the sclk. Had to spin new pcbs (bit-bang spi for initial workaround). I have not seen an errata on this though. It would be nice.

Please start a new thread, describing exactly your hardware/software, the symptoms, and give a readout of relevant SPI and GPIO registers, giving a link to this thread.

JW