2020-09-07 12:30 PM
Hi,
I am using a STM32G431KB board with STMCubeIDE. I am trying to read out the one ADC using DMA but have run into problems. As I am new to the STM32G4 and STM STMCubeIDE. I decided to follow the example of Shawn Hymel https://www.youtube.com/watch?v=EsZLgqhqfO0. A number of other examples are available which are essentially the same.
I got the single conversion example working correctly. This tells me the ADC is working.
The ADC-DMA example did not work and despite several weeks of investigation I am unable to find the reason for this. I have attached the key parts of the main code. This sets up the ADC and immediately before calling HAL_ADC_Start_DMA writes a constant value of 2047 to the ADC buffer. Once started the buffer is read out to the UART where the conversion values (albeit without sync) are written.
What I can deduce from this code is:
1. Zeros are being written to the ADC buffer by the DMA instead of the ADC conversion value. (The debugger shows that the “2047�?s are overwritten with zeros).
2. The buffer half-complete and buffer complete interrupts are being called.
3. The timing of the digital toggle on GPIO pin 10 is consistent with a ADC clock of 170/4 MHz, suggesting the clocks are set correctly.
Other tests revealed:
4. HAL_ADC_Start_DMA does not return an error code.
5. Reading the forum it seems the capacitor switching can lead to the ADC conversion becoming frail at too high a clock frequency. So I tried changing the clock pre-scaler from divide by 4 to divide by 6. This gave no improvement.
Incidentally, I did try to import the code to the Arduino IDE. That did not work either.
If anybody has any idea what is wrong, or where to look. Please let me know.
Many thanks in advance.
volatile uint16_t adc_buf[ADC_BUF_LEN];
char msg [20];
int16_t ix;
int main(void)
{
HAL_Init();
for (int i = 0;i < ADC_BUF_LEN; i++){
adc_buf[i] = 2047;
}
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, ADC_BUF_LEN);
sprintf(msg, "Started ADC \r\n");
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
HAL_Delay(1);
while (1)
{
for (int i = 0; i < ADC_BUF_LEN; i++ ){
sprintf(msg, "%i : %hu\r\n",i, adc_buf[i]);
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
HAL_Delay(1);
}
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc1){
// Test_set GPIO pin High
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc2){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
}
2020-09-07 12:45 PM
Read the ADC/DMAMUX/DMA chapters in RM. Read out and check/post the ADC/DMAMUX/DMA/relevant GPIO registers content.
You may want to start with a polled ADC implementation, and then proceed to DMA.
JW
2020-09-17 09:41 AM
Hi,
I have (i) started with a polled implementation and recorded the ADC registers, (ii) Implemented the ADC/DMA code Read out using the STM32CubeIDE debugger the registers.
(I) The polled ADC readout works.
(ii) The ADC/DMA/DMAMUX code does not work. The ADC DR register is stuck on zero. I have ascertained that the DMA is reading these zeros because if I populate the ADC buffer with some numbers, these are written over with zeros.
So the problem seems to be with the ADC and not the DMA. Reading the chapters in the manual the register values all seem OK. The only think I can think of is that the ADSTART bit in ADC_CR is not set. This should be 1 if the ADC is operating. I begin to think this can be a problem at the hardware level.
The non-zero register values and IDs for the non-zero bits are listed below.
Best regards,
H.
....Polling conversion WORKS
ADC1
ISR: 0x3 ESOP + ADRDY
CR: 0x10000001 adregen + ADEN
CFGR:0x80000000 JQDIS
TR1: 0xfff0000 HT1 (FFF)
TR2: 0xfff0000 HT2 (FFF)
TR2: 0xfff0000 HT3 (FFF)
SQR1: 0x40 SQ1
DR: 0x734 (changes)
....DMA conversion DOES NOT WORK
ADC1
ISR: 0xb EOS EOSMP ADRDY
IER: 0x3c0 OVRIE
CR: 0x10000001 ADVREGEN ADEN
CFGR: 0x80002003 JQDIS CONT DMACFG DMAEN
TR1: 0xfff0000 HT1 (FFF)
TR2: 0xfff0000 HT2 (FFF)
TR2: 0xfff0000 HT3 (FFF)
SQR1: 0x40 SQ1
DR: 0x0 (Does not change)
DMA1
ISR: 0x3 TCIF1 GIF1
CCR1: 0x5af EN TCIE HTIE TEIE MINC PSIZE MSIZE
CNDTR1: 0x1000 NTD = 0x1000
CPAR1: 0x50000040 PA = 0x50000040
CMAR1: 0x20000178 MA = 0x20000178
DMAMUX
C0CR: 0x5 DMAREQ_ID = 0x5
2020-10-04 04:15 PM
I have imnvestogated this further by looking at the ADC registers using debug. I come to the following:
I therefore seems to me the STM32G431KB board cannot be used with HAL and STMCubeIDE to read ADC1 via DMA (at least easily). The idea of HAL in the IDE is that it should facilitate simple and implementation of peripheral functions. I have had to spent about 2 months trying to find the problem, which hardly makes implementation of my project efficent.
2021-12-01 12:57 PM
I have a same problem. Can someone tell us what is wrong it G4 series? (I am using STM32G474, and even simple polling routine doesn't work clearly and seems to be extremly time dependent.)
2022-04-04 06:09 AM
Hello,
I'm also stuck with the same problem. DMA does not write to the buffer as requested and it is filled as default with 0s (zeros) only. Single conversion without DMA works fine. It is not just the G4 series.
But stranger is that it used to work. I followed the mentioned tutorial: https://www.youtube.com/watch?v=EsZLgqhqfO0 with Nucleo board STM32L4P5ZG and it worked fine last year (2021). I now need the same code and behavior that worked correctly before and now it just doesn't work anymore. I can just assume that there is an issue with an unsolicited update of STM32Cube IDE. I think I will need to set up the memory address for DMA manually now. I look forward to learning how to do this.
If anyone have found the solution for this problem, it would be great if he/she shares the experience.
2022-05-15 09:38 AM
I'm having the same issue on a custom board with an STM32G030F6P.
2022-05-15 01:07 PM
Hi,
I did not find a solution to the case with continuous repetitive ADC readout and DMA.
However, for another application using a STM32G431, I have successfully used TIM15 with 170 MHz clock frequency and a divide (synchronous) by 64 counter to trigger single ADC 12-bit conversions with DMA at close to maximum at 2.66 MS/s with what seems to be perfect synchronization. The fADC clock was (synchronous) 170/4 (synchronous) = 42.5 MHz. The theoretical maximum sample rate at this fADC is 2.83 MS/s for 12 bit conversions.
So, the best advice I can currently give is to use a timer to trigger the ADC at precise regular intervals. Moreover, I recommend synchronous division of the bus clock for fADC. This facilitates precise synchronization between the ADC trigger clock (TIM15 in my case) and ADC clock which gives exact sampling intervals.
My current thoughts are that as continuous polling with DMA take place at intervals that are determined (at least to some degree) by bus usage. As the bus latency can vary, the ADC sampling will not be exactly at the same time interval. These variations can be a problem as most signal processing algorithms require regular sampling intervals, or somehow, you know the exact sampling times. So maybe I was just not being very smart in my original project....
Best regards,
H.J. Whitlow
.
2024-05-29 08:49 AM
Hi,
Sorry to re-up this old subject... But it seems to match an issue I have... and it can be better than reopen a new one.
In our case, with G431KB (+cubeide last version 1.15):
- TIM6 triggers ADC2 (Both interrupts TIM6+ADC2 confirm that ADC do the job each time TIM6 overflow)
- We want DMA1 CH1 to be triggered by every acquition of ADC. But, we measured the period of DMA interrupts... and it is much faster than ADC acquisition!!!!!!!
- in some case, it happens (not randomly) that DMA copied a right value from ADC (sometime exactly every 21 seconds !!)
We just suspect that DMA is triggered by a bad signal...
But, when we disable the ADC, the DMA is not trigger anymore... that means it was "not so bad".
Any idea?
Any example of working TIM+ADC+DMA to help us?
Thanks!!!
2024-06-03 11:40 PM
I found my mistakes...
If you read this post beacause you met similar issue, your problem is certainly different...but I suggest you to check your "ranks" in the config of channels.
With G4, the ranks are not as simple as on STM32F1 family.... ! (0->6->12->18->24->and more crazy after instead of 0->1->2->3....)
Anyway, I got a software which correctly read in a circular way a list of channels, triggered with TIM6, and "DMA writing" values in an array!
've fun