AnsweredAssumed Answered


Question asked by a. richard on Oct 22, 2010
Latest reply on Oct 22, 2010 by Clive One
I'm trying to talk to an sdcard via SPI with the SPI2 peripheral.
This is my initialisation routine
void SPIInit()

     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  SPI_InitTypeDef   SPI_InitStructure;
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
     //SPI_InitStructure.SPI_CRCPolynomial = 7;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_Init(SPI2, &SPI_InitStructure);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  /*GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

The 'sending' loop is something like this
    for (k = 0; k < 10; k++)
      SPI_I2S_SendData(SPI2, 0x55);
      while((SPI2->SR & SPI_I2S_FLAG_TXE) == 0);

Obviously not very useful for SD card comms, because I've kept tracing back my steps to find out that there's actually no signal on the SPI pins. What I've actually done is set up a led on MOSI and hope to see the led intensity vary as I change the data being sent.
But there's always logic 0 on that pin and nothing else. Sure, you might say - the loop is too short. It was initially at a very large value - 50k, but it took a lot of time. So this brings me to my first issue, for some reason the delay, which should count down from 0x7FFFF takes an instant of a second, probably 0.1-0.2s, while sending 10 characters over SPI with a prescaler of 2 is incredibly slow. The TX out led for the serial blinks twice every second or so (and the data read always shows the longer loop is the actual SPI sending, NOT the break).

I checked the SCK line, nope, there's no clock either. I'm just going to leave this wire that goes to a resistor+led in the SCK pin for now and go for a beer. Ah, there we go. Few minutes leter, the USART TX led isn't blinking anymore. Undoing the last operation, removing the led from SCK, and suddenly it works. Let's put it back, the TX led flashes, so the loop is skipped. Was it lucky? Repeat action, same results, if I wiggle the wire (with a resistor + led in series) the loop keeps skipping. Weird. Checking the code, I see the SCK is likely an input. I set PB13 (SPI2_SCK) to output, reflash, run the code, heh, now the loop is stuck forever, and the usart TX led won't flash.

Also - another oddity. Sometimes after a few minutes the loop gets stuck again, but if I wiggle my hand above the chip, it resumes (as long as I keep my hand above the chip). I suspect some hardcore EMI and a bad configuration. Not really sure what.

I'm currently out for ideas. What might be wrong?
Oddly enough, if I change everything for SPI1 no remap, this works, but I can't use SPI1 because I need the DAC later, and I can't use the SPI1 alternative remap either, because it is shared with the SWD programming pins.

LE: ok, apparently it was later set to slave mode, due to some older code, so the errors make sense now: if clk was an output, the loop would halt, and the EMI would clock it, albeit slowly, thus my hand reacting with it, and the incredibly slow update rate.

So now it works, but not as it should, I still get nothing on the output pins! If I make the output pins flash however, it works, so I know they are inited right. Maybe there's something else I need to set to make the pins work with SPI2 function instead of the timer function?