0
votes

I have to use 4 ADC channels in my stm32f3 Discovery, so I've decided to use DMA with Nvic. Values sent by USART are correct, however, the DMA1 Channel1 interrupt is called only once after downloading code to flash. I need a continuous conversion, is there something wrong with ADC/DMA/Nvic configuration?

#include"stm32f30x.h"
#include"stm32f30x_gpio.h"
#include"stm32f30x_rcc.h"
#include"stm32f30x_usart.h"
#include"stm32f30x_misc.h"
#include"stm32f30x_adc.h"
#include"stm32f30x_tim.h"
#include"stm32f30x_dma.h"

#define ADC1_DR    ((uint32_t)0x4001244C)
__IO uint16_t calibration_value = 0;
__IO uint32_t TimingDelay = 0;
__IO uint16_t ADC_Values[4];
uint16_t tmp[4];
volatile uint32_t dmaFlag = 0;

volatile char   rxData[100];
volatile long int    rxIndex=0, rxFlag=0;


void USART_puts( USART_TypeDef* USARTx, char *str )
{
    while(*str)
    {
        while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
        USART_SendData(USARTx, *str);
        *str++;
    }
}

void adc_init(void);

int main(void)
{

    int8_t dmaIndex;
    int k;
    usart_init();
    USART_puts(USART1,"ok");
    adc_init();
    while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_RDY));
    DMA_Cmd(DMA1_Channel1, ENABLE);
    ADC_StartConversion(ADC1);
    //

    while(1)
    {
        while(!dmaFlag);
         usart_num(tmp[0]);
                    usart_num(tmp[1]);
                    usart_num(tmp[2]);
                    usart_num(tmp[3]);
                    for(k=0;k<10000000;k++);
                    dmaFlag= 0;

    }
}

void adc_init(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure1;
    GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOC, &GPIO_InitStructure1);

    RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);

          ADC_CommonInitTypeDef ADC_CommonInitStructure;
          ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
          ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
          ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
          ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
          ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
          ADC_CommonInit(ADC1, &ADC_CommonInitStructure);

          ADC_InitTypeDef       ADC_InitStructure;
          ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
          ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
          ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
          ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
          ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
          ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
          ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
          ADC_InitStructure.ADC_NbrOfRegChannel = 4;
          ADC_Init(ADC1, &ADC_InitStructure);

          ADC_StructInit(&ADC_InitStructure);
          ADC_VoltageRegulatorCmd(ADC1, ENABLE);
          ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
          ADC_StartCalibration(ADC1);
          while(ADC_GetCalibrationStatus(ADC1) != RESET );
          calibration_value = ADC_GetCalibrationValue(ADC1);

          ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_7Cycles5);
          ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_7Cycles5);
          ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_7Cycles5);
          ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 4, ADC_SampleTime_7Cycles5);

          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
          DMA_InitTypeDef       DMA_InitStructure;
          DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
          DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Values;
          DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
          DMA_InitStructure.DMA_BufferSize = 4;
          DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
          DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
          DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;   // 16 bit
          DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   // 16 bit
          DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
          DMA_InitStructure.DMA_Priority = DMA_Priority_High;
          DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
          DMA_Init(DMA1_Channel1, &DMA_InitStructure);

          NVIC_InitTypeDef      NVIC_InitStructure;
          NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);
          DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
          DMA_Cmd(DMA1_Channel1, ENABLE);
          ADC_DMACmd(ADC1, ENABLE);
          ADC_Cmd(ADC1, ENABLE);


}

void DMA1_Channel1_IRQHandler(void)
{
     USART_puts(USART1,"fsfr");
  if (DMA_GetITStatus(DMA1_IT_TC1))
  {

      int dmaIndex;
        for(dmaIndex=0; dmaIndex<4; dmaIndex++)
                {
                    tmp[dmaIndex]=ADC_Values[dmaIndex]/4;
                }
   DMA_ClearITPendingBit(DMA1_IT_TC1);
    dmaFlag= 1;
  }
}

void usart_init( void )
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init( GPIOA, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);

    USART_Cmd( USART1, ENABLE);
}
void USART1_IRQHandler( void )
{
    if( USART_GetITStatus( USART1, USART_IT_RXNE) )
    {
          rxData[rxIndex] = USART_ReceiveData(USART1);
         // USART_ClearITPendingBit(USART1,USART_IT_RXNE);

                    while( !(rxData[rxIndex] == 'e') )
                    {
                        if( USART_GetITStatus( USART1, USART_IT_RXNE) )
                        {
                            rxIndex++;
                            rxData[rxIndex] = USART_ReceiveData(USART1);

                            if( rxData[rxIndex] == ' ')
                                rxData[rxIndex] = '0';

                            USART_ClearITPendingBit(USART1,USART_IT_RXNE);
                        }
                    }
                    rxFlag = 1;
        }

            ///USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
void rxDataClear( void )
{
    int i=0;

    while( rxData[i] )
    {
        rxData[i] = 0;
        i++;
    }

    rxIndex = 0;
}
void usart_float( float liczba )
{
    float tmp;
    char dane[7];
    tmp =   liczba;
    dane[0]=(((int)tmp %1000) /100)+0x30;
    dane[1]=(((int)tmp %100) /10)+0x30;
    dane[2]=(((int)tmp %10))+0x30;
    dane[3]='.';
    dane[4]=((int)(tmp*10)  %10)+0x30;
    dane[5]=((int)(tmp*100) %10)+0x30;
    dane[6]=((int)(tmp*1000) %10)+0x30;
    dane[7]='\0';
    USART_puts(USART1,dane);
}
void usart_num(signed int liczba)
{
    int i, length=0,znak=0;
    char liczba_str[10] = {0};
    if( liczba < 0 )
    {
        znak = 1;
        liczba = - liczba;
    }

    for( i = 1; (i <= liczba) && (length <= 10); i*=10 )
    {
        if( (liczba/i) > 0 )
            length++;
    }
    if(length == 0)
        length = 1;
    i = 1;

    while(length)
    {
        liczba_str[length-1]=liczba%(10*i)/i+48;
        length--;
        i*= 10;
    }
    if(znak)
        USART_puts(USART1,"-");
    else
        USART_puts(USART1," ");
    USART_puts(USART1, liczba_str );
}
1
Try clearing the flags and pending bits before enabling the interrupts.SamR
it still fires only once..Michelle

1 Answers

0
votes

Try this to continuous conversion,change this:

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

to : DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; and replace this: DMA_Cmd(DMA1_Channel1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE);

by:

ADC_DMAConfig( ADC1, ADC_DMAMode_Circular );  
/* Enable ADC1 DMA */
ADC_DMACmd( ADC1, ENABLE );
/* Enable ADC1 */
ADC_Cmd( ADC1, ENABLE );

/* Wait for ADC1 ready */
i = 0xFFFFF;
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_RDY ) && i) i--;

/* Enable the DMA1 channel1 */
DMA_Cmd( DMA1_Channel1, ENABLE );

/* Start ADC1 Software Conversion */
ADC_StartConversion( ADC1);`