2021-07-11 07:37 AM
I'm using STM32F303RE, and I'm trying to sense analog values from different ports of the ADC using the DMA, but at the moment the application is running, I don't get any data. I tried to put an interrupt routine to see if the DMA is at least been called like the following:
extern "C" {
void DMA1_Channel1_IRQHandler(void){
if(DMA1->ISR & (1U << 1U)){
counter ++;
DMA1->IFCR |= (1U << 1U);
}
}
}
but it never gets called.
this is my initialization function for the ADC and DMA:
void Initializate_ADC1(){
periph::GPIO::set_pin(GPIOA, 0, ANALOG);
periph::GPIO::set_pin(GPIOA, 1, ANALOG);
/*configuring dma for the ADC*/
DMA1_Channel1->CCR |= DMA_CCR_CIRC | DMA_CCR_MINC | DMA_CCR_PSIZE_0 | DMA_CCR_MSIZE_0 ;
//inside the adc DMA function it activates the sha channel
//Configure length and channels
DMA1_Channel1->CCR |= DMA_CCR_TCIE;
ADC1->SQR1 = 0;
ADC1->SQR1 |= (ADC_LENGTH_2 << 0U);
periph::ADC::SetChannelSequence(ADC1_SQR1, ADC_CH_1, ADC_SQ1_1);
periph::ADC::SetChannelSequence(ADC1_SQR1, ADC_CH_2, ADC_SQ1_2);
periph::ADC::DMA_Init(ADC1, DMA1_Channel1, adc_dma_buffer, DMA_BUFFER_LENGTH,ADC_LENGTH_2);
}
I have to say that functions like set_pin and set channel sequence work perfectly, now, this is my ADC DMA_Init:
void DMA_Init(ADC_TypeDef * adc, DMA_Channel_TypeDef * dma_ch, std::uint16_t * buffer, std::uint32_t buffer_length,std::uint8_t length){
adc->CFGR |= ADC_CFGR_CONT;
adc->CFGR |= ADC_CFGR_DMAEN;
adc->SMPR1 |= (7U << 3U) | (7U << 6U); //max sampling rate
dma_ch->CPAR = (std::uint32_t)(&adc->DR);
dma_ch->CMAR = (std::uint32_t)(buffer);
dma_ch->CNDTR = buffer_length;
dma_ch->CCR |= DMA_CCR_EN;
Enable_regulator(adc);
Calib(adc);
Enable(adc);
}
adc-> in this case, I passed ADC1 as a parameter to configure it.
dma_ch-> DMA channel as a parameter, I'm using channel one of DMA1 because the reference manual says that one of the peripherals of channel one corresponds to ADC1.
Enable_regulator, Calib, and Enable work perfectly.
If not too much bother to try to understand what's wrong or what I'm doing wrong.
Thanks
2021-07-11 08:08 AM
You need to enable the NVIC interrupt.
2021-07-11 08:12 AM
Yes, I have enabled the interrupt:
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
2021-07-11 08:26 AM
Do any other flags in DMA1_ISR get set? Particularly an error flag.
There's stuff here that you're not including in your OP (like NVIC), so it's a bit hard to debug with only pieces. Investigating the register values of ADC and DMA would probably expose the problem the quickest.
> DMA1->IFCR |= (1U << 1U);
Although not the cause of the issue here, IFCR is write only. To clear bit 1, this should be DMA1->IFCR = (1U << 1U);
2021-07-11 08:41 AM
Yes, I checked the error flags if any get set but no, there is no error flag set. If helps, this is the complete main function:
int main(void){
__disable_irq();
/*variables initializations*/
volatile std::uint16_t sensor_value_1 = 0;
/*configure clock for ADC*/
RCC->CR |= RCC_CR_PLLON;
RCC->CFGR2 |= (16U << 4U);
/*Peripheral activation*/
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
RCC->AHBENR |= RCC_AHBENR_ADC12EN;
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
/*Peripheral initializattions*/
periph::GPIO::set_pin(GPIOA, 5, OUTPUT);
Initializate_UART3();
Initializate_ADC1();
volatile std::uint16_t val = 54230;
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
__enable_irq();
while(1){
data1 = adc_dma_buffer[0];
data2 = adc_dma_buffer[1];
utils::delay::ms(10);
}
}
And here are some functions I used for the ADC:
void Enable(ADC_TypeDef * adc){
adc->CR |= ADC_CR_ADEN;
while(!(adc->ISR & ADC_ISR_ADRDY)){}
}
void Disable(ADC_TypeDef * adc){
adc->CR |= ADC_CR_ADDIS;
while((adc->CR & ADC_CR_ADEN)){}
}
void Enable_regulator(ADC_TypeDef * adc){
adc->CR &= ~(ADC_CR_ADVERGEN_CLEAR);
adc->CR |= ADC_CR_ADVERGEN_ENABLE;
utils::delay::us(25);
}
void Calib(ADC_TypeDef * adc){
Disable(adc);
adc->CR &= ~ADC_CR_ADCALDIF;
adc->CR |= ADC_CR_ADCAL;
while((adc->CR & ADC_CR_ADCAL) != 0){}
}
2021-07-11 02:51 PM
ok, what it seems, in the STM32F303, is necessary to start a conversion, with this: ADC1->CR |= ADC_CR_ADSTART; and then, the DMA makes the request. The thing is, I was watching a video of a guy that uses stmf1 and he didn't start any conversion when using the ADC, and I was reading the reference manual and I notice this part: "a DMA request is generated
after each conversion of a channel." I didn't understand at first but reading carefully now, it was that.
Thanks for taking the time to reply to me and forgive any inconvenience.