2020-09-22 10:03 AM
I've been over and over RM0433 regarding how to set this mode up and I've never been able to get data from ADC2. ADC1 acts a bit oddly in that my reading says that 16 bit ADC results from both ADC1 and ADC2 are packed together in one uint32_t location. But in my work, I've seen only values from ADC1 (I have variable DC voltages from 0 to 3.3 on 4 ADC1 pins and 2 ADC2 pins). While I mentioned that I have voltages on only 2 of the ADC2 pins, ADC2 is set to convert 4 values as is ADC1. The data from ADC1 is packed as if it came from both ADC1 and ADC2, but I've verified that it's all coming from ADC1 pins. "Packed" as in two 16 bit values are in a 32 bit location and change when the external voltage is changed. EDIT ADD: This happened because I was using HALFWORD instead of WORD. Once I changed the DMA data width back to WORD, I see two 32 bit buffers that have activity, the others are constant zero. The high 16 bits appear to be noise, the low 16 bits are two of the ADC1 inputs.
I used STM32CubeMX to generate a Makefile project for this purpose.
I use software trigger (ADC_SOFTWARE_START), two DMA channels, no oversampling and I currently trigger only 5 times per second. I start the DMA with HAL_ADCEx_MultiModeStart_DMA() only on ADC1.
I am working with HAL, and though I can't see in RM0433 what I'm doing wrong, I know that I must be.
Things I am confused about is when to use WORD and when to use HALFWORD when using 16 bit ADC values in dual ADC mode for regular simultaneous conversions.
Information on the web is as to be expected of dubious value, much of it showing wrong ways to do things and then never following up with what fixed the problem.
Any help with this is greatly appreciated.
2020-09-22 10:48 AM
> Information on the web is as to be expected of dubious value, much of it showing wrong ways to do things and then never following up with what fixed the problem.
I agree. Perhaps you can find out what is wrong and report back. The CubeMX example very likely works correctly:
2020-09-22 11:16 AM
I got the interleaved project to half-a$$ work, I was getting values, but it was also throwing exceptions with HAL_BUSY when a new DMA start is executed.
This is going into a commercial product, so it is imperative that I get it working. I do intend to come back and post results, I would post my hello-world code once it works.
2020-09-22 12:33 PM
I now appear to be getting some good data from ADC1 and ADC2 simultaneously.
If I set ADC_CONVERTED_DATA_BUFFER_SIZE to 4, I get 2 values from ADC1 and 2 values from ADC2 in the upper and lower 16 bits of the buffer space. I have both ADCs set to have the number of conversions set to 4 on both ADCs where I am using 8 unique pins. If I had set both to 2 conversions each, these results would be correct. I'm probably chasing a wild goose, but I'm going to read out the registers to see if the HAL stuff is actually making it to the ADC registers. If I set the buffer size to 8, the ADC2 values turn into what looks like floating pins.
Both ADCs are showing an L (sequence length) value of 3 which translates to 4 conversions for each ADC (ADC x regular sequence register 1). So that isn't the problem.
2020-09-22 01:25 PM
I have it working properly now. I had an intellectually deficient moment and did not code the half and cplt callbacks to copy ALL of the data... I have 8 channels, 6 of which have pots connected and 2 are open. They all behave as they should with the open pins near 0x4000 with random bobble and the potted pins show the value from 0 to FFFF. I will clean up the code and post it as an 8 channel dual ADC regular simultaneous conversions. The program operates at 50000 sequence starts per second.
2020-09-22 02:13 PM
Here are the 4 most important files: main.c, main.h, stm32h7xx_hal_msp.c and stm32h7xx_it.c in the attached zip file. The firmware used was version 1.4.0 for STM32H7. The CPU is STM32H743VIT which I have on a special board and not a nucleo. The project runs with a CPU clock of 480 MHz. There is no Virtual Com Port per se, though you see calls to a vcp() function. This is USART3 wired to a RS232 interface and plugged into my workstation. The timer that launches each conversion sequence is set to run at 50kHz. Note that there are no cache invalidate statements. I use the MPU to turn cache off in the first 8 kilobytes of RAM D2.
Hopefully someone finds this useful.
2020-09-22 02:48 PM
Found an error and I can't delete the post or the attachment so please use this one instead. main.c had the buffer size at 16 when it should be 8 because each time the sequence is executed, it gathers 4 uint32_t values. The value is set to 2 times larger so that the halfcplt and cplt callbacks work correctly. At 16, the DMA would probably write twice as far into RAM as it's supposed to.
This project used:
480 MHz CPU clock
ADC1 and ADC2 set for 16B resolution
ADC1 and ADC2 set for ADC scan enable
ADC1 and ADC2 set for EOCSelection set to ADC_EOC_SEQ_CONV
ADC1 and ADC2 set for Trigger conversion by ADC_SOFTWARE_START
ADC1 and ADC2 set for DMA in one shot mode
All 8 ADC inputs are set to 32.5 cycles sample time.
I chose to leave oversampling disabled.
Both DMA controllers have:
DMA_PINC_DISABLE
DMA_MINC_ENABLE
Alignment is WORD for both peripheral and memory
I used STM32CubeMX to create the project hardware requirements and generate the project files needed to access those resources. The code for dual ADC configuration was correctly generated by STM32CubeMX. Where I messed up was mainly with the DMA. I set to half word because the ADC values fit in 16 bits. This is incorrect and needs to be set to word even though the ADC is set for 16 bits. The values are deposited as two uint16_t in one uint32_t with ADC1 as bits [15:0] and ADC2 as bits [31:16]. The callbacks can distribute the data to an array of uint16_t.
This code is probably not optimal, I'm sure there is tuning in terms of ADC clock speed and/or sampling times.