AnsweredAssumed Answered

STM32F373 Code Question

Question asked by felix9de on Apr 14, 2015
Latest reply on Apr 23, 2015 by Clive One
Hi everybody,
I have a problem with my code and I hope somebody can help me.

I'm using a STM32F373RC with a ST-LINK / V2.

I want to continuously sample 12 channels of the adc in scan mode and transfer the results via DMA (in circular mode) in an array.  After a half and after a full transfer of the DMA-Controller an interrupt should be triggert. 

I'm using the Debugger of IAR Embedded Workbench and there it looks like the interrupt doesn't work properly. It looks like the half transfer interrupt and the full transfer interrupt occur at the same time. 

I hope I gave you all the information you need.
Maybe somebody can find a bug that I can't see.




My code in main.c:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <stdio.h>
 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ARRAYSIZE (1680*2) // size of the result arrays
#define ADC1_DR_Address 0x4001244C
 
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
volatile uint16_t ADC1ConvertedValues1[ARRAYSIZE]; // arraysize: 1680 * 2
 
/* Private function prototypes -----------------------------------------------*/
static void CLK_Config(void);
static void GPIO_Config(void);
static void DMA_Config(void);
static void ADC_Config(void);
/* Private functions ---------------------------------------------------------*/
 
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontrollers clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f37x.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f37x.c file
     */
 
  /* Add your application code here */
  CLK_Config();
  GPIO_Config();
  DMA_Config();
  ADC_Config();
   
  /* Starts ADC1 Software Conversion */
  ADC_SoftwareStartConv(ADC1);
   
  /* Infinite loop */
  while (1)
  {
 
  }
}
 
/**
  * @brief  System Clock Configuration
  * @param  None
  * @retval None
  */
static void CLK_Config(void)
{
/* Enables the Internal High Speed oscillator (HSI) */
RCC_HSICmd(ENABLE);
   
/* Configures the PLL clock source: a) specifies the PLL entry clock source to be HSI
                                    b) specifies the PLL multiplication factor to be /16 */
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);
     
/* Enables the PLL */
RCC_PLLCmd(ENABLE);
 
/* specifies the clock source used as system clock source  to be PLL*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
 
/* defines the AHB clock divider to be 1 -> AHB clock = SYSCLK*/
RCC_HCLKConfig(RCC_SYSCLK_Div1);
 
/* defines the APB1 clock divider to be 2 -> APB1 clock = HCLK/2 (possible maximum)*/
RCC_PCLK1Config(RCC_HCLK_Div2);
 
/* defines the APB2 clock divider to be 2 -> APB2 clock = HCLK/2 (modifiable) */
RCC_PCLK2Config(RCC_HCLK_Div4);
 
/* defines the ADC clock divider to be 8 -> ADC clock = PCLK2/8 (modifiable) */
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
}
 
/**
  * @brief  Configures the GPIO channels for the ADC
  * @param  None
  * @retval None
  */
static void GPIO_Config(void)
{
/* Creats struct to configure GPIO */
GPIO_InitTypeDef GPIO_InitStructure;
 
/* GPIOA, GPIOB, GPIOC Periph clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
 
/* Reset init structure, if not it can cause issues */
GPIO_StructInit(&GPIO_InitStructure);
 
/* Configure ADC pins (PA0 - PA7,  PB0 - PB1, PC0 - PC5) -----start----- */
 
/* Sets the operating mode for the selected pins to "GPIO Analog In/Out Mode" */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
/* Sets the operating Pull-up/Pull down for the selected pins to no pull. */
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
 
 
/* Specifies the GPIO pins to be configured for GPIOB*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
/* Initializes GPIOB pins */
GPIO_Init(GPIOB, &GPIO_InitStructure);
 
/* Specifies the GPIO pins to be configured for GPIOC*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5;
/* Initializes GPIOC pins */
GPIO_Init(GPIOC, &GPIO_InitStructure);
         
/* Specifies the GPIO pins to be configured for GPIOA*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7; 
/* Initializes GPIOA pins */
GPIO_Init(GPIOA, &GPIO_InitStructure); 
 
//* Configure ADC pins (PA0 - PA7,  PB0 - PB1, PC0 - PC5) -----end----- */
}
 
/**
    * @brief Configures the DMA1 Channel1 to transfer data from ADC1 to SRAM
    * @param  None
    * @retval None
    */
