AnsweredAssumed Answered

STM32F4: no clock on SPI

Question asked by matt on Jun 12, 2012
Latest reply on Apr 25, 2014 by Clive One
Hello,

I'm trying to use the SPI2 interface on the STM32F4Discovery board. I do not observe anything on the SPI clock and data pins. Clocks and PLL should be initialized correctly since I can toggle an LED. I did not configure any interrupts - as far as I know I do not need them with my code below.

Here my code:

#define SPI_SCLK_PIN                      GPIO_Pin_13
#define SPI_SCLK_PORT                     GPIOB
#define SPI_SCLK_Source                   GPIO_PinSource13

#define SPI_DATA_PIN                      GPIO_Pin_15
#define SPI_DATA_PORT                     GPIOB
#define SPI_DATA_Source                   GPIO_PinSource15

#define SPI_Camera                        SPI2



void init_SPI_Config(void)
{
  SPI_InitTypeDef SPI_InitStruct;
  
  // configure SPI
  SPI_InitStruct.SPI_Direction         = SPI_Direction_1Line_Tx; // has to be updated before receiving
  SPI_InitStruct.SPI_Mode              = SPI_Mode_Master;
  SPI_InitStruct.SPI_DataSize          = SPI_DataSize_8b;
  SPI_InitStruct.SPI_CPOL              = SPI_CPOL_High;          // idle state of clk is high
  SPI_InitStruct.SPI_CPHA              = SPI_CPHA_2Edge;         // TBC ?
  SPI_InitStruct.SPI_NSS               = SPI_NSS_Soft;
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  SPI_InitStruct.SPI_FirstBit          = SPI_FirstBit_MSB;
  SPI_InitStruct.SPI_CRCPolynomial     = 7;
  SPI_Init(SPI_Camera, &SPI_InitStruct);
    
  // disable the SPI, it is enable when actually used
  SPI_Cmd(SPI_Camera, DISABLE);
}


void init_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Pin   = SPI_SCLK_PIN;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
  GPIO_Init(SPI_SCLK_PORT, &GPIO_InitStructure);
  GPIO_PinAFConfig(SPI_SCLK_PORT, SPI_SCLK_Source, GPIO_AF_SPI2);
 
  GPIO_InitStructure.GPIO_Pin   = SPI_DATA_PIN;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
  GPIO_Init(SPI_DATA_PORT, &GPIO_InitStructure);
  GPIO_PinAFConfig(SPI_DATA_PORT, SPI_DATA_Source, GPIO_AF_SPI2);
}


void init_RCC_Config(void)
{
  uint8_t sysclk_source = 1;    // debug only
   
  // set the RCC clock configuration to the default reset state
  RCC_DeInit(); 
 
  // selects the clock source to output on MCO1 pin(PA8)
  RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_5);
 
  // get system clock source
  sysclk_source = RCC_GetSYSCLKSource(); // 0x00: HSI; 0x04: HSE; 0x08: PLL
   
  // High Speed Internal Clock used
  RCC_HSICmd(ENABLE);
 
  // set AHB clock divider
  RCC_HCLKConfig(AHB_CLK_DIVIDER);
 
  // set low speed APB clock divider
  RCC_PCLK1Config(APB1_CLK_DIVIDER);
 
  // set high speed APB clock divider
  RCC_PCLK2Config(APB2_CLK_DIVIDER);
 
  // enable peripheral clocks
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
  RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
 
  // configure PLL
  RCC_PLLConfig(RCC_PLLSource_HSI, 8, 160, 2, 15);
 
  // enable PLL
  RCC_PLLCmd(ENABLE);
  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == 0)
  {
    // wait until PLL clock is stable and can be used as system clock source
  }
 
  // switch to PLL clock as system clock
  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
 
  // Wait till PLL is used as system clock source
  while(RCC_GetSYSCLKSource() != 0x08)
  {}
 
  // get system clock source
  sysclk_source = RCC_GetSYSCLKSource(); // 0x00: HSI; 0x04: HSE; 0x08: PLL
 
  // update system core clock
  SystemCoreClockUpdate();
}


void Com_TX_byte_to_camera(uint8_t* msg)
{
  // set direction to TX
  SPI_BiDirectionalLineConfig(SPI_Camera, SPI_Direction_Tx);
 
  // enable the SPI
  SPI_Cmd(SPI_Camera, ENABLE);
 
  // make sure the transmit buffer is empty
  while (SPI_I2S_GetFlagStatus(SPI_Camera, SPI_I2S_FLAG_TXE) == 0)
  {}
 
  // write message to the transmit buffer (= data register of SPI2)
  SPI_I2S_SendData(SPI_Camera, (uint16_t)(*msg));
 
  // wait until the message is transmitted
  while (SPI_I2S_GetFlagStatus(SPI_Camera, SPI_I2S_FLAG_TXE) == 0)
  {}
  while (SPI_I2S_GetFlagStatus(SPI_Camera, SPI_I2S_FLAG_BSY) == 1)
  {}
 
  // disable the SPI
  SPI_Cmd(SPI_Camera, DISABLE);
}


uint8_t Com_RX_byte_from_camera()
{
  uint16_t tmp = 0;
 
  // set direction to RX
  SPI_BiDirectionalLineConfig(SPI_Camera, SPI_Direction_Rx);
 
  // enable the SPI
  SPI_Cmd(SPI_Camera, ENABLE);
 
  // wait until receive buffer is not empty
  while (SPI_I2S_GetFlagStatus(SPI_Camera, SPI_I2S_FLAG_RXNE) == 0)
  {}
 
  // read byte from receive buffer
  tmp = SPI_I2S_ReceiveData(SPI_Camera);
 
  // disable the SPI
  SPI_Cmd(SPI_Camera, DISABLE);
 
  return (uint8_t)tmp;
}


int main()
{
  Init_Init();

  uint8_t msg8 = 0;
  uint8_t received8 = 0;

  msg8 = 0xB9; 
  Com_TX_byte_to_camera(&msg8);
    
  received8 = Com_RX_byte_from_camera();

  return 0;
}

Outcomes