2025-01-13 03:58 AM - edited 2025-01-13 03:59 AM
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();
}
}
}