SPI Receive not working on STM32F4

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
k3nt
Posts: 2
Joined: Sun Aug 24, 2014 1:48 am

SPI Receive not working on STM32F4

Post by k3nt »

Hello,

I am trying to read from an ADC chip http://www.ti.com/lit/ds/symlink/ads1232.pdf using SPI2 and I'm not having any success yet.

There is no need for MOSI, since the chip only spews out data. Also is it mandatory that I use the spiSelectI()? Going low on this line shuts down the ADC.

When I initiate the Receive routine from the serial shell, the DOUT(MISO) line goes high for a bit, but the SCK line only clocks out one pulse.

Any help or suggestions is greatly appreciated!!

My relevant code:

Code: Select all

/*
 * SPI2 configuration structure.
 * Speed 21MHz, CPHA=0, CPOL=0, 16bits frames, MSb transmitted first.
 * The slave select line is the pin 12 on the port GPIOB.
 */
static const SPIConfig spi2cfg = {
  spicb,
  /* HW dependent part.*/
  GPIOB,
  12,
  SPI_CR1_DFF
};

/*
   * Initializes the SPI driver 2. The SPI2 signals are routed as follow:
   * PB12 - NSS.
   * PB13 - SCK.
   * PB14 - MISO.
   */

  palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL |
                           PAL_STM32_OSPEED_HIGHEST);           /* NSS.     */
  palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) |
                           PAL_STM32_OSPEED_HIGHEST);           /* SCK.     */
  palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5) |
                             PAL_STM32_OSPEED_HIGHEST);           /* MISO.    */

  palSetPad(GPIOB, 12);
  spiStart(&SPID2, &spi2cfg);

static void cmd_adc(BaseSequentialStream *chp, int argc, char *argv[]) {

  uint32_t value = 0;
  uint16_t samples[2];

  chprintf(chp, "Reading ADC\r\n");

  //spiSelectI(&SPID2);

  /* If data line goes low, data is ready */
  while(palReadPad(GPIOB, GPIOB_SPI2_MISO));

  /* Read 24bits of data, MSB First */
  //chSysLockFromIsr();
  spiStartReceiveI(&SPID2, 3, samples);
  //chSysUnlockFromIsr();

  //palSetPad(GPIOB, 13);

  value = (samples[0] << 16) + samples[1];

  /* Print ADC Data */
  chprintf((BaseSequentialStream *)&SDU1, "ADC Result: %d\r\n", value);

  return;

}

/*
 * SPI end transfer callback.
 */
static void spicb(SPIDriver *spip) {

  /* On transfer end just releases the slave select line.*/
  chSysLockFromIsr();
  //spiUnselectI(spip);
  chSysUnlockFromIsr();
}
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: SPI Receive not working on STM32F4

Post by Giovanni »

Hi,

I can see several problems in you code with I-functions called outside a critical zone, enabling the state checker in chconf.h would reveal that.

spiSelect() and spiUnselect() are required if you need to handle the Chip Select line.

Why are you using the asynchronous functions? you could do spiReceive() instead of spiStartReceive() and you would not need to use a callback.

Also you need to make sure to use the correct settings for SI parameters (CPOL etc), I am not sure if your settings are correct for your device.

Giovanni
k3nt
Posts: 2
Joined: Sun Aug 24, 2014 1:48 am

Re: SPI Receive not working on STM32F4

Post by k3nt »

Giovanni,

Your reply was very helpful, thanks!

I am now using the spiReceive() and this config:

Code: Select all

static const SPIConfig spi2cfg = {
  NULL,
  /* HW dependent part.*/
  GPIOB,
  12,
  SPI_CR1_BR_0 | SPI_CR1_BR_1
};


I now seem to be clocking data in from the ADC.

My last bit of confusion though is the spiReceive() func parameters.

The docs note:
Note:
The buffers are organized as uint8_t arrays for data sizes below or equal to 8 bits else it is organized as uint16_t arrays.


Does this literally mean that if spiReceive() reads 8 or more bits, I should be passing it uint16_t arrays, and not uint8_t?

And the number of words, I presume means 8bit words yes? Regardless of the size of int.

[in] n number of words to receive


The ADC outputs 24bits in 2's complement

Code: Select all

static void cmd_adc(BaseSequentialStream *chp, int argc, char *argv[]) {

  uint16_t samples[2]; // or uint8_t samples[3]; ?

  /* If data line goes low, data is ready */
  while(palReadPad(GPIOB, GPIOB_SPI2_MISO));

  /* Read 24bits of data, MSB First */
  spiReceive(&SPID2, 3, samples);

  return;

}
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: SPI Receive not working on STM32F4

Post by Giovanni »

Hi,

You can program the STM32 SPI to use 8 bits or 16 bits frames, that pointer points to uint8_t or uint16_t depending on the configured frame size. "n" is always the number of frames, regardless their size so don't confuse it with the size of the buffer in bytes.

Giovanni
Post Reply