static void DMA_Config(void)
{
/* Creats structs to configure DMA1 & NVIC */
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
     
/* Enables DMA1 Periph clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
     
/* Configures DMA settings -----start----- */
     
/* Deinitializes DMA1 Channel1 */
DMA_DeInit(DMA1_Channel1);
     
/* Sets the peripheral base adress to ADC1*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;//(uint32_t)&ADC1->DR;
/* Sets the memory base adress to the 16 bit result register of ADC1*/
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC1ConvertedValues1;
/* Sets the DMA direction from peripher to memory */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/* Sets the number of transfers to the defined value of @ref ARRAYSIZE */
DMA_InitStructure.DMA_BufferSize = ARRAYSIZE;
/* Specifies that the Peripheral address register is not incremented after each transfer*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/* Specifies that the memory address register is incremented after each transfer*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/* Sets the Peripheral data width to 16 bit */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/* Sets the memory data width to 16 bit */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/* Selects the circular operation mode*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/* Sets software priority for the DMA Channel to High */
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/* Specifies that the DMA Channle won't be used for memory-to-memory transfer. */
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
         
/* Initializes DMA1 Channel1 */
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
         
// Enable DMA1 Channel Transfer Complete interrupt
DMA_ITConfig(DMA1_Channel1, (DMA_IT_HT | DMA_IT_TC), ENABLE);
         
/* Configure DMA settings -----end----- */
     
/* Configures NVIC settings -----start----- */ 
 
/* Specifies the DMA1 IRQ channel to be enabled */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
/* Sets the pre-emption priority for the IRQ channel to 0 (highest) */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
/* Sets the subpriority level for the IRQ channel to 0 (highest) */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
/* Specifies that the IRQ channel defined in NVIC_IRQChannel will be enabled  */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
         
/* Enable DMA1 channel IRQ Channel */
NVIC_Init(&NVIC_InitStructure);    
 
// Interrupt Handler Code can be found in stm32f37x_it.c
 
/* Configures NVIC settings -----end----- */
     
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
 
/**
  * @brief  Configures the used ADC1 channels.
  * @param  None
  * @retval None
  */
static void ADC_Config(void)
{
/* Creats struct to configure ADC1 */
ADC_InitTypeDef ADC_InitStructure;
     
/* Enable ADC1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
     
/* ADC1 DeInit */ 
ADC_DeInit(ADC1);
   
/* Specifies that the ADC1 should send a DMA request to DMA1 afer each conversion */
ADC_DMACmd(ADC1, ENABLE); 
 
/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);
     
/* Configures ADC settings -----start----- */
 
/* Specifies that the conversion is performed in Scan (multichannels) mode */
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
/* Specifies that the conversion is performed in Continuous */
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
/* Specifies that no external Trigger is needed to start conversion */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
/* Specifies that the ADC data alignment is right */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
/* Sets the number of ADC channels that will be converted using the sequencer for regular channel group to 12 */
ADC_InitStructure.ADC_NbrOfChannel = 12;
     
/* Initializes ADC1 */
ADC_Init(ADC1, &ADC_InitStructure);
     
/* Configure ADC settings -----end----- */
     
/* ADC1 regular channel0-11 configuration with a sample time of 41.5 cycles */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 9, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 10, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 11, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 12, ADC_SampleTime_239Cycles5);
     
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
     
/* ADC1 reset calibration register */  
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
   
/* ADC1 calibration start */
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
   
/* Enable ADC1 */
//ADC_Cmd(ADC1, ENABLE);
}

and my Interrupt Service Routine in stm32f37x_it.c:

/**
  * @brief  This function handles DMA1 Channel 1 interrupt request.
  * @param  None
  * @retval None
  */
void DMA1_Channel1_IRQHandler(void)
{
   static uint16_t half = 0;
   static uint16_t full = 0;
   
  /* Test on DMA1 Channel1 Transfer Complete interrupt */
  if(DMA_GetITStatus(DMA1_IT_TC1))
  {
    /* DMA1 finished the transfer of the complete block */
    full++;
     
    /* Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits */
    DMA_ClearITPendingBit(DMA1_IT_GL1);
  }
   
   /* Test on DMA1 Channel1 Half Transfer Complete interrupt */
  if(DMA_GetITStatus(DMA1_IT_HT1))
  {
    /* DMA1 finished the transfer of a half block */
    half++;
 
    /* Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits */
    DMA_ClearITPendingBit(DMA1_IT_GL1);
  }
}

Outcomes