The ADC1 & ADC2 is configured in multimode with DMA and trigged by TIM1, but I only get half sample rate 20 kHz. What I have done wrong? Q2 I can only use TIM1 Trigger 2 Out Event to trig the ADCs. Why can I not use any other timers or events?
- September 22, 2019
- 8 replies
- 5197 views
static void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode;
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO2;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_DUALMODE_REGSIMULT;
multimode.DMAAccessMode = ADC_DMAACCESSMODE_2;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}/* TIM1 init function */
static void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}/* TIM4 init function */
static void MX_TIM4_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 2499;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}int main(void)
{
// Enable I-Cache & D-Cache
SCB_EnableICache();
SCB_EnableDCache();
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_TIM4_Init();
MX_TIM1_Init();
MX_ADC2_Init();
if(HAL_TIM_Base_Start_IT(&htim4) != HAL_OK)
{
// Error
while(1);
}
while (1)
{
HAL_Delay(1);
}
}void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
HAL_ADCEx_MultiModeStop_DMA(&hadc1);
HAL_ADC_Stop(&hadc2);
HAL_GPIO_TogglePin(PK2_LED_GPIO_Port, PK2_LED_Pin);
if(m_res_cnt < 1000)
{
//m_res_adc_buf[m_res_cnt++] = HAL_ADC_GetValue(hadc);
m_res1_adc_buf[m_res_cnt] = m_adc_buf[0];
m_res2_adc_buf[m_res_cnt] = m_adc_buf[1];
m_res3_adc_buf[m_res_cnt] = m_adc_buf[2];
m_res4_adc_buf[m_res_cnt++] = m_adc_buf[3];
}
else
{
m_res_cnt = 0;
}
}void TIM4_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim4);
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)&m_adc_buf, 4);
HAL_GPIO_TogglePin(PK0_LED_GPIO_Port, PK0_LED_Pin);
HAL_TIM_Base_Start_IT(&htim1);
}void TIM1_UP_TIM10_IRQHandler(void)
{
HAL_GPIO_TogglePin(PK1_LED_GPIO_Port, PK1_LED_Pin);
HAL_TIM_Base_Stop_IT(&htim1);
HAL_TIM_IRQHandler(&htim1);
}I start TIM1 in
void TIM4_IRQHandler(void)
{
...
HAL_TIM_Base_Start_IT(&htim1);
...
}
and stop TIM1 in
void TIM1_UP_TIM10_IRQHandler(void)
{
...
HAL_TIM_Base_Stop_IT(&htim1);
...
}
I start the ADC DMA in
void TIM4_IRQHandler(void)
{
...
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)&m_adc_buf, 4);
...
}
and stop ADC DMA in
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
...
HAL_ADCEx_MultiModeStop_DMA(&hadc1);
HAL_ADC_Stop(&hadc2);
…
}I'm using STM32F746, and the configuring is done with the HAL-library.
In the code below there is a 40 kHz TIM4 interrupt.
The ADC1 & ADC2 is configured in multimode which is triggered by TIM1.
I also use DMA for the ADC data transfer
Each ADC samples 2 channels (ADC1: IN3, IN4), (ADC2: IN5, IN6).
TIM1 is invoked in TIM4 interrupt handler and stopped in TIM1 interrupt handler.
The 4 data from ADC1 & ADC2 are accessible in HAL_ADC_ConvCpltCallback()
The problem is that the ADCs only samples data with 20 kHz instead of 40 kHz.
I have try several different setting but I cannot increase the ADC sampling rate.
Can someone point out what I have done wrong?
As you can see I have enabled Scan Conversion Mode but disabled Continuous Conversion Mode
As I understand it, (when I read the STM32F746 user manual), it should be enough with one TIM1 trigger to the ADC, since the ADCs should the be responsible to sample all channels automatically and the invoke HAL_ADC_ConvCpltCallback() (when End of Conversion Selection = ECO flag at the end of all conversations).
I saw somewhere that someone suggested to activate the Continuous Conversion Mode to get all channels sampled when a timer is triggs the ADCs but I cannot find anything which confirms this in the STM32F746 user manual.
I have another problem too and that is that the only trigger event that is possible to use to trig the ADCs is timer 1 Trigger 2 Out Event. Why can I not use any other timer or events?
I have tried to trig the ADCs with timer 4. The settings I have tried are:
TIM4 ADC1
- TRGO update event -> Timer 2 Trigger Out Event
- Output Compare (OC1REF) -> Capture Compare 1 event
- Output Compare (OC2REF) -> Capture Compare 2 event
- Output Compare (OC3REF) -> Capture Compare 3 event
- Output Compare (OC4REF) -> Capture Compare 4 event
Nothing above are working.