AnsweredAssumed Answered

SPI Rx buffer not reading

Question asked by Arno Thiele on Aug 30, 2017
Latest reply on Aug 31, 2017 by Arno Thiele
Hello,
I am trying to get my MCP3204 ADC to run with my STM32F4. Unfortunately all I get from my SPI_I2S_ReceiveData() function is a bunch of zeros. According to my oscilloscope everything looks normal. I am getting a clock signal, a MOSI transmission to the ADC that looks normal and is in the right range, the chip select signal looks fine and the ADC is answering with what looks like a word that reacts accurately to potentiometer movement. But my STM32F4 just won’t read anything from the SPI4->DR register. 
I also tried a simple loopback test connecting MISO and MOSI. The result is the same. All signals look normal on my scope, all the flags are set and cleared, all clocks are running but the SPI read register still appears empty. I also tried the same on SPI2 with the same negative result.
Also I can assure that the problem is not with the <*pitchP> pointer or anything down stream, since it works just fine if I replace <value> with any constant integer value.
Unfortunately I don’t have a multi channel scope or logic analyzer to look at the timing at the pins but the code for the send/receive procedure I am using is very basic and by the book and it works in countless other projects. 
Any help is much appreciated!
void init_Clocks(void)
{
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2, ENABLE);  // maybe try DMA for ADC at some point
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_SPI4 | RCC_APB2Periph_ADC1, ENABLE); // SPI1 Clock - DAC, SPI4 Clock - ADC, ADC1 Clock
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // TIM2 Timer - Clock prescale 2
}

void init_ADC_ext (void)
{

  // Initialize CS pin.
  GPIO_InitTypeDef gpio_init;
  gpio_init.GPIO_Pin = GPIO_Pin_12;
  gpio_init.GPIO_Speed = GPIO_Fast_Speed;
  gpio_init.GPIO_Mode = GPIO_Mode_OUT;
  gpio_init.GPIO_OType = GPIO_OType_PP;
  gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &gpio_init);

  // Initialize CLK pin.
  gpio_init.GPIO_Pin = GPIO_Pin_13;
  gpio_init.GPIO_Speed = GPIO_Fast_Speed;
  gpio_init.GPIO_Mode = GPIO_Mode_AF;
  gpio_init.GPIO_OType = GPIO_OType_PP;
  gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &gpio_init);

  // Initialize MOSI pin.
  gpio_init.GPIO_Pin = GPIO_Pin_1;
  gpio_init.GPIO_Speed = GPIO_Fast_Speed;
  gpio_init.GPIO_Mode = GPIO_Mode_AF;  
  gpio_init.GPIO_OType = GPIO_OType_PP;
  gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &gpio_init);

  // Initialize MISO pin. This one is not receiving anything.
  gpio_init.GPIO_Pin = GPIO_Pin_11;
  gpio_init.GPIO_Speed = GPIO_Fast_Speed;
  gpio_init.GPIO_Mode = GPIO_Mode_IN;   // MISO must be configured as HI-Z IN, not AF!!
//   gpio_init.GPIO_OType = GPIO_OType_PP;
  gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &gpio_init);

  // Initialize SPI
  SPI_InitTypeDef spi_init;
  spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  spi_init.SPI_Mode = SPI_Mode_Master;
  spi_init.SPI_DataSize = SPI_DataSize_16b; // SPI_DataSize_8b for ADCread()  
  spi_init.SPI_CPOL = SPI_CPOL_Low;
  spi_init.SPI_CPHA = SPI_CPHA_1Edge;
  spi_init.SPI_NSS = SPI_NSS_Soft;
  spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // Prescaler_64 for ADCread()
  spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
  spi_init.SPI_CRCPolynomial = 7;
  SPI_Init(SPI4, &spi_init);
//  GPIO_SetBits(GPIOB, GPIO_Pin_12);
  SPI_Cmd(SPI4, ENABLE);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1,  GPIO_AF_SPI4);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_SPI4);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF6_SPI4);

}


void loopback(void){

   uint16_t value = 0;

   while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
   SPI_I2S_SendData(SPI4, 440);
   while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
           value = SPI_I2S_ReceiveData(SPI4);

   *pitchP = value;
}

void ADCread(void){
  
           uint16_t value = 0;

  GPIO_ResetBits(GPIOB, GPIO_Pin_12);

  // Send header
  while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
  SPI_I2S_SendData(SPI4, 0b00000110);  // or 0x04 | 0x02
  while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
  SPI_I2S_ReceiveData(SPI4);

  // Send channel / receive first part
  while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
  SPI_I2S_SendData(SPI4, 0b00000000);  // 0b01000000 for the other channel
  while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
  value = (SPI_I2S_ReceiveData(SPI4) & 0xf) << 8; 
 

           // Send trailing word / receive second part
  while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
  SPI_I2S_SendData(SPI4, 0x00);
  while (SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
  value |= SPI_I2S_ReceiveData(SPI4);

  GPIO_SetBits(GPIOB, GPIO_Pin_12);

  *pitchP = value;
}



int main (){

SystemInit();
init_Clocks();
init_ADC_ext();

while(1) {
Loopback();
ADCread();
}
}

Outcomes