cancel
Showing results for 
Search instead for 
Did you mean: 

ADC: DMA of injected conversions does not work, when there are no regular conversions

Tobe
Senior III

Hi,

i created this minimum code, where the dma for the injected conversions will not work. Only after each(!) start of a regular conversion, the injected conversion does work for one time. I have set it up, in a way, that it should work in circular mode.

The pin is not set up, but it does not matter anyway.

 

uint32_t lastADCMeasure = 0;
volatile uint16_t adc2InjectedBits = 99;
volatile uint16_t adc1InjectedBits = 99;

void setup(){
	// ######### DMA ###########
	SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN);	// Enable clock //TODO: move to better place and test if working
	delayMicroseconds(50);
	SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN);	// Enable clock //TODO: move to better place and test if working
	delayMicroseconds(50);

	// ######## DMAMUX ######### as per 13.3.2 (13.4.3)
	SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN);	// Enable DMAMUX	//TODO: move to better place and test if working
	delayMicroseconds(50);

	DMA1_Channel3->CPAR = (uint32_t) &(ADC2->JDR1);		// Address of source
	DMA1_Channel3->CMAR = (uint32_t) &adc2InjectedBits;	// Address of memory

	DMA1_Channel3->CCR |= DMA_CCR_PL_1 | DMA_CCR_PL_0;	// Priority highest

	DMA1_Channel3->CCR |= DMA_CCR_MSIZE_0; 	// 16 bits memory destination
	DMA1_Channel3->CCR |= DMA_CCR_PSIZE_0; 	// 16 bits peripheral destination

	DMA1_Channel3->CCR |= DMA_CCR_TEIE;		// Transfer error interrupt enable
	DMA1_Channel3->CCR |= DMA_CCR_TCIE;		// Transfer complete interrupt enable

	DMA1_Channel3->CNDTR = 1;				// Number of data to be transferred

	// ######## DMAMUX ######### as per 13.3.2 (13.4.3)
	DMAMUX1_Channel2->CCR |= 36;			// ADC 2 (DMAMUX channel to DMA connection: 13.3.2)

	DMA1_Channel3->CCR |= DMA_CCR_CIRC; 	// Circular mode

	DMA1_Channel3->CCR |= DMA_CCR_EN;		// Enable channel (

	SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADC12EN);
	delayMicroseconds(1); 	// CAUTION: 	Just after enabling the clock for a peripheral, software must wait for a delay before accessing the peripheral registers.

	ADC12_COMMON->CCR |= (ADC_CCR_CKMODE_1 | ADC_CCR_CKMODE_0);		// adc_hclk/4 -> 42.5Mhz

	delayMicroseconds(1);

	ADC2->CR &= ~ ADC_CR_DEEPPWD;	// Disable power down (is default after reset)

	ADC2->CR |= ADC_CR_ADVREGEN;	// Enable voltage regulator
	delayMicroseconds(100); 			// Wait for voltage regulator to start up (fixed value of datasheet!)

	ADC2->CR |=	ADC_CR_ADCAL;		// Calibrate single ended (ADCALDIF is default 0)

	while(ADC2->CR & ADC_CR_ADCAL);	// Wait until calibration has finished
	delayMicroseconds(50); 			// ADC can only be enabled after short wait after ADCAL

	ADC2->ISR |= ADC_ISR_ADRDY;		// Clear ready bit for reading the right status below

	ADC2->CR |=	ADC_CR_ADEN;		// Enable ADC

	while((ADC2->ISR & ADC_ISR_ADRDY) == false); 			// Wait until ready

	ADC2->JSQR |= (ADC_JSQR_JSQ1_1 | ADC_JSQR_JSQ1_0);		// Channel 3 injected (with dual mode)

	ADC2->CFGR |= ADC_CFGR_DMACFG; 							// DMA circular mode
	ADC2->CFGR |= ADC_CFGR_OVRMOD;							// Overrun overrides data
	ADC2->CFGR |= ADC_CFGR_DMAEN; 							// Enable DMA

	while(1){
		delay(100);
		ADC2->CR |= ADC_CR_JADSTART;
		delay(100);

		if(millis() - lastADCMeasure > 350){// && lastADCMeasure == 0){
			ADC2->CR |= ADC_CR_ADSTART; 	// Start new regular measurements TODO: keep away from times of noise (communication etc.)
			lastADCMeasure = millis();
		}
	}
}

 

 

 

0 REPLIES 0