2021-04-26 12:28 PM
Description:
I'm running Timer 3 to produce a continuous PWM output on Channel 1.
I'm also running Timer 1 in slave mode to Timer 3, in PWM one shot mode with the Repetition Counter set to 5 and the Update Event Interrupt enabled.
This causes Timer 1 to produce a stream of 5 pulses on its Channel 1 output after every Update Event on Timer 3.
I'm running ADC 1 in DMA mode with data stored in an array variable.
The ADC is triggered by the 5 Capture/Compare Update events from Timer 1.
The DMA is set up to store the data in an array.
When Timer 1 completes the 5 pulses it issues an Update Event which triggers a Timer Interrupt.
A HAL_TIM_PeriodElapsedCallback(...) is called and a brief output pulse is generated on a GPIO output pin. This can be observed on the oscilloscope.
I use STM Studio to track the values in the data array.
I can vary the ADC input voltage.
Problem:
The data array values remain at zero no matter what the input voltage is set to.
What am I doing wrong?
Relevant Code:
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define Number_of_Samples 5 // Number of ADC samples to collect *** NOTE: Number_of_Samples = TIM1 RCR+1 ***
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint32_t adc_data[Number_of_Samples]; // Array for collecting raw ADC samples (12 bit)
uint32_t adc_data_sum; // Summation of all 5 values of adc_data
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED);// Calibrate the ADC for both offset and linearity for single ended mode
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_data, Number_of_Samples);// Start the ADC with DMA transfer of the output to the variable "adc_data"
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // Start the sampling time base timer
HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1); // Start Timer 1 to produce 5 Capture/Compare Output Events that will trigger ADC1 to take a sample
TIM1->DIER=0x1; // This instruction is required to enable Timer 1 Update Event Interrupt because HAL_TIM_PWM_Start_IT doesn't do it
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_4, GPIO_PIN_SET); // Create an output pulse for the oscilloscope
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_4, GPIO_PIN_RESET); // Reset the output
}
STM32Cube IDE Set Up for ADC1:
2021-04-26 12:57 PM
Which STM32?
Observe ADC registers in debugger. While this might be intrusive and stop the stream of conversions (I'm not sure, ADCs are very complex and they vary across STM32 families a lot), you should see at least one converted output in the ADC data register.
Observe DMA registers. You should see NDTR changing.
Read out and check/post the relevant TIM, ADC, DMA and GPIO registers content.
JW
2021-04-26 01:45 PM
Register ADC1 - DR - RDATA is changing correctly with changing input voltage - showing that data is being produced by the ADC.
This would indicate that the ADC is being triggered properly by Timer 1 - so no need to look at Timer 1 (or timer 3) registers as they seem to be working properly.
Register DMA1 - S0NDTR - NDT has a value of 4 and does not seem to changing.
ADC Registers:
2021-04-26 02:17 PM
STM32H743ZI
2021-04-26 03:29 PM
> Register DMA1 - S0NDTR - NDT has a value of 4 and does not seem to changing.
Then check the path from ADC to DMA.
First, read the DMA-related sections of Data management subchapter of ADC chapter. Check the ADC registers if they are set up properly for DMA, and if there's no status blocking further conversion and/or DMA triggering.
Then check the DMAMUX registers relevant to given DMA stream.
Then check the DMA registers - the status bits and registers related to that channel.
JW
2021-04-26 09:03 PM
ADC1 uses DMA1 Stream 0
It does not appear that any of the required DMA control bits are set to 1.
I don't understand why.
2021-04-26 10:20 PM
DMAMUX is a complex machine of which you probably don't use nothing just the plain routing provided by the DMAREQ_ID field, which is filled in - just check if that value corresponds to ADC request, in table at beginning of the DMAMUX chapter.
In DMA, check if the destination memory buffer is accessible by given DMA, and avoid the problems imposed by caching. This should've been probably checked first, search here, is a reoccurring theme and there's a FAQ somewhere dealing with this. I don't use 'H7 nor Cube.
JW
2021-04-27 11:38 AM
How do I check to see if the destination memory buffer is accessible by the DMA?
2021-04-27 01:20 PM
Have a look at Table 3. Bus-master-to-bus-slave interconnect.
If you use DMA1/2, only TCM appears to be inaccessible in 'H7.
JW
2021-04-27 01:57 PM
I'm sorry but I don't understand what to do next.
My apologies but I am fairly new to the STM family and using STMCubeIDE and HAL.
I have implemented a fairly simple timer driven ADC converter routine with a DMA to store the data.
I have followed the manuals and on-line examples carefully but it simply does not work.
I have been trying to resolve this for several weeks now and am very frustrated. You appear to be telling me that this simple program does not work because of some complex oddity in the STM32H743 DMA architecture. I find it hard to believe that STM would produce a microcontroller that could not implement a simple ADC routine. If I can't make this simple program work, how does anyone make anything complicated work?
Am I missing something basic here? Someone must have successfully implemented a simple ADC routine with DMA. If that doesn't work it would be glaring flaw in the product!
Again, I am not being critical of you - I very much appreciate your time and efforts and would welcome your opinion on my points and any further investigative steps.