cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F303CBT6 DAC not working with DMA

freya17365
Associate III

Dear all,

I'm trying to generate a waveform using DAC OUT1.

I configured pin PA4 as analog (works)

I configured DAC1 without DMA and it works

I configured TIM6 and it works

 

Then I configured DAC with DMA, configured DMA, but output never changes.

Where can I check?

 

I enclose the minimun configuration code:

 

/* DAC Configuration */
if(!(RCC->APB1ENR & RCC_APB1ENR_DAC1EN)) RCC->APB1ENR |= RCC_APB1ENR_DAC1EN; // Enable DAC clock
DAC1->CR |= DAC_CR_DMAEN1 | DAC_CR_MAMP1_3 | DAC_CR_EN1; // DMA1 enable | Amplitude 511 |Wave generation disabled | Timer6 TRGO event | Trigger enable | Buffer enable | DAC1_OUT1 enable


/* DAC Timer */
if(!(RCC->APB1ENR & RCC_APB1ENR_TIM6EN)) RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // Enable TIM6 clock
TIM6->CR2 |= TIM_CR2_MMS_2; // The update event is selected as a trigger output (TRGO).
TIM6->DIER |= TIM_DIER_UIE | TIM_DIER_UDE; //Enable interrupt | Enable DMA request
TIM6->EGR = TIM_EGR_UG; // Re-initializes the timer counter and generates an update of the registers
TIM6->CR1 |= TIM_CR1_CEN; // Enable TIM6


/* DAC DMA */
if(!(RCC->AHBENR & RCC_AHBENR_DMA1EN)) RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Enable DMA1 clock
SYSCFG->CFGR1 |= SYSCFG_CFGR1_TIM6DAC1Ch1_DMA_RMP;
DMA1_Channel3->CCR |= DMA_CCR_PL_0 | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_DIR | DMA_CCR_TCIE; // Medium priority | size 16 bit both mem and periph | mem increment | circular | mem to periph | Transfer complete interrupt
DMA1_Channel3->CNDTR = 100; // Data to be transfered
DMA1_Channel3->CPAR = (uint32_t) &(DAC1->DHR12R1); // Peripheral address
DMA1_Channel3->CMAR = (uint32_t) &sen[0]; // Memory address
DMA1_Channel3->CCR |= DMA_CCR_EN; // Enable DMA

 

Both TIM6_DAC_IRQn and DMA1_Channel3_IRQn are enabled.

I tried to find also some examples or AN documents, but I faild.

 

Any hint would be appreciated.

 

Thank you

Freya

 

 

 

 

 

13 REPLIES 13

In attachment is working example (writen using LL API) from lectures (dual channel DAC using TIM+DMA) for STM32F303K. Key part of source code is following:

#define MAX_SAMPLES 256 
#define DAC_DUAL_DATA_REG 0x40007420 

void dac_init(void);
void tim6_init(void);
uint32_t wave[MAX_SAMPLES];
uint16_t samples = MAX_SAMPLES; 

int main(void){
	SystemCoreClockUpdate(); // 72MHz
	DBGMCU_APB1PeriphConfig(DBGMCU_TIM6_STOP, ENABLE); 
	dac_init();
	tim6_init();
	
	DMA_SetCurrDataCounter(DMA1_Channel3,samples); 
	DMA_Cmd(DMA1_Channel3, ENABLE);
	DAC_DMACmd(DAC1,DAC_Channel_1,ENABLE);
	TIM_Cmd(TIM6, ENABLE); 

	while(1){
		asm("nop");
	}
}


void tim6_init(void){
	TIM_TimeBaseInitTypeDef tim;
	NVIC_InitTypeDef nvic;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); 

	TIM_TimeBaseStructInit(&tim);
	tim.TIM_Prescaler = 0; 
	tim.TIM_Period = 71; // 1Msps
	TIM_TimeBaseInit(TIM6, &tim);
	TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); 
}

void dac_init(void){
	GPIO_InitTypeDef gp;
	DAC_InitTypeDef dac;
	DMA_InitTypeDef dma;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

	// PA4 (DAC1_OUT1) - analog, PA5 (DAC1_OUT2) - analog
	gp.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	gp.GPIO_Mode = GPIO_Mode_AN;
	gp.GPIO_OType = GPIO_OType_PP;
	gp.GPIO_PuPd = GPIO_PuPd_NOPULL;
	gp.GPIO_Speed = GPIO_Speed_Level_1;
	GPIO_Init(GPIOA, &gp);

	// konfigurace DAC1_ch1 (s bufferem)
	dac.DAC_Buffer_Switch = DAC_BufferSwitch_Disable; 
	dac.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; 
	dac.DAC_Trigger = DAC_Trigger_T6_TRGO; // trigger z TIM6
	dac.DAC_WaveGeneration = DAC_WaveGeneration_None; 
	DAC_Init(DAC1,DAC_Channel_1,&dac); 
	
	dac.DAC_Buffer_Switch = DAC_BufferSwitch_Enable; 
	dac.DAC_LFSRUnmask_TriangleAmplitude = 
	dac.DAC_Trigger = DAC_Trigger_T6_TRGO; // trigger z TIM6
	dac.DAC_WaveGeneration = DAC_WaveGeneration_None;
	DAC_Init(DAC1,DAC_Channel_2,&dac); 

 // konfigurace DMA
	dma.DMA_BufferSize = MAX_SAMPLES; 
	dma.DMA_DIR = DMA_DIR_PeripheralDST; 
	dma.DMA_M2M = DMA_M2M_Disable; 
	dma.DMA_MemoryBaseAddr = (uint32_t)(wave); 
	dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // data jsou 32bit
	dma.DMA_MemoryInc = DMA_MemoryInc_Enable; 
	dma.DMA_Mode = DMA_Mode_Circular; 
	dma.DMA_PeripheralBaseAddr = (uint32_t)DAC_DUAL_DATA_REG; 
	dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 
	dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  adresu
	dma.DMA_Priority = DMA_Priority_High; 
	DMA_Init(DMA1_Channel3, &dma); 

	SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_TIM6DAC1Ch1, ENABLE);

	// spustit DAC
	DAC_Cmd(DAC1,DAC_Channel_1,ENABLE);
	DAC_Cmd(DAC1,DAC_Channel_2,ENABLE);
}

 

freya17365
Associate III

Dear all,

at last it works!

I do not know exactly what was wrong, surely I forgot the line:

if(!(RCC->APB2ENR & RCC_APB2ENR_SYSCFGEN)) RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;	// Enable SYSCFG clock

 

In annex I enclose my code, if it could be useful for someone

 

Thnak you to all

Freya

By the way, why are you using following if condition:

if(!(RCC->APB2ENR & RCC_APB2ENR_SYSCFGEN)) RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;


instead of simple bitsetting ?

RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

 

Indeed no rational reason.

I am used that way

 

Times ago I had some problem in setting registers, since then I use the "if" instruction, but I agree with you

 

Freya