AnsweredAssumed Answered

DMA normal mode issue with ADC and USART

Question asked by cziko.adam on Nov 16, 2013
Hello,

I use an STM32F105RC microcontroller and I have a problem that I could not solve, no matter how hard I tried.
This is what I am willing, to do:
-> I read analog datas with ADC, with a sampling frequency of 8kHz, provided by timer.
-> All the datas are written with the help of ADC into a buffer, with the size of BUFFER_IN.
-> When the half transfer to the ADC buffer is done, there comes the interrupt, then I send out the datas through USART, using DMA.
-> The key factor is that, I a willing to send out the first part of the buffer, while i am writing the other part of that, with an other DMA channel.
-> After halft transfer there is an other interrupt with the same method.


BUFFER_IN is defined with the value of 64.
BUFFER_OUT is defined with the value of 32.


Here is the problem:
I read 32 time 8 bit data, then I am willing to send out all the 32*8 bits with USART, but I just send out 8 bits, and nothing else till the next interrupt comes.
32 times 8 bit datas with a sampling rate of 8kHz means that there is an interupt in every 4ms, and in every 4 ms I send out once 8 bit.


Where can be the problem in my code? I have checked it more times, but i still can not see the problem.
Your help would be a great relief for me!




Here is my code:


/* Application include */
#include "telemetry_apl.h"

/* Private functions */
void telemetry_apl_init_GPIO(void);

/* Private variables */
static uint8_t ADC_Mic_Values[BUFFER_IN];

/* OS tasks */
void telemetry_apl_100ms_Task(void);

void telemetry_apl_Init(void) {

     printf("Init started!");
     uint8_t i;

     for(i=0;i<BUFFER_IN;i++)
     {
          ADC_Mic_Values[i]=0;
     }

     Radio_apl_init_ADC_RCC();
     Radio_apl_init_ADC_GPIO();
     Radio_apl_init_ADC_TIM();
     Radio_apl_init_ADC_NVIC();
     Radio_apl_init_ADC_DMA();
     Radio_apl_init_ADC_ADC();

     Radio_apl_init_UART_RCC();
     Radio_apl_init_UART_GPIO();
     Radio_apl_init_UART_NVIC();
     Radio_apl_init_UART_DMA_TX(BUFFER_OUT);
     Radio_apl_init_UART_UART();

     RTOS_layer_registrate("Example application 100ms task", telemetry_apl_100ms_Task, _100MS_TIME, 0);
     printf("Init ended!");
}

uint8_t count;
void telemetry_apl_100ms_Task(void)
{
     uint8_t i;
     count++;
     if(count==25)
     {
          for(i=0;i<BUFFER_IN;i++)
          {
               printf(" -> %d",ADC_Mic_Values[i]);
          }
          printf("\r\n");
     }
     if(count==50)
     {
          count = 0;
     }
}

/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*-------------------------------------ADC-----------------------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/

void Radio_apl_init_ADC_RCC()
{
          /* Enable DMA1 clock */
          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

          /* Enable GPIOs and ADC1 clock */
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
                                    RCC_APB2Periph_TIM1 |
                                    RCC_APB2Periph_AFIO |
                                    RCC_APB2Periph_ADC1, ENABLE);
}
void Radio_apl_init_ADC_GPIO()
{
          /* Disable the Serial Wire Jtag Debug Port SWJ-DP */
          GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);

          GPIO_InitTypeDef GPIO_InitStructure;

          /* GPIO */
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

          /* Configure PA.05 (ADC Channel6) as analog input */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
          GPIO_Init(GPIOA, &GPIO_InitStructure);

          /* Configure TIM1_CH1 (PA8) as alternate function push-pull */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_Init(GPIOA, &GPIO_InitStructure);

          /* Enable the GPIO_MPEN Port's Clock */
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
          /* Configure the GPIO_MPEN pin */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_Init(GPIOC, &GPIO_InitStructure);
}

void Radio_apl_init_ADC_TIM()
{
       TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
       TIM_OCInitTypeDef         TIM_OCInitStructure;

       /* TIM1 configuration ------------------------------------------------------*/
       /* Time Base configuration for 8kHz*/
       TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
       TIM_TimeBaseStructure.TIM_Period = 2250; 
       TIM_TimeBaseStructure.TIM_Prescaler = 0x03; 
       TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
       TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

       /* TIM1 channel1 configuration in PWM mode */
       TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
       TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
       TIM_OCInitStructure.TIM_Pulse = 0x7F;
       TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
       TIM_OC1Init(TIM1, &TIM_OCInitStructure);

       TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
}

void Radio_apl_init_ADC_NVIC()
{
     NVIC_InitTypeDef NVIC_InitStructure;

     /* Enable the TIM6 global Interrupt */
     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);
}

