Goal
In STM32F103, with External trigger(Timer3 TRGO) Capture data from for two ADC pin PA0 and PA1.
Plan here
- ADC2 configured to PA0 pin then Storing data via ADC Interrupt
- ADC1 configured to PA1 pin capture in DMA Channel 1 via DMA interrupt data 3. is stored
Both ADC1 and ADC2 is trigger by Timer 3 TRGO input
Code used here
// Interrupt service routine for the timer
void setup_timer3_ADC_PA0_PA1()
{
// ADC2 used to meaursing the GA pin (Voltage/Current).
/*
1. Setting up Timer 3 to Output TRGO
2. Setting up ADC2 to Trigger on Timer 3 TRGO
3. From the ADC2 Conversion Complete Interrupt I will store the ADC data
4. Start the ADC2
*/
// Setup ADC2 to Trigger on Timer 3 TRGO
__HAL_RCC_ADC2_CLK_ENABLE();
hadc2.Instance = ADC2;
hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO; // Triggered by Timer 3 TRGO
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc2);
ADC_ChannelConfTypeDef adc2ChannelConfig = {0};
adc2ChannelConfig.Channel = ADC_CHANNEL_0; // Selected pin PA0
adc2ChannelConfig.Rank = ADC_REGULAR_RANK_1; // For ADC2, this should be Rank 1.
adc2ChannelConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
HAL_ADC_ConfigChannel(&hadc2, &adc2ChannelConfig);
//--------------------------------------------------------------------------------------------
// Setting up Timer 3 to Output TRGO
__HAL_RCC_TIM3_CLK_ENABLE();
timer3_set_interval(100, 10);
//--------------------------------------------------------------------------------------------
// Enable interrupt for ADC1_2
HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
// ADC1 used to measure the AFC pin
// Setup ADC1 to Trigger on Timer 3 TRGO
__HAL_RCC_ADC1_CLK_ENABLE();
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO; // Triggered by Timer 3 TRGO
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
ADC_ChannelConfTypeDef adc1ChannelConfig = {0};
adc1ChannelConfig.Channel = ADC_CHANNEL_1; // Selected pin PA1
adc1ChannelConfig.Rank = ADC_REGULAR_RANK_1; // ADC1 configured here
adc1ChannelConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &adc1ChannelConfig);
//--------------------------------------------------------------------------------------------
// DMA controller clock enable
__HAL_RCC_DMA1_CLK_ENABLE();
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&hdma_adc1);
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
// The link between hadc1 and hdma_adc1 was completed via:
uint8_t ADC_BUFLEN = 10;
HAL_ADC_Start_DMA(&hadc1, &buffer_adc_AFC, ADC_BUFLEN); // Link DMA to ADC1
// DMA interrupt init
// DMA1_Channel1_IRQn interrupt configuration
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0); // Second priority than ADC interrupt
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
// interrupt handler for ADC 1 & 2
extern "C" void ADC1_2_IRQHandler(void)
{
HAL_ADC_IRQHandler(&hadc2);
}
extern "C" void DMA1_Channel1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc1);
// Check if transfer is complete
if (__HAL_DMA_GET_FLAG(&hdma_adc1, DMA_FLAG_TC1))
{
// Transfer complete: Process or analyze data in adc1_data_buffer
store_AFC_data(&buffer_adc_AFC);
// Clear the DMA transfer complete flag
__HAL_DMA_CLEAR_FLAG(&hdma_adc1, DMA_FLAG_TC1);
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC1)
{
int16_t adc_pa0 = HAL_ADC_GetValue(hadc);
if (adc_capture_data_enable)
if (measure_volt_flag || measure_current_flag)
store_VI_data(adc_pa0); // Store Voltage data
}
}
void store_VI_data(int16_t _sdata)
{
// Circle or Ring Buffer to store data Volt, Current Measure data
// NOTE: Here only memory pointing variable is used.
_adc_sample_time_gap += (micros() - _timer3_record);
_adc_sample_time_gap /= 2;
_timer3_record = micros();
if (measure_volt_flag)
{
if (volt_sample_count < _sample_size)
volt_sample_count++;
else
volt_sample_count = 0;
volt_raw_data[volt_sample_count] = _sdata;
}
else if (measure_current_flag)
{
if (current_sample_count < _sample_size)
current_sample_count++;
else
current_sample_count = 0;
current_raw_data[current_sample_count] = _sdata;
}
}
void store_AFC_data(uint32_t *_sdata2)
{
if (AFC_sample_count < _sample_size)
AFC_sample_count++;
else
AFC_sample_count = 0;
AFC_raw_data[AFC_sample_count] = _sdata2[0];
}
Problem
After flashing this code STM32 is getting hang. I trying many combined still unable get a proper ADC
Related my previous posts
- ADC timer link
cc: maxgerhardt