2018-02-28 05:56 AM
Hi everyone,
I need to control the ADC in a STM32F769 MCU to take a bunch of samples after a period of time (this acquisition is repeated over time). My idea is to use one timer as a counter and as master controller of another timer. This second timer would be configured as One-shot so it can take x samples (x One-shot times). Each one-shot should then trigger the ADC and at the end of conversion the DMA would have to take the sample and put it in a buffer in the memory automatically.
To give an intuition of this previously description I attach a pdf with a schematic of what I want to do.
I have made some tests trying to configure one timer as a counter to trigger the ADC and also the DMA but unfortunately It doesn't seem to work properly. The DMA seems to work only the first time but no after the first triggering. I am not sure what I am doing wrong.
I am also wondering whether this is the best way to take samples from an ADC.
This is the configuration of the peripherals used for the tests (using only one timer as up counter):
/* ADC1 init function */
static void MX_ADC1_Init(void){ 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_DIV2; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T6_TRGO; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = ENABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc1) != 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 = 1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }}/* TIM6 ------------------------------------------------------------------------------- */
/* TIM6 init function */
static void MX_TIM6_Init(void){ TIM_MasterConfigTypeDef sMasterConfig; htim6.Instance = TIM6; htim6.Init.Prescaler = 12000; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 5000; htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }}/* DMA ----------------------------------------------------------------- */
/**
* Enable DMA controller clock */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);}/* MAIN FUNCTION -------------------------------------------------------------------------------------------------------------------------- */
int main(void)
{/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_TIM6_Init(); MX_ADC1_Init(); /* init the ADC DMA conversion */ HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADCreadings, 1); /* Init the timer for triggering the ADC */ HAL_TIM_Base_Start(&htim6); while (1) { }}Thanks in advanced,
Omar
#stm32f7-dma #dma-adc #stm32f72018-02-28 06:00 AM
Advanced timers have a repetition counter, and can recycle a defined number of times (8-bit wide), ie one-shot generating multiple pulses.
2018-02-28 09:08 AM
I am not sure if I understand your idea on how to use the repetition counter. I checked the reference manual and the repetition counter is used to count how many overflows need the timer to make the Update Event and set the flag of the interrupt (if repetition counter equal to 5, the timer will overflow 5 times and then set the interrupt). How I can use this functionality inside my idea??
Thanks again,
Omar
2018-02-28 09:27 AM
The ADC can be triggered by TIMx_CCx, with a repetition count of 10 this will sample 10 times for every update, a TIM in one-shot mode will fire 10 equidistance pulses and stop.
Alternatively you might consider sampling on a persistent timebase, know where you start signal is on this timeline, and discard the samples which are of no interest.
2018-03-01 12:21 AM
Hi Clive,
thanks for your replies. I think now understand your idea. Take a look at the attached image, is this the configuration you are trying to explain??
2018-03-01 06:51 AM
Hi again Clive,
I am taking a look to some example projects and code trying to configure the TIM1 as the timer for triggering the ADC using the 5 channel to compare. Also I am configuring it as One-Pulse mode.
The problem is that I can't find examples of code configuring the timer this way so I am bit lost here.
Can you help me with the configuration of the timer??
Thanks,
Omar