AnsweredAssumed Answered

ADC to DAC using DMA on STM32F4-Discovery

Question asked by pansoul on Nov 10, 2016
Hello

I am using an STM32F4-Discovery board.
My purpose is first to copy ADC to DAC using DMA (after that is done, my purpose will be to process the signal but this is another story).

The problem is that on DAC output Pin (PA4), i only output noise whatever is ADC input signal on PC3.

I programmed LED4 and LED6 to blink every 1024 of DMA ADC handler and DMA DAC Handler.
There are blinking with same frequency which mean that ADC sampling and DAC feeding are working synchronously.

several "uncontrolled" point :
- BUFFER SIZE from ADC is double from DAC. This is the only way i can have LED4 and LED6 blinking at same frequency. The problem is that there are both linked to TIMER 8. I don't set up prescaler
    so i don't understand why frequency is not the same when buffer size is the same. Consequently i copy 1 value over 2 from ADC in order to output only 1024 value, so the should be the same but just "under sampled".
- Another test i did is generating value  ADC handler to feed DAC and strangely index 512 to 1024 of output variable OutputDAC1 does not seems to be used while buffer size and array size are 1024.
- for now, i am using another STM32F4-Discovery board as source, i try to make a direct connection to DAC output of this board but not sure about what is best wiring (that said i monitor that correct signal
is bring to ADC Pin using an oscilloscope)
- to simplify the problem, i tried to use only DAC1 but when i remove DAC_Ch2_Config LED6 is not working.


- I did a lot of test on several parameters (scanmode, priority, prescaler,    buffer size, double buffering, data alignement,    pull mode) but i still get noise at output (but not always the same noise).

Here is the code :

/* Includes
------------------------------------------------------------------*/
#include "stm32f4_discovery.h"
 
/* Private typedef
-----------------------------------------------------------*/
/* Private define
------------------------------------------------------------*/
#define DAC_DHR12R1_ADDRESS    0x40007408
#define DAC_DHR12R2_ADDRESS    0x40007414
#define DAC_DHR8R1_ADDRESS     0x40007410
#define DAC_DHR8R2_ADDRESS     0x4000741C
 
#define ADC3_DR_ADDRESS     ((uint32_t)0x4001224C)
 
/* Private macro
-------------------------------------------------------------*/
/* Private variables
---------------------------------------------------------*/
DAC_InitTypeDef  DAC_InitStructure;
 
uint16_t OutputDAC2[1024];
uint16_t OutputDAC1[1024];
long temps_attenuation = 0;
long index_dac = 0;
 
__IO uint8_t SelectedWavesForm = 0;
__IO uint8_t KeyPressed = SET;
 
__IO uint16_t ADC3ConvertedValue[1024] = 0;
__IO uint32_t ADC3ConvertedVoltage = 0;
 
/* Private function prototypes
-----------------------------------------------*/
void TIM8_Config(void);
void DAC_Ch1_Config(void);
void DAC_Ch2_Config(void);
void ADC3_CH12_DMA_Config(void);
 
/* Private functions
---------------------------------------------------------*/
 
int main(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   NVIC_InitTypeDef      NVIC_InitStructure;
 
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_GPIOA, ENABLE);
 
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
 
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
 
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
 
   TIM8_Config();
 
   /* Configures User Button */
   STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_EXTI);
 
   STM_EVAL_LEDInit(LED4);
   STM_EVAL_LEDInit(LED6);
 
   DAC_DeInit();
   DAC_Ch2_Config();
   DAC_Ch1_Config();
 
   DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_HT, ENABLE);
 
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
 
   ADC3_CH12_DMA_Config();
 
   NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
 
   DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
 
   ADC_SoftwareStartConv(ADC3);
 
   while (1)
   {
 
   }
}
 
void ADC3_CH12_DMA_Config(void)
{
   ADC_InitTypeDef       ADC_InitStructure;
   ADC_CommonInitTypeDef ADC_CommonInitStructure;
   DMA_InitTypeDef       DMA_InitStructure;
   GPIO_InitTypeDef      GPIO_InitStructure;
 
   /* Enable ADC3, DMA2 and GPIO clocks ****************************************/
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
 
   /* DMA2 Stream0 channel0 configuration**************************************/
   DMA_InitStructure.DMA_Channel = DMA_Channel_2;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
 
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
   DMA_InitStructure.DMA_BufferSize = 2048;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
 
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
 
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
 
   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(DMA2_Stream0, &DMA_InitStructure);
   DMA_Cmd(DMA2_Stream0, ENABLE);
 
   /* Configure ADC3 Channel12 pin as analog input******************************/
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
 
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
 
   GPIO_Init(GPIOC, &GPIO_InitStructure);
 
   /* ADC Common Init**********************************************************/
   ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
 
   ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;
   ADC_CommonInit(&ADC_CommonInitStructure);
 
   /* ADC3 Init ****************************************************************/
   ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
   ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T8_TRGO;
   ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
   ADC_InitStructure.ADC_ScanConvMode = DISABLE;
   ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
   ADC_InitStructure.ADC_NbrOfConversion = 1;
   ADC_Init(ADC3, &ADC_InitStructure);
 
   /* ADC3 regular channel12 configuration*************************************/
   ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1,ADC_SampleTime_3Cycles);
   ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
 
   /* Enable ADC3 DMA */
   ADC_DMACmd(ADC3, ENABLE);
 
   /* Enable ADC3 */
   ADC_Cmd(ADC3, ENABLE);
}
 
