2013-06-30 08:27 AM
I'm using TIM1 to generate a PWM signal of period 1 sec and a varying pulse duty.
This pulse undergoes some signal conditioning and then entered to the ADC, worth to mention that nothing happens to the signal's period nor the pulse width.How i make the ADC reads only this value? i want something like triggering the ADC to start the conversion. #adc #stm32 #timers2013-06-30 08:29 AM
Tried to use this
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;But i'm sure there's something i already miss and it's not that simple!2013-06-30 09:55 AM
Pacing the ADC with a timer is a pretty straight forward task. Here's an example on the STM32F4
[DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/stm32f207%20ADC%2BTIMER%2BDMA%20%20Poor%20Peripheral%20Library%20Examples&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=223]https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2Fstm32f207%20ADC%2BTIMER%2BDMA%20%20Poor%20Peripheral%20Library%20Examples&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=2232013-06-30 10:01 AM
An F1 example half way down.
2013-07-01 09:19 AM
Thanks a lot for your reply.
I'm not using the DMA so i'm going to cross it out. Here's my code, it didn't anyway!void Initializations(void)
{
/* CLocks and GPIOs configurations */
HW_Init();
/* ADC configuration */
ADC_Config();
/* Timers configurations */
Timers_Config();
/* NVIC configuration */
NVIC_Config();
}
void ADC_Config(void)
{
/* Initialize the ADC1 according to the ADC_InitStructure members */
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE; /* Single Channel */
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* Configures ADC1 (ADC) Channel3 as: second converted channel with a 7.5 cycles sample time */
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_239Cycles5);
/*Enable the start of conversion for ADC1 through external trigger */
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
/* Enable ADC1 EOC interrupt */
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); /* EOC = End Of Conversion */
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Reset the ADC1 Calibration registers */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* It is recommended to start calibration for the ADC after each power up */
/* Start the ADC1 Calibration */
ADC_StartCalibration(ADC1);
/* Get the ADC1 calibration status */
while(ADC_GetCalibrationStatus(ADC1));
/* Start by software the ADC1 Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void Timers_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructInit;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Selects the internal clock for TIM1 */
TIM_InternalClockConfig(TIM1);
TIM_TimeBaseStructInit.TIM_Period = Pulse_Period;
TIM_TimeBaseStructInit.TIM_Prescaler = Pulse_Prescaler;
TIM_TimeBaseStructInit.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructInit.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructInit.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructInit);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = Pulse_Duty;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
/* Enables the TIM1 Preload on CC1 Register */
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //OCxPE bit in the TIMx_CCMRx register
/* Enables the TIM1 Preload on ARR Register */
TIM_ARRPreloadConfig(TIM1, ENABLE); //ARPE bit in the TIMx_CR1 register
/* Sets the TIM1 new Autoreload value ARR */
TIM_SetAutoreload(TIM1, Pulse_Period); //Autoreload register sets the period
/* Sets the new TIM1 Capture Compare 1 value */
TIM_SetCompare1(TIM1, Pulse_Duty); //Capture Compare register sets the duty cycle
/* Selects the OC1 event as TRGO for TIM1 */
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC1);
/* Enables the TIM1 counter */
TIM_Cmd(TIM1, ENABLE);
/* Enables the TIM1 peripheral Main Outputs */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
void NVIC_Config(void)
{
/* The following example illustrates how to initialize a NVIC_InitTypeDef structure */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
/* All needed initializations */
Initializations();
while(1);
}
void __attribute__ ((interrupt)) __cs3_isr_adc1_2 (void)
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
ConvertedValue = ADC_GetConversionValue(ADC1);
}
2013-07-01 09:21 AM
Why do i see it's not working? Because the Convertedvalue variable reads zero for the most of the time. So it doesn't really fire at the start of the pulse!
2013-07-01 11:09 AM
It's not sufficiently complete for me to spend time reviewing.
I'll assume you modified ADC1_2_IRQHandler() in the vector table, and have the clocks enabled.2013-07-03 04:56 AM
I used that handler structure as to cope with the interrupt vector comes already with the Codesourcery IDE.
void HW_Init(void)
{
/* System Clocks configuration */
RCC_Config();
/* GPIO configuration */
IO_Config();
}
void RCC_Config(void)
{
FlagStatus HSIStatus;
/* Enable Internal High Speed oscillator */
RCC_HSICmd(ENABLE);
HSIStatus = RCC_GetFlagStatus(RCC_FLAG_HSIRDY);
while(!HSIStatus)
{}
/* Set PLL clock output to 24MHz using HSI (8MHz) as entry clock */
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_6);
/* Select the PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
volatile u8 i;
for(i=0; i<=10; ++i)
{;}
/* Enable the PLL */
RCC_PLLCmd(ENABLE);
/* Configure HCLK such as HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* Configure PCLK1 such as PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div1);
/* Configure PCLK2 such as PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* Configure ADCCLK such as ADCCLK = PCLK2/2 */
RCC_ADCCLKConfig(RCC_PCLK2_Div2);
/* Enable peripheral clocks */
/* Enable GPIOA, TIM1, ADC1, AFIO clocks */
RCC_APB2PeriphClockCmd((RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO), ENABLE);
}
void IO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_3);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //Analog Input
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_8);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Push-Pull Output Alternate-Function
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
2013-07-03 08:41 AM
CodeSourcery must be using a hideously old firmware library (v2.x.x prior to CMSIS)
I really don't like how you're enabling and switching to the PLL The following has a more reasonable flow, and checks for the PLL lock before switching to it, and waits for the switch over to occur.void RCC_Config(void)
{
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK/1 */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/1 */
RCC_PCLK1Config(RCC_HCLK_Div1);
/* ADCCLK = PCLK2/2 */
RCC_ADCCLKConfig(RCC_PCLK2_Div2);
/* PLLCLK = 8MHz / 2 * 6 = 24 MHz */
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_6);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08);
/* Enable peripheral clocks --------------------------------------------------*/
/* Enable TIM1, ADC1, AFIO and GPIOA clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_ADC1 |
RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
}
2013-07-03 09:15 AM
Would it be worth mentioning that the clock is working just fine? I tested the MCO pin and the 24MHz is out.
And why did you omit the part where the HSI should be enabled?Thidly: i tried to use the while loop to check for the lock of the PLL, but it doesn't come out, that's why i used the for loop instead.Thanks so much for your help!