AnsweredAssumed Answered

Problem with ADC using DMA and timer

Question asked by montoliu.miquel on Oct 15, 2013
Latest reply on Nov 14, 2013 by marco.messori
Hello everyone,

few days ago I write a post with a problem in my program. Well, now I can compile and execute my program, but there is a problem:

my intention is to collect the values of the temperature sensor (ADC channel 16), Vbat (ADC1 channel 18), and the potentiometer (ADC3 channel 7) through the DMA and record them to an SD card.
For this, I need to do a triple mode of adc. The problem is that the recorded values are not correct, since for example the supposed value of the potentiometer is wrong.
I copy my program (main and interrupts). I hope you can help me, since I'm a bit new to this. If you need some additional text, please tell me.


Thank you!

/*----------------------------------------------------------------------*/
/*Main program                                                        */
/*----------------------------------------------------------------------*/




#include "stm32f4xx.h"
#include "stm324xg_eval.h"
#include "stm324xg_eval_sdio_sd.h"
 
 #include "main.h"
 
#include <stdio.h>
//#include "core_cm4.h" //definició IO
#include "ff.h"
#include "diskio.h"






/*Private variables*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef       TIM_OCInitStructure;
TIM_BDTRInitTypeDef     TIM_BDTRInitStructure;
__IO uint16_t aADCTripleConvertedValue[3];


char vectordelatrama [2048];
int posiciodelvector=0;
char estructura[32];
int a;
int recompte=0;
int enviar=0;
int offset=0;


__IO uint32_t TimeOut = 0x0; 


FATFS Fatfs;               /* File system object */
FIL Fil2;                         /* File object */
BYTE Buff[128];          /* File read buffer */




void die (          /* Stop with dying message */
     FRESULT rc     /* FatFs return value */
)
{
}


static void TIM_Config(void)
{
     
     NVIC_InitTypeDef NVIC_InitStructure;
       /* Enable the TIM1 Trigger and commutation interrupt */
     
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
     
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);   
     
     NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_Init(&NVIC_InitStructure);
     
     NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_Init(&NVIC_InitStructure);
}






void INTTIM_Config(void)
{
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* Time base configuration for 5 ms */
TIM_TimeBaseStructure.TIM_Period = 10500 - 1; // 1 MHz down to 10 KHz (0.1 ms)
TIM_TimeBaseStructure.TIM_Prescaler = 40 - 1; //posar 40!!! (16000 son 2 segons)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM2 enable counter */
     TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 
     TIM_Cmd(TIM2, ENABLE);


}




static void ADC_Config(void)
{
  GPIO_InitTypeDef       GPIO_InitStructure;
  DMA_InitTypeDef        DMA_InitStructure;
  ADC_InitTypeDef        ADC_InitStructure;
  ADC_CommonInitTypeDef  ADC_CommonInitStructure;  
  
  /* Enable peripheral clocks *************************************************/
  RCC_AHB1PeriphClockCmd( ADC1_2_CHANNEL_GPIO_CLK , ENABLE);
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA2 , ENABLE);
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1 , ENABLE);
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC2 , ENABLE);
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC3 , ENABLE);  


  /* Configure ADC Channel 12 pin as analog input *****************************/ 
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIO_PORT, &GPIO_InitStructure);


  /* DMA2 Stream0 channel0 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_CHANNELx;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&aADCTripleConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 3;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA_STREAMx, &DMA_InitStructure);


  /* DMA2_Stream0 enable and enable interrupts */
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
     DMA_Cmd(DMA_STREAMx, ENABLE);


  /* ADC Common configuration *************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;  
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; 
  ADC_CommonInit(&ADC_CommonInitStructure);


  /* ADC1 regular channel 16 configuration ************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 2; //2 o 3??
  ADC_Init(ADC1, &ADC_InitStructure);


  ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_3Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 1, ADC_SampleTime_3Cycles);
  /* Enable ADC1 DMA */
   //ADC_VBATCmd(ENABLE);  //afegit
     ADC_DMACmd(ADC1, ENABLE);


  /* ADC2 regular channel 12 configuration ************************************/
  //ADC_Init(ADC2, &ADC_InitStructure);
     ADC_DMACmd(ADC2, ENABLE);
  /* ADC2 regular channel12 configuration */ 
  //ADC_RegularChannelConfig(ADC2, ADC_CHANNEL, 1, ADC_SampleTime_3Cycles);


  /* ADC3 regular channel 7 configuration ************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADC3, &ADC_InitStructure); 
  /* ADC3 regular channel 7 configuration */
  ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 1, ADC_SampleTime_3Cycles);
          ADC_DMACmd(ADC3, ENABLE);




  /* Enable DMA request after last transfer (multi-ADC mode) ******************/
  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);


  /* Enable ADC1 **************************************************************/
  ADC_Cmd(ADC1, ENABLE);


  /* Enable ADC2 **************************************************************/
  ADC_Cmd(ADC2, ENABLE);


  /* Enable ADC3 **************************************************************/
  ADC_Cmd(ADC3, ENABLE);
     
      //ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); // afegit


}  


