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.

This discussion is locked. Please start a new topic to ask your question.
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