cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F3 DMA triggered by ADC triggered by TIM without HAL

MF.3
Associate

Hello,

currently I'am working on a STM32 project with the CMSIS core.

I want the ADC getting triggered by a Timer (TIM3). Iam trying to do that with the TRGO option.

The ADC should sample 4 different channels. Each channel then gets transfered by the DMA to the RAM.

With my current code it works only once at startup, but I dont get any new readings in the memory.

void DMA_Init()
{
	//1. Channel im SYSCFG CFGR1/3 bekannt geben
	//SYSCFG_CFGR1: Nichts für ADC
	//SYSCFG_CFGR3: Bit 9 == 1: ADC2 mapped on DMA1 Ch2
	SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ADC2_DMA_RMP_1);
	
	//Vier Register sind wichtig
	//Configuration:						DMA_CCRx			MINC, PINK, CIRC, /MEM2MEM
	//Holding number of bytes:	DMA_CNDTRx
	//Source Adress: 						DMA_CMARx
	//Destination Adress: 			DMA_CPARx
	
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_DIR);			//Data Transfer Direction: 0 = Read from Peripheral
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_MEM2MEM);	//Nicht MEM 2 MEM
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_CIRC);		//Circ Mode Disabeled, wird nur von ADC EOC ausgelöst
	
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PL_0);		//Priority level
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PL_1);		//00 low, 01 med, 10 high, 11 very high
	
	SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MSIZE_0);			//Memory Size
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_MSIZE_1);		//00 8bit, 01 16bit, 10 32 bit
	
	SET_BIT(DMA1_Channel1->CCR, DMA_CCR_PSIZE_0);			//Peripheral Size
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PSIZE_1);		//00 8bit, 01 16bit, 10 32 bit
 
	SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MINC);				//Memory Increment
	CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PINC);			//NICHT Periph. increment
	
	//DMA Source und Destination Adressen setzen
	DMA1_Channel1->CMAR = ( uint32_t )&ADC_raw[0];
	DMA1_Channel1->CPAR = ( uint32_t )(&ADC1->DR);
	DMA1_Channel1->CNDTR = 4;
	
	SET_BIT(DMA1_Channel1->CCR, DMA_CCR_EN);					//DMA enablen
}
void TIM3_Init()
{
	//Timer zum Triggern des ADCs bei bestimmter Frequenz über TRGO
	
	TIM3->PSC = 0;			//Prescaler
	TIM3->ARR = 72-1;		//Auto Reload
	TIM3->CNT = 0;			//Count
	
		SET_BIT(TIM3->CR2, TIM_CR2_MMS_1);	//TRGO
		SET_BIT(TIM3->DIER, TIM_DIER_UIE);	//Update Interrupt Enable
		NVIC_EnableIRQ(TIM3_IRQn);					//TIM3 Interrupts enable
		SET_BIT(TIM3->EGR, TIM_EGR_UG);
		NVIC_SetPriority(TIM3_IRQn, 0);
	SET_BIT(TIM3->CR1, TIM_CR1_CEN);		//Timer Enable
}
static void ADC1_Init(void)
{
	//GPIO_MODER gesetzt?
	//RCC_AHBENR gesetzt? 
	//PA1 ist ADC Input
	
	//sicher gehen, dass Clock gesetzt ist
	SET_BIT(RCC->AHBENR, RCC_AHBENR_ADC12EN);
	
	
	//ADC1 disablen
	if(READ_BIT(ADC1->ISR, ADC_ISR_ADRDY))
	{
		SET_BIT(ADC1->ISR, ADC_ISR_ADRDY);
	}
	if(READ_BIT(ADC1->CR, ADC_CR_ADEN))
	{
		SET_BIT(ADC1->CR, ADC_CR_ADDIS);
	}
	
	//Warten bis ADC1 komplett disabled ist
	while(READ_BIT(ADC1->CR, ADC_CR_ADEN)) {}
		
	//ADC1 voltage regulator enablen
	//Enable sequence im Reference sheet (Seite 219)
	MODIFY_REG(ADC1->CR, ADC_CR_ADVREGEN, 0);
	MODIFY_REG(ADC1->CR, ADC_CR_ADVREGEN, ADC_CR_ADVREGEN_0);
		
	//kurzer delay zum enablen	
	/********************************DELAY FUNKTION NEU SELBER SCHREIBEN****************************/	
	HAL_Delay(2);
	
	//ADC1 Clock = HCLK/1
	MODIFY_REG(ADC12_COMMON->CCR, ADC12_CCR_CKMODE, ADC12_CCR_CKMODE_0 + ADC12_CCR_CKMODE_1);
		
	//Single Ended Mode für alle Kanäle
	ADC1->DIFSEL = 0x0;
		
	//Kalibrierung für single ended Mode starten
	CLEAR_BIT(ADC1->CR, ADC_CR_ADCALDIF);
	SET_BIT(ADC1->CR, ADC_CR_ADCAL);
		
	//Warten bis Kalibrierung erfolgt ist
	while(READ_BIT(ADC1->CR, ADC_CR_ADCAL));
	
	//Ready Flag zurücksetzen
	SET_BIT(ADC1->ISR, ADC_ISR_ADRDY);
	
	
	SET_BIT(ADC1->SQR1, ADC_SQR1_L_1 + ADC_SQR1_L_0);					//Sequnz Laenge = 4 (0011)
	SET_BIT(ADC1->SQR1, ADC_SQR1_SQ1_1); 											//Erste Konv Channel 2 (0010) Vin
	SET_BIT(ADC1->SQR1, ADC_SQR1_SQ2_2); 											//Zweit Konv Channel 4 (0100) Vout
	SET_BIT(ADC1->SQR1, ADC_SQR1_SQ3_0); 											//Dritt Konv Channel 1 (0001) Iin
	SET_BIT(ADC1->SQR1, ADC_SQR1_SQ4_0 + ADC_SQR1_SQ4_1);			//Viert Konv Channel 3 (0011) Iout
	
	SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP2_2);										//Sampling Time f. Channel 2 = 32 CLK
	SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP4_2);										//Sampling Time f. Channel 2 = 32 CLK
	SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP1_2);										//Sampling Time f. Channel 2 = 32 CLK
	SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP3_2);										//Sampling Time f. Channel 2 = 32 CLK
	
	SET_BIT(ADC1->CFGR, ADC_CFGR_CONT);											//Single conversion mode auswählen
	
	SET_BIT(ADC1->CFGR, ADC_CFGR_EXTSEL_2);										//External Trigger für TIM3_TRGO Event EXT4 0100
	SET_BIT(ADC1->CFGR, ADC_CFGR_EXTEN_0);										//External Trigger auf Rising Edge 01
	
	SET_BIT(ADC1->CFGR, ADC_CFGR_DMAEN);											//DMA einschalten
	CLEAR_BIT(ADC1->CFGR, ADC_CFGR_DMACFG);										//DMA im One Shot Mode
	
	//SET_BIT(ADC1->IER, ADC_IER_EOCIE);												//Interrupt Enable für EOC
	//SET_BIT(ADC1->IER, ADC_IER_EOSIE);												//Interrupt Enable für EOS
	
	NVIC_EnableIRQ(ADC1_IRQn);
	NVIC_SetPriority(ADC1_2_IRQn, 0);
	
	//ADC einschalten bis es funktioniert (aus Errata Sheet)
	do
	{
		SET_BIT(ADC1->CR, ADC_CR_ADEN);
	}
	while(!READ_BIT(ADC1->ISR, ADC_ISR_ADRDY));
	
 
	SET_BIT(ADC1->CR, ADC_CR_ADSTART);
	//togled1();
	
}//ADC1 Init

If you'd need any more information let me know!

1 REPLY 1

> SET_BIT(ADC1->CFGR, ADC_CFGR_CONT); //Single conversion mode auswählen

The code does not do what the comment says. In continuous mode, you are likely to cause ADC overrun, preventing further DMA.

Read the ADC chapter in RM.

JW