cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103- How Can I Start and stop ADC with timer trigger?

hamed_solar
Associate II
Posted on June 21, 2016 at 22:28

Hello,

I have used a timer for triggering ADC for sampling per 20uS and use DMA to transfer 100 sample to the array.

 I suppose that the total time of converting and sampling time for ADC is about 2uS. So at each 20uS I can transfer 10 samples to the array with DMA.

I want to know that does the ADC stop the conversion at the end of 20uS or it continues the conversion and transferring the data to the array until it fills the whole array ?

Is it possible to force the DMA to transfer the converted values to the zero index of the array at the start of each triggering?

I dont know the order of transferring the converted values to the array with DMA at the start of each triggering?

 

Regards

Hamed
15 REPLIES 15
Posted on June 23, 2016 at 14:47

Correct, it will not give you a DMA Interrupt after 5 samples in a buffer that holds 100

I wouldn't zero the pointer, it would create a discontinuity in the buffer, I'd rather just observe where in the buffer it was and save that pointer.

You're going to want to code some methods and evaluate them yourself. This isn't my project.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hamed_solar
Associate II
Posted on June 26, 2016 at 10:47

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6dy&d=%2Fa%2F0X0000000bsM%2Ff4Xx0lHLJ0KQ4ojeKxPrLF5ksP6hl3tgWo6vLOoFY6c&asPdf=false
Posted on June 26, 2016 at 17:25

Continuous is where you saturate the ADC, if you want it paced/triggered, you need to turn that off. ie NOT Continuous.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hamed_solar
Associate II
Posted on June 27, 2016 at 23:30

Hi clive1

Thanks for reply. I remove the configuration for trigger ADC. ADC is configured for continuous conversion and I config TIM3 for input capture. Now I want to getting 2 pulses on the channel2 of TIM3 and then two times trigger the TIM3_IRQHandler(). Is my code true? as below code:

void TIM3_ExternalClockMode1()
{
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
TIM_DeInit(TIM3); 
TIM_BaseInitStructure.TIM_Period = 2; 
TIM_BaseInitStructure.TIM_Prescaler = 0; 
TIM_BaseInitStructure.TIM_ClockDivision = 0;
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 
TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_BaseInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
/* Select the TIM3 Input Trigger: TI1FP1 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);// TIM_TS_TI2FP2==>PA7 - TIM_TS_TI1FP1==>PA6
/* Select the slave Mode: Reset Mode */
//TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_External1);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM3, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn ; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{ 
/* Clear TIM3 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
if(CanStartCovert==true)
{
if(CaptureNumber==0 )
{
Current_Pos1=DMA_GetCurrDataCounter(DMA1_Channel1); 
CaptureNumber=1;
}
else
{ 
Current_Pos2=DMA_GetCurrDataCounter(DMA1_Channel1); 
CaptureNumber=0;
CanStartCovert=false;
}
}
}
}
void ADC1_Init()
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 Channel1 Configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC3ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferLenght;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_None; //ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO; //ADC_ExternalTrigConv_T1_CC2;//; ;// ;//;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC3 regular channels configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_13Cycles5); //c2 ==for voltage
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */ 
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

when the frequency of input pulse is below than 5khz it samples only one pulse but with the increasing the frequency it samples more than one pulse. I think there is a delay between the rising edge of the input pulse and time-stamping the DMA transferring. What is you idea? Regards
hamed_solar
Associate II
Posted on June 28, 2016 at 21:09

clive1:''Continuous is where you saturate the ADC, if you want it paced/triggered, you need to turn that off. ie NOT Continuous.''

Can you inform me about what kind of ADC configuration must be choosen?

Continious ADC or Trigger ADC?

I think I must config TIMx for external clock mode 1 that can call IRQHandler  with each rising edge of input pulses.

At the last code that I was sent , I save the position of DMA at each rising edge.I dont know is it correct or not ?!!

Please help me.

Regards

Regards.

Posted on June 28, 2016 at 22:11

So to reiterate, you need to use the ADC either in a CONTINUOUS mode or TRIGGERED mode.

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // Triggered case

The source of the trigger is typically a timer, either the update or channel compare/input. To start/stop the ADC in the triggering mode, the timer would need to be a slave. You should perhaps review the timer modes in the manual and experiment with generating pulse trains in the fashion you want to trigger. You can output timer signals to a pin and review with an oscilloscope. I have my own projects to work on, so can't commit a great deal of time to yours.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..