title: STM32f4 SPI DMA receive
body: <p>I have STM32F4407VGT6 controller on board STM32F4 Discovery. I try to read data from the AD7683 ADC using SPI + DMA, but the DMA receive buffer is always empty (all zeroes). In polled mode, everything works fine, but i must read one 16-bit sample value as 3x 8-bit SPI value and use a bit shifts. That is perhaps the problem. My sampling frequency is 48 kHz and and during each period must be read three spi values to get one ADC sample.</p>
  
  <p>AD7683 timing diagram is in <a href="http://www.analog.com/media/en/technical-documentation/data-sheets/AD7683.pdf" rel="nofollow">datasheet</a>, page 5.</p>
  
  <p>SPI comunication on pins is fine. Here is screen from analyzer: <a href="http://www.imagehosting.cz/?v=spianalyze.png" rel="nofollow">pic</a></p>
  
  <p>Does anyone know how to solve this, or where the problem is ?</p>
  
  <p>Thanks in advance.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>#define DMAbufferSizeRx 3
  __IO uint8_t DMAbufferRx[DMAbufferSizeRx];
  
  #define DMAbufferSizeTx 1
  __IO uint8_t DMAbufferTx[DMAbufferSizeTx] ;
  
  void DMAconfig(void)
  {
  
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Enable the DMA Stream IRQ Channel */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&amp;NVIC_InitStructure);
  
  
  
  
  
  DMA_InitTypeDef DMA_InitStructure;
  
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&amp;(SPI3-&gt;DR));
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  
  
  
  
  // Configure Tx DMA
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &amp;DMAbufferTx[0];
  DMA_InitStructure.DMA_BufferSize = DMAbufferSizeTx;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_Cmd(DMA1_Stream5, DISABLE);
  while (DMA1_Stream5-&gt;CR &amp; DMA_SxCR_EN);
  DMA_Init(DMA1_Stream5, &amp;DMA_InitStructure);
  
  
  /* Configure Rx DMA */
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &amp;DMAbufferRx[0];
  DMA_InitStructure.DMA_BufferSize = DMAbufferSizeRx;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_Cmd(DMA1_Stream0, DISABLE);
  while (DMA1_Stream0-&gt;CR &amp; DMA_SxCR_EN);
  DMA_Init(DMA1_Stream0, &amp;DMA_InitStructure);
  
  
  
  DMA_ITConfig(DMA1_Stream0, DMA_IT_TC , ENABLE); //| DMA_IT_HT
  
  /* Enable the DMA channel */
  
  DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_FEIF0|DMA_FLAG_DMEIF0|DMA_FLAG_TEIF0|DMA_FLAG_HTIF0|DMA_FLAG_TCIF0);
  DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_FEIF5|DMA_FLAG_DMEIF5|DMA_FLAG_TEIF5|DMA_FLAG_HTIF5|DMA_FLAG_TCIF5);
  
  
  DMA_Cmd(DMA1_Stream0, ENABLE); // Enable the DMA SPI TX Stream
  DMA_Cmd(DMA1_Stream5, ENABLE); // Enable the DMA SPI RX Stream
  
  
  // Enable the SPI Rx/Tx DMA request
  SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, ENABLE);
  SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
  
  SPI_Cmd(SPI3, ENABLE);
  
  }
  
  
  
  
  
  
  void DMA1_Stream0_IRQHandler(void)  
  {
    /* Test on DMA Stream Transfer Complete interrupt */
    if(DMA_GetITStatus(DMA1_Stream0, DMA_IT_TCIF0))
    {
      /* Clear DMA Stream Transfer Complete interrupt pending bit */
      DMA_ClearITPendingBit(DMA1_Stream0, DMA_IT_TCIF0);
  
        // here is buffer still empty....
    }
  }
  
  
  
  
  
  
  void SPIconfig()
  {
  
  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_DataSize   = SPI_FirstBit_MSB;      
  SPI_InitStructure.SPI_CPOL     = SPI_CPOL_High;            
  SPI_InitStructure.SPI_CPHA     = SPI_CPHA_2Edge;     
  SPI_InitStructure.SPI_NSS     = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; 
  
  SPI_InitStructure.SPI_BaudRatePrescaler  =SPI_BaudRatePrescaler_16; 
  SPI_InitStructure.SPI_CRCPolynomial   = 0; 
  
  SPI_Init(SPI3, &amp;SPI_InitStructure);                         
  SPI_CalculateCRC(SPI3, DISABLE);                         
  SPI_Cmd(SPI3,ENABLE);                       
  }   
  
  
  
  
  void RCCenable(void)
  {
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,  ENABLE);  
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA1, ENABLE);
  }
  
  
  
  
  
  
  void GPIOconfig(void)
  {
  
  GPIO_InitTypeDef GPIO_InitDef;
  
  GPIO_InitDef.GPIO_Pin =  REG_ON_OFF | ADC_DRIVER_ON_OFF | GPIO_Pin_6;
  GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
  GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitDef.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_Init(GPIOE, &amp;GPIO_InitDef);
  
  
  
  GPIO_InitTypeDef GPIO_InitStructure;
  
  GPIO_InitStructure.GPIO_Pin   = SDATA | MOSI | SCLK;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF; 
  GPIO_Init(GPIOB, &amp;GPIO_InitStructure);
  
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI3); 
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);
  
  
  
  GPIO_InitStructure.GPIO_Pin   = CS;
  GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_OUT; 
  GPIO_InitStructure.GPIO_PuPd   = GPIO_PuPd_UP;   
  GPIO_Init(GPIOD, &amp;GPIO_InitStructure);
  
  GPIO_SetBits(GPIOD,CS); 
  }
  
  
  
  
  void TIM2_IRQHandler(void)
  {
      if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
      {
          TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  
          GPIO_ToggleBits(GPIOD,CS);
  
      }
  }
  
  
  
  void TIM2_Config(void)
  {
  NVIC_InitTypeDef NVIC_InitStructure;
  
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&amp;NVIC_InitStructure);
  
  
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  
  TIM_TimeBaseStructure.TIM_Period = 875; 
  TIM_TimeBaseStructure.TIM_Prescaler = 0; 
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &amp;TIM_TimeBaseStructure);
  
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  
  TIM_Cmd(TIM2, ENABLE);
  }
  </code></pre>