void DAC_Ch1_Config(void)
{
   DMA_InitTypeDef DMA_InitStructure;
 
   // DAC channel1 Configuration
   DAC_InitStructure.DAC_Trigger = DAC_Trigger_T8_TRGO;
   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
   DAC_Init(DAC_Channel_1, &DAC_InitStructure);
 
   DMA_DeInit(DMA1_Stream6);
   DMA_InitStructure.DMA_Channel = DMA_Channel_7;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDRESS;
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&OutputDAC1;
   DMA_InitStructure.DMA_BufferSize = 1024;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   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(DMA1_Stream6, &DMA_InitStructure);
 
   // Enable DMA1_Stream6
   DMA_Cmd(DMA1_Stream6, ENABLE);
 
   // Enable DAC Channel1
   DAC_Cmd(DAC_Channel_1, ENABLE);
 
   // Enable DMA for DAC Channel1
   DAC_DMACmd(DAC_Channel_1, ENABLE);
}
 
void DAC_Ch2_Config(void)
{
   DMA_InitTypeDef DMA_InitStructure;
 
   // DAC channel2 Configuration
   DAC_InitStructure.DAC_Trigger = DAC_Trigger_T8_TRGO;
   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
   DAC_Init(DAC_Channel_2, &DAC_InitStructure);
 
   // DMA1_Stream5 channel7 configuration
   DMA_DeInit(DMA1_Stream5);
   DMA_InitStructure.DMA_Channel = DMA_Channel_7;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&OutputDAC2;
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
   DMA_InitStructure.DMA_BufferSize = 1024;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   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(DMA1_Stream5, &DMA_InitStructure);
 
   // Enable DMA1_Stream5
   DMA_Cmd(DMA1_Stream5, ENABLE);
 
   // Enable DAC Channel2
   DAC_Cmd(DAC_Channel_2, ENABLE);
 
   // Enable DMA for DAC Channel2
   DAC_DMACmd(DAC_Channel_2, ENABLE);
 
}
 
void TIM8_Config(void)
{
   TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
   /* TIM8 Periph clock enable */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
 
   /* Time base configuration */
   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
   TIM_TimeBaseStructure.TIM_Period = 0x200;
   TIM_TimeBaseStructure.TIM_Prescaler = 0;
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
 
   /* TIM8 TRGO selection */
   TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update);
 
   /* TIM8 enable counter */
   TIM_Cmd(TIM8, ENABLE);
}
 
// DAC 2 Stream Handler
void DMA1_Stream6_IRQHandler(void)
{
   if (DMA_GetITStatus(DMA1_Stream6 , DMA_IT_HTIF6))
   {
       Blink_LED6_Every_1024_iteration();
   }
 
   if (DMA_GetITStatus(DMA1_Stream6 , DMA_IT_TCIF6))
   {
   }
 
   DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6 | DMA_IT_HTIF6);
   DMA_ClearFlag(DMA1_Stream6, DMA_IT_TCIF6 | DMA_IT_HTIF6);
}
 
// ADC Stream Handler
void DMA2_Stream0_IRQHandler(void)
{
   if (DMA_GetITStatus(DMA2_Stream0 , DMA_IT_HTIF0))
   {
        Blink_LED4_Every_1024_iteration();
   }
 
   if (DMA_GetITStatus(DMA2_Stream0 , DMA_IT_TCIF0))
   {
        for (index_dac = 0; index_dac < 512; index_dac++)
        {
            OutputDAC2[index_dac] = ADC3ConvertedValue[index_dac];
            OutputDAC1[index_dac] = ADC3ConvertedValue[index_dac];
        }
    }
 
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0 | DMA_IT_HTIF0);
    DMA_ClearFlag(DMA2_Stream0, DMA_IT_TCIF0 | DMA_IT_HTIF0);
}

If someone has any hint, i'd appreciate it.

Thanks

Outcomes