2026-01-17 2:50 AM - last edited on 2026-01-17 3:01 AM by Andrew Neil
Hi all,
I am using STM32G030F6P6 and trying to read ADC channel 11 and channel 16 using DMA.
ADC works correctly in polling and interrupt mode.
When I enable DMA, the ADC values in the buffer remain 0 all the time.
DMA does not trigger at EOC, and DMA transfer never happens.
I have been trying for 1 week, and I cannot understand what is wrong.
Configured ADC correctly (calibration, sequence, sampling time, etc.)
Configured DMA correctly (channel, source/destination, size, circular mode)
Enabled ADC DMA request (DMAEN)
Enabled DMAMUX (for STM32G0 series)
But still no data is transferred and buffer remains 0.
#include "stm32g030xx.h"
#include "gpio.h"
volatile uint32_t adc_value[2] = {0},adc_buff = 0, adc_index = 0;
void delay_ms(uint32_t ms)
{
SysTick->LOAD = 64000 - 1; // 64MHz ? 1ms
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_ENABLE_Msk;
for(uint32_t i = 0; i < ms; i++)
{
while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}
}
void RCC_Clock_Config(void){
//Clock Config
RCC->CR &= ~RCC_CR_PLLON;
while(RCC->CR & RCC_CR_PLLRDY);
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLSRC; // Clear both PLLSRC bits
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_1; // 10b ? HSI16
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLM;
RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_0;
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLN;
RCC->PLLCFGR |= (16U << RCC_PLLCFGR_PLLN_Pos);
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLR;
RCC->PLLCFGR |= (1U << RCC_PLLCFGR_PLLR_Pos);
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN;
FLASH->ACR &= ~FLASH_ACR_LATENCY;
FLASH->ACR |= FLASH_ACR_LATENCY_2; // 48–64 MHz ? 2 WS
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= (2 << RCC_CFGR_SW_Pos);
while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != 0x2);
}
void UART2_Init(void){
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
GPIO_Init(GPIOA,2,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_HIGH);
GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL2_Msk;
GPIOA->AFR[0] |= (1U << GPIO_AFRL_AFSEL2_Pos);
RCC->APBENR1 |= RCC_APBENR1_USART2EN;
USART2->CR1 = 0;
USART2->BRR = 556; // 115200 baud @ 64MHz
USART2->CR1 |= USART_CR1_UE;
USART2->CR1 |= USART_CR1_TE;
}
void UART2_Send_Byte(uint8_t c){
while(!(USART2->ISR & USART_ISR_TXE_TXFNF));
USART2->TDR = c;
while(!(USART2->ISR & USART_ISR_TC)); // wait transmission complete
}
void UART2_Send_Number(int32_t num)
{
char buf[12]; // enough for -2147483648
int i = 0;
if(num == 0){
UART2_Send_Byte('0');
return;
}
if(num < 0){
UART2_Send_Byte('-');
num = -num;
}
while(num > 0){
buf[i++] = (num % 10) + '0';
num /= 10;
}
while(i--){
UART2_Send_Byte(buf[i]);
}
}
void ADC_Init(void){
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
GPIO_Init(GPIOA,10,GPIO_MODE_ANALOG,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_LOW); //ADC Channel 16
RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
GPIO_Init(GPIOB,7,GPIO_MODE_ANALOG,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_LOW); //ADC Channel 11
RCC->APBENR2 |= RCC_APBENR2_ADCEN;
ADC1->CR &= ~ADC_CR_ADEN;
while(ADC1->CR & ADC_CR_ADEN);
ADC1->CR |= ADC_CR_ADVREGEN;
for(volatile int i=0;i<30000;i++);
ADC1->CR |= ADC_CR_ADCAL;
while(ADC1->CR & ADC_CR_ADCAL);
ADC1->CFGR1 = 0;
ADC1->CFGR1 |= ADC_CFGR1_CONT;
ADC1->CFGR1 |= ADC_CFGR1_CHSELRMOD;
ADC1->CFGR1 |= ADC_CFGR1_DMAEN;
ADC1->CFGR1 |= ADC_CFGR1_DMACFG;
//ADC1->CFGR1 |= ADC_CFGR1_CHSELRMOD;
ADC1->CFGR1 |= ADC_CFGR1_OVRMOD; // overwrite old data
ADC1->SMPR &= ~ ADC_SMPR_SMP1_Msk;
ADC1->SMPR |= (7U << ADC_SMPR_SMP1_Pos);
//ADC->CCR &= ~ADC_CCR_TSEN; // ?? this is the missing piece
/*ADC1->IER |= ADC_IER_EOCIE;
NVIC_SetPriority(ADC1_IRQn, 0);
NVIC_EnableIRQ(ADC1_IRQn);
__enable_irq();*/
ADC1->CHSELR = ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL16;
ADC1->CR |= ADC_CR_ADEN;
while (!(ADC1->ISR & ADC_ISR_ADRDY)); // ADC ready
//ADC1->CR |= ADC_CR_ADSTART;
}
uint16_t ADC_Read(void){
//ADC1->CR |= ADC_CR_ADSTART;
while(!(ADC1->ISR & ADC_ISR_EOC));
return ADC1->DR;
}
void DMA_Init(void){
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CCR = 0;
DMA1_Channel1->CCR |= (3 << DMA_CCR_PL_Pos); //Priority set very High
DMA1_Channel1->CCR |= (1 << DMA_CCR_MSIZE_Pos); // 16 bits
DMA1_Channel1->CCR |= (1 << DMA_CCR_PSIZE_Pos);
DMA1_Channel1->CCR &= ~DMA_CCR_DIR;
DMA1_Channel1->CCR |= DMA_CCR_CIRC; //Circularly porbe
DMA1_Channel1->CCR |= DMA_CCR_MINC;
DMA1_Channel1->CPAR = (uint32_t) &(ADC1->DR);
DMA1_Channel1->CMAR = (uint32_t)adc_value;
DMA1_Channel1->CNDTR = 2;
//DMA1_Channel1->CCR |= DMA_CCR_EN;
}
int main(void){
//Clock Config
RCC_Clock_Config();
//GPIO
//__enable_irq();
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
GPIO_Init(GPIOA,4,GPIO_MODE_OUTPUT,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_LOW);
//ADC
UART2_Init();
DMA_Init();
ADC_Init();
DMA1_Channel1->CCR |= DMA_CCR_EN; // enable DMA channel
ADC1->CR |= ADC_CR_ADSTART; // start ADC conversions
while(1){
int16_t adc = adc_buff;
int16_t T = 0;
UART2_Send_Number(adc_value[0]& 0xFFFF);
UART2_Send_Byte('\n');
UART2_Send_Byte('\r');
UART2_Send_Number(adc_value[1]& 0xFFFF);
UART2_Send_Byte('\n');
UART2_Send_Byte('\r');
GPIO_TogglePin(GPIOA,4);
delay_ms(100);
}
}
void ADC1_IRQHandler(void)
{
if (ADC1->ISR & ADC_ISR_EOC)
{
uint16_t val = ADC1->DR; // MUST read DR to clear EOC
adc_value[adc_index] = val;
adc_index++;
if (adc_index >= 2)
adc_index = 0;
}
}The DMA never transfers data and the buffer remains 0.
Even though ADC conversion is running and EOC flag is set, DMA is not triggered.
Please help me identify what is missing or wrong in my configuration.
What should I check?
Edited to apply source code formatting - please see How to insert source code for future reference.
Solved! Go to Solution.
2026-01-17 7:09 AM
I am not using a dev board. I am using microcontroller that is attached with my own pcb. Could you review my code.
2026-01-17 7:22 AM
I would strongly suggest that you first get it working with a known-good example on a known-good board.
2026-01-17 8:42 AM
Try start with LL instead bare, after LL work you can rewrite it (i mean waste time)
good start point
2026-01-17 9:17 AM
If I'm not mistaken, you don't set DMAMUX anywhere. You have to route DMA requests from ADC to your DMA channel.
In other words, how does your DMA channel 1 know that it should handle requests from ADC and not, for example, from UART or SPI?
2026-01-17 11:45 PM
Thank You very much