K Manos
K Manos

Reputation: 507

Why does SPI not work with my STM32f4DISCOVERY?

I've been stuck with this one for a while. I've followed a few examples online, but with no success. I cannot get it working with my STM32F4Discovery. I have an external chip (SX1272 from Semtech to be more specific) with whom I try to have an SPI communication. It is all kids games when doing it via Arduino, but no luck with ST product. I've used oscilloscope and it showed that the MOSI command is sent, but there is no MISO going out. (With Arduino it's good). Here's my code:

#include "main.h"

void init_SPI1(void){   


  GPIO_InitTypeDef GPIO_InitStruct; 
  SPI_InitTypeDef SPI_InitStruct; 

  // enable clock for used IO pins 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 

  /* configure pins used by SPI1 
  * PA5 = SCK 
  * PA6 = MISO 
  * PA7 = MOSI 
  */ 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5; 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; 
  GPIO_Init(GPIOA, &GPIO_InitStruct); 

  // connect SPI1 pins to SPI alternate function 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); 

  // enable clock for used IO pins 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); 

  /* Configure the chip select pin 
  in this case we will use PE7 */ 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7; 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; 
  GPIO_Init(GPIOE, &GPIO_InitStruct); 

  GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 high 

  // enable peripheral clock 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); 

  /* configure SPI1 in Mode 0  
  * CPOL = 0 --> clock is low when idle 
  * CPHA = 0 --> data is sampled at the first edge 
  */ 
  SPI_InitStruct.SPI_Direction =                SPI_Direction_2Lines_FullDuplex;        // set to full duplex mode, seperate MOSI and MISO lines 
  SPI_InitStruct.SPI_Mode =                     SPI_Mode_Master;                        // transmit in master mode, NSS pin has to be always high 
  SPI_InitStruct.SPI_DataSize =                 SPI_DataSize_8b;                        // one packet of data is 8 bits wide 
  SPI_InitStruct.SPI_CPOL =                     SPI_CPOL_High;                           // clock is low when idle 
  SPI_InitStruct.SPI_CPHA =                     SPI_CPHA_1Edge;                         // data sampled at first edge 
  SPI_InitStruct.SPI_NSS =                      SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high 
  SPI_InitStruct.SPI_BaudRatePrescaler =        SPI_BaudRatePrescaler_64;                // SPI frequency is APB2 frequency / 4 
  SPI_InitStruct.SPI_FirstBit =                 SPI_FirstBit_MSB;                       // data is transmitted MSB first 
  SPI_Init(SPI1, &SPI_InitStruct);  

  SPI_Cmd(SPI1, ENABLE); // enable SPI1 
} 


/* This funtion is used to transmit and receive data  
* with SPI1 
*           data --> data to be transmitted 
*           returns received value 
*/ 
uint8_t SPI1_read(uint8_t data){   
  GPIO_ResetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) low 

  SPI1->DR = data; // write data to be transmitted to the SPI data register 
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete 
  while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore 

  GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) high
  uint8_t ret = SPI1->DR;
  return ret; // return received data from SPI data register 
} 


void SPI1_write(uint8_t address, uint8_t data){ 

  uint16_t comb = (address << 8) | data;
  GPIO_ResetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) low 

  SPI1->DR = address; // write data to be transmitted to the SPI data register 
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete 
  //while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore 

  SPI1->DR = data; // write data to be transmitted to the SPI data register 
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete 
  while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore 

  GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) high   
} 

int main(void){ 

  init_SPI1(); 

  while(1){  
    SPI1_read(0x01); 
  } 
} 

All I get from MOSI is a random ~1.5V peak, which is out of sync.

Upvotes: 1

Views: 2533

Answers (2)

uɐɪ
uɐɪ

Reputation: 2580

Have you tried using the ST configuration tool STM32Cube to generate the initialisation and communications interface code. I used it to generate the clock setup USART, I2C and SPI comms interfaces using DMA transfers in about an hour. It includes a pre-defined configuration for the F4 discovery board. All I had to do was clear the CS line when the transfer was loaded into the DMA and set it again in the transfer complete interrupt callback function.

Upvotes: 0

Chris Stratton
Chris Stratton

Reputation: 40407

/* configure pins used by SPI1 
 * PA5 = SCK 
 * PA6 = MISO 
 * PA7 = MOSI 
 */

This suggests that your MISO (master in, slave out) signal is on PA6

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5; 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; 
  GPIO_Init(GPIOA, &GPIO_InitStruct); 

But this configures PA6 as an output.

Configure PA6 as an input, and try again. If it still doesn't work try injecting a level there through a 1K or so resistor and see if you can get both the voltage to change on the scope and the received value to reflect that at all.

Upvotes: 1

Related Questions