/*-----------------------------------------------------------------------*/
/* Program Main                                                          */
/*-----------------------------------------------------------------------*/


int main (void) 
{
     FRESULT rc;                    /* Result code */
     DIR dir;                    /* Directory object */
     FILINFO fno;               /* File information object */
     UINT bw, br, i;


     STM_EVAL_LEDInit(LED1);
     STM_EVAL_LEDInit(LED2);
          STM_EVAL_LEDInit(LED3);
     STM_EVAL_LEDInit(LED4);
     
     
     
     f_mount(0, &Fatfs);          /* Register volume work area (never fails) */
     
     rc = f_open(&Fil2, "ADC.TXT", FA_WRITE | FA_CREATE_ALWAYS);
     
     if (rc) die(rc);
     
     
     
     for(a=0; a < 32; a++)
     {
          if (a<4) estructura[a]= 0x11*(a+1);
          else estructura[a]= 0x00;
     }
     rc = f_write(&Fil2, &estructura, 32, &bw);
     if (rc) die(rc);
     
     //rc = f_close(&Fil2);
          //          if (rc) die(rc);
     
     TIM_Config();
     INTTIM_Config();
     ADC_Config();
               




     while(1){
          if(enviar==1){
               enviar=0;
               rc = f_write(&Fil2, vectordelatrama+offset, 1024, &bw);
               if (rc) die(rc);
                                   STM_EVAL_LEDToggle(LED4);


               if (recompte==25){
                    rc = f_close(&Fil2);
                    if (rc) die(rc);
                    STM_EVAL_LEDOff(LED4);
                    ADC_Cmd(ADC1, DISABLE);
                    ADC_Cmd(ADC2, DISABLE);
                    ADC_Cmd(ADC2, DISABLE);
                    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, DISABLE);
                    DMA_Cmd(DMA_STREAMx, DISABLE);
                    TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); 
                    TIM_Cmd(TIM2, DISABLE);
                    
               }
          }
     }
}


Interrupts

/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */
/******************************************************************************/


void TIM2_IRQHandler(void)
{
     //ADC_TempSensorVrefintCmd(ENABLE);
     //ADC_RegularChannelConfig(ADC1,ADC_Channel_16,16,ADC_SampleTime_3Cycles);
     //valor=ADC_GetConversionValue(ADC1);
     ADC_SoftwareStartConv(ADC1);
     STM_EVAL_LEDToggle(LED1);
     TIM_ClearFlag(TIM2, TIM_FLAG_Update);
     TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);






}




/* Configuració de la interrupció associada a la DMA */


void DMA2_Stream0_IRQHandler (void)
{
          STM_EVAL_LEDToggle(LED2);


     //DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
     DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
     if (recompte < 2) {
          for(i=0; i < tamanyvector;i++) {
               vectordelatrama[i+posiciodelvector]= estructura[i];
          }
     }
     vectordelatrama[posiciodelvector+4]=(aADCTripleConvertedValue[0])>>8;
     vectordelatrama[posiciodelvector+5]=aADCTripleConvertedValue[0];
     vectordelatrama[posiciodelvector+6]=(aADCTripleConvertedValue[1])>>8;
     vectordelatrama[posiciodelvector+7]=aADCTripleConvertedValue[1];
     vectordelatrama[posiciodelvector+8]=(aADCTripleConvertedValue[2])>>8;
     vectordelatrama[posiciodelvector+9]=aADCTripleConvertedValue[2];
     STM_EVAL_LEDToggle(LED3);


     if (posiciodelvector==992){
          offset=0;
          posiciodelvector+=32;
          enviar=1;
     }
     else if (posiciodelvector==2016){
          offset=1024;
          enviar=1;
          posiciodelvector=0;
          recompte+=1;
     }


     else if (recompte ==25){
          STM_EVAL_LEDToggle(LED4);
          enviar=1;
          
     }
     else posiciodelvector+=32;
     DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
     




     }
     
I'm using the STM32F417IGH6 microcontroller and STM3241G-EVAL board.
Thanks again!

Outcomes