2022-11-25 06:47 AM
I have had an experience of working with TIM+ADC+DMA on microcontrollers F series. Now I need to use TIM+ADC+DMA on microcontroller STM32G030F6P6. A part of ADC and DMA registers was changed in G0 series. I want to digitize sequencely two channels after external event and get result with DMA. I wrote a code for working with TIM+ADC+DMA on STM32G030F6P6:
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
__NOP();
GPIOA->MODER |= GPIO_MODER_MODE4_0 | GPIO_MODER_MODE4_1; //11: Analog mode
GPIOA->MODER |= GPIO_MODER_MODE5_0 | GPIO_MODER_MODE5_1; //11: Analog mode
RCC->APBENR2 |= RCC_APBENR2_ADCEN;
__NOP();
ADC1->CFGR1 |= ADC_CFGR1_DMAEN; //1: DMA enabled
ADC1->CFGR1 |= (1 << ADC_CFGR1_EXTEN_Pos); //01: Hardware trigger detection on the rising edge
ADC1->CFGR1 |= (3 << ADC_CFGR1_EXTSEL_Pos); //TIM3_TRGO
ADC1->SMPR |= (7 << ADC_SMPR_SMP1_Pos); //160.5 ADC clock cycles
ADC1->SMPR |= (7 << ADC_SMPR_SMP2_Pos); //160.5 ADC clock cycles
ADC1->SMPR |= (1 << ADC_SMPR_SMPSEL4_Pos);
ADC1->SMPR |= (1 << ADC_SMPR_SMPSEL5_Pos);
ADC1->ISR |= ADC_ISR_CCRDY;
ADC1->CHSELR |= ADC_CHSELR_CHSEL4; //1: Input Channel-x is selected for conversion
while (ADC1->ISR & ~ADC_ISR_CCRDY);
ADC1->ISR |= ADC_ISR_CCRDY;
ADC1->CHSELR |= ADC_CHSELR_CHSEL5; //1: Input Channel-x is selected for conversion
while (ADC1->ISR & ~ADC_ISR_CCRDY);
ADC1->ISR |= ADC_ISR_CCRDY;
ADC1->CR |= ADC_CR_ADEN; // ON ADC
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
__NOP();
DMAMUX1_Channel0->CCR |= (5 << DMAMUX_CxCR_DMAREQ_ID_Pos); //ADC
DMA1_Channel1->CCR &= ~DMA_CCR_TEIE;
DMA1_Channel1->CCR &= ~DMA_CCR_HTIE;
DMA1_Channel1->CCR |= DMA_CCR_TCIE;
DMA1_Channel1->CCR |= (3 << DMA_CCR_PL_Pos); //11: Very high
DMA1_Channel1->CCR |= (1 << DMA_CCR_MSIZE_Pos) | (1 << DMA_CCR_PSIZE_Pos); //01: half-word (16-bit)
DMA1_Channel1->CCR |= DMA_CCR_MINC; //1: Memory address pointer is incremented after each data transfer (increment is done according to MSIZE)
DMA1_Channel1->CCR |= DMA_CCR_CIRC; //1: Circular mode enabled
DMA1_Channel1->CCR |= 0 << DMA_CCR_DIR_Pos; //00: Peripheral-to-memory ! 01: Memory-to-peripheral
DMA1_Channel1->CNDTR = 2; //Number of data items to transfer
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; //Peripheral address
DMA1_Channel1->CMAR = (uint32_t)&res_adc_other[0]; //Memory 0 address
NVIC_SetPriority(DMA1_Channel1_IRQn,0);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
DMA1_Channel1->CCR |= DMA_CCR_EN;
RCC->APBENR1 |= RCC_APBENR1_TIM3EN;
__NOP();
TIM3->CR2 = (2 << TIM_CR2_MMS_Pos); //010: Update - The update event is selected as trigger output (TRGO)
TIM3->PSC = 1600-1;
TIM3->ARR = 1000-1;
TIM3->EGR |= TIM_EGR_UG;
TIM3->SR &= ~ TIM_SR_UIF;
TIM3->CR1 |= TIM_CR1_CEN;
It doesn't work. I noticed that external event which should start ADC doesn't come from timer. If I manually start ADC (ADC1->CR |= ADC_CR_ADSTART) then I get result. Why does an external event not start ADC?
I went over the documentation several times, tried various options, but could not start TIM + ADC + DMA on STM32G030F6P6. I was already desperate and decided maybe someone could help me here ...
2022-11-25 06:57 AM
being 100% honest , i let cubeMX initialize these kind of things, or at least as a template to guide my own baremetal initialization code.
TIM3->CR2 = (2 << TIM_CR2_MMS_Pos); //010: Update - The update event is selected as trigger output (TRGO)
does what you want ?
ADC1->CFGR1 |= (3 << ADC_CFGR1_EXTSEL_Pos); //TIM3_TRGO
doing what you want?
2022-11-25 07:06 AM
I prefer CMSIS to understand how things work at the register level.
I was trying to use only TIM3. TIM1 is busy for PWM output. TIM4 is not present in this microcontroller.
are you sure of
TIM3->CR2 = (2 << TIM_CR2_MMS_Pos); //010: Update - The update event is selected as trigger output (TRGO)
does what you want ?
are you sure of
ADC1->CFGR1 |= (3 << ADC_CFGR1_EXTSEL_Pos); //TIM3_TRGO
doing what you want?
2022-11-26 10:11 AM
Debug Dig and split, make the timer output signal to a pin, then wire it to the adc trigger input pin. Check functionality stage by stage.
2022-11-28 02:56 AM
What if
TIM3->CR2 = (2 << TIM_CR2_MMS_Pos);
is overwriting some other important stuff in CR2?
Im seeing now you dont use any
|=
to set those bits
Or maybe youre trying to set the MMS in the wrong register, i dont really know, just trying to get some clues