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.
2026-01-17 3:03 AM
Welcome to the forum.
Please see How to write your question to maximize your chances to find a solution for best results
In particular, please give details of your hardware setup, and your software tools.
Have you tried the examples provided by ST ?
2026-01-17 3:12 AM
I am using STM32G030F6P6 with Keil uVision. I am programming in bare-metal (no HAL/CubeMX). I did not use any ST example. I configured the ADC and DMA manually based on the datasheet, and I also tried using code generated with ChatGPT, but the DMA still does not work.
2026-01-17 3:16 AM - edited 2026-01-17 3:34 AM
@shohanur00 wrote:I am using STM32G030F6P6
That's just the STM32 chip - what about the external hardware?
See point 2 & 3 of How to write your question to maximize your chances to find a solution
PS:
@shohanur00 wrote:I did not use any ST example.
Would be worth trying.
@shohanur00 wrote:I also tried using code generated with ChatGPT, .
Have you tried Sidekick - ST's AI agent specifically trained for STM32?
2026-01-17 3:33 AM
I have use 2 ant sensor at PA10 and PB7, I have read ntc sensor value with polling and interrupt method , Thats works fine , but DMA method not working .
2026-01-17 3:33 AM
I have use 2 ant sensor at PA10 and PB7, I have read ntc sensor value with polling and interrupt method , Thats works fine , but DMA method not working .
2026-01-17 3:51 AM
I have use 2 ntc sensor at PA10 and PB7, I have read ntc sensor value with polling and interrupt method , Thats works fine , but DMA method not working .
I haven't use sidekick
2026-01-17 6:14 AM
I suggest getting the working examples up and running. If you really want to use bare metal, compare register values on the working examples vs your code.
2026-01-17 6:19 AM
Where I will get bare metal example?
2026-01-17 6:43 AM
Start a project in CubeMX - choose to base it on an example from the list.
You still haven't said what board you're using but, if it's an ST board, there will be examples specifically for it ...