void Radio_apl_init_ADC_DMA()
{
          /* -------------------- DMA1 channel1 configuration -------------------- */
          DMA_InitTypeDef DMA_InitStructure;

          DMA_DeInit(DMA1_Channel1);
          DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address+1;
          DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Mic_Values[0];
          DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
          DMA_InitStructure.DMA_BufferSize = BUFFER_IN;
          DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
          DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
          DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
          DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
          DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
          DMA_InitStructure.DMA_Priority = DMA_Priority_High;
          DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
          DMA_Init(DMA1_Channel1, &DMA_InitStructure);

          DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);
          DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);

          /* Enable DMA1 channel1 */
          DMA_Cmd(DMA1_Channel1, ENABLE);
}
void Radio_apl_init_ADC_ADC()
{
          /* -------------------- ADC1 configuration -------------------- */
          ADC_InitTypeDef ADC_InitStructure;

          ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
          ADC_InitStructure.ADC_ScanConvMode = ENABLE;
          ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
          ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
          ADC_InitStructure.ADC_NbrOfChannel = 1;
          ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
          ADC_Init(ADC1, &ADC_InitStructure);

          /* ADC1 regular channels configuration */
          ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_7Cycles5);
          /* Enable ADC1 external trigger conversion */
          ADC_ExternalTrigConvCmd(ADC1, ENABLE);

          /* Enable ADC1 DMA */
          ADC_DMACmd(ADC1, ENABLE);

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

          /* Enable ADC1 reset calibration register */
          ADC_ResetCalibration(ADC1);

          /* Check the end of ADC1 reset calibration register */
          while(ADC_GetResetCalibrationStatus(ADC1));

          /* Start ADC1 calibaration */
          ADC_StartCalibration(ADC1);

          /* Check the end of ADC1 calibration */
          while(ADC_GetCalibrationStatus(ADC1));

          /* TIM1 counter enable */
          TIM_Cmd(TIM1, ENABLE);

          /* TIM1 main Output Enable */
          TIM_CtrlPWMOutputs(TIM1, ENABLE);

          //ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*-------------------------------------UART----------------------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/

void Radio_apl_init_UART_RCC()
{
     /*----------------------------- RCC ---------------------------------*/

     /* DMA clock enable */
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable GPIO clock */
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

     /* Enable UART clock */
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
}
void Radio_apl_init_UART_GPIO()
{
     /*----------------------------- GPIO ---------------------------------*/

     GPIO_InitTypeDef GPIO_InitStructure;

     /* Configure USART Tx as alternate function push-pull */
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     /* Configure USART Rx as input floating */
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void Radio_apl_init_UART_NVIC()
{
     /*----------------------------- NVIC ---------------------------------*/
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART3 Interrupt */
     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
}
void Radio_apl_init_UART_DMA_TX(uint32_t index)
{
     /*----------------------------- DMA ---------------------------------*/

     DMA_InitTypeDef DMA_InitStructure;

     /* USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config */
     DMA_DeInit(DMA1_Channel6);
     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;  //USART2_BASE+0x04;
     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&(ADC_Mic_Values[index]);
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
     DMA_InitStructure.DMA_BufferSize = BUFFER_OUT;
     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
     DMA_InitStructure.DMA_Priority = DMA_Priority_High;
     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
     DMA_Init(DMA1_Channel6, &DMA_InitStructure);
}

void Radio_apl_init_UART_UART()
{
     /*----------------------------- UART ---------------------------------*/

     USART_InitTypeDef USART_InitStructure;

     //USART_InitStructure.USART_BaudRate = 115200;
     USART_InitStructure.USART_BaudRate = 921600;
     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;

     /* Configure USART2 */
     USART_Init(USART2, &USART_InitStructure);

     /* Enable USARTy DMA Rx and TX request */
     USART_DMACmd(USART2, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);

     //USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

     /* Enable USARTy TX DMA1 Channel */
     DMA_Cmd(DMA1_Channel6, ENABLE);

     /* Enable the USARTy */
     USART_Cmd(USART2, ENABLE);
}

void DMA1_Channel1_IRQHandler(void) //Channel1==ADC -->> Channel6==TX
{
     if(DMA_GetITStatus(DMA1_IT_HT1))
     {
          GPIO_SetBits(GPIOC,GPIO_Pin_1);

          DMA_ClearITPendingBit(DMA1_IT_HT1);

          DMA_ClearFlag(DMA1_FLAG_HT6);
DMA_ClearFlag(DMA1_FLAG_HT1);

          //DMA_Cmd(DMA1_Channel6, DISABLE);

          Radio_apl_init_UART_DMA_TX(0);

          DMA_Cmd(DMA1_Channel6, ENABLE);

          while(DMA_GetFlagStatus(DMA1_FLAG_HT6)==RESET);
     }
     if(DMA_GetITStatus(DMA1_IT_TC1))
     {
          GPIO_ResetBits(GPIOC,GPIO_Pin_1);

          DMA_ClearITPendingBit(DMA1_IT_TC1);

          DMA_ClearFlag(DMA1_FLAG_TC6);

          DMA_ClearFlag(DMA1_FLAG_TC1);

          //DMA_Cmd(DMA1_Channel6, DISABLE);

          Radio_apl_init_UART_DMA_TX(BUFFER_OUT);

          DMA_Cmd(DMA1_Channel6, ENABLE);

          while(DMA_GetFlagStatus(DMA1_FLAG_TC6)==RESET);
     }
}

Outcomes