cancel
Showing results for 
Search instead for 
Did you mean: 

40 Mhz PWM generation on TIM1 PA8

ginnikhanna27
Associate II
Posted on August 28, 2012 at 14:26

Hello!

I have already written the code to produce a 40Mhz clock at the output of TIM1_PWM1. I wanted to confirm is it possible to make a 40Mhz clock or not because according to the datasheet , APB2 can have a maximum frequency of 84 Mhz, but for some reason I can not get a 40 Mhz clock.

Any help will be appreciated

This is my code

/* Compute the prescaler value */

  PrescalerValue = (uint16_t) ((168000000) /  84000000 ) -1;

  uint16_t PreCalPeriod = (84000000 / 40000000) -1;

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = PreCalPeriod ;

  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel1 */

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM_OCInitStructure.TIM_Pulse = (PreCalPeriod * 50) / 100;

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC1Init(TIM1, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

  TIM_ARRPreloadConfig(TIM1, ENABLE);

  /* TIM1 enable counter */

  TIM_Cmd(TIM1, ENABLE);

  TIM_CtrlPWMOutputs(TIM1, ENABLE);

  while (1)

  {}

}

/**

  * @brief  Configure the TIM3 Ouput Channels.

  * @param  None

  * @retval None

  */

void TIM_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* TIM1 clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

  /* GPIOA clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);

  /* GPIOA Configuration: TIM1 CH1 (PA8) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Connect TIM1 pins to AF2 */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);

}

7 REPLIES 7
Posted on August 28, 2012 at 14:41

You need to appreciate that the STM32 only has INTEGER dividers.

The period/prescale work on N-1 numbers

A 50/50 duty uses a N/2 value

For high rates consider using TOGGLE, not PWM

To get 40MHz consider a 160 MHz PLL clock

..

  PrescalerValue = (uint16_t) ((168000000) /  84000000 );

  uint16_t PreCalPeriod = (84000000 / 40000000);

..

  TIM_TimeBaseStructure.TIM_Period = PreCalPeriod - 1 ;

  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue -1;

..

  TIM_OCInitStructure.TIM_Pulse = (PreCalPeriod * 50) / 100;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ginnikhanna27
Associate II
Posted on August 28, 2012 at 14:46

Hi!

Thanks for the reply. But I do not understand when you say TOGGLE. Is this some mode, or through the GPIO I have to do something ?

I tried with what you told, but it does not give any output!

Posted on August 28, 2012 at 16:07

// STM32 PWM 42 MHz (TIM1 CH1 PA.08) STM32F4 Discovery - sourcer32@gmail.com
#include ''stm32f4_discovery.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM1 pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
}
/**************************************************************************************/
void TIM1_Configuration(void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
uint16_t Period;
Period = (SystemCoreClock / 42000000);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0; // Dump 1X clock into timer
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Enable TIM1 Preload register on ARR */
TIM_ARRPreloadConfig(TIM1, ENABLE);
/* TIM PWM1 Mode configuration */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = Period / 2; // 50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/* Output Compare PWM1 Mode configuration: Channel1 PA.08 */
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
TIM1_Configuration();
while(1); // Don't want to exit
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**************************************************************************************/

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ginnikhanna27
Associate II
Posted on August 28, 2012 at 17:12

Hi!

Thanks a lot!! But, I already worked on my code, and it was working 🙂

linas2
Associate II
Posted on August 31, 2012 at 15:44

i have 100Msps adc, and i don't want to use FPGA to supply encoder signal to ADC ( LVDS or just two square wave 180 angle difference)

can i use PWM to generate ENC signal fro ADC ?

and if yes, what is the fastest way to read it ?

I have detector made from 128 photo-diodes, and readout frequency is 8MHz (charge is pushed with serial interface to opamp)

i need to be able to read adc and make that point DFT, so my program use as much cpu time as possible to get better overall time.

i have two ideas, use MCO or PWM as ENC signal , chech ADC CLK output polarity, and when i have rising or falling edge read data, and then make DFT.

or drive ENC with 80MHz so i don't need to check ADC clk for data, and read then i push charge since adc has 7 conversion latency, so i have to be able to make >7 conversions in one 8MHz period

i tested STM32F4, it can do single point DFT in less than 14ns (250MHz core clk)

or maybe some one have better idea? (maybe use interruption to read data, bus at the same time i have to generate signal for photo-diode)

http://www.mouser.com/catalog/specsheets/TSL1401CL.pdf << Detector

http://cds.linear.com/docs/Datasheet/2217f.pdf                       <<ADC

Posted on August 31, 2012 at 16:32

Well you could get 80 MHz out of MCO if you clock the F4 at 160 MHz (or 240 MHz div 3 if it works effectively at those speeds), you could get a timer to generate 8 MHz, of use HSE out of the secondary MCO if you use an 8 or 16 MHz external crystal.

You'd probably need to use DMA via the FSMC to get data from an external ADC. Generating 56 MHz, and getting the bus to work effectively that's another matter. Why is an FPGA unappealing?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
linas2
Associate II
Posted on August 31, 2012 at 19:22

well, i have altera usb blaster so i can use only cyclones.

But they are expensive (i even can't get in my country, i have to order them from uk) and i need low pin count and cyclone with pll, also configuration flash is same cost as stm32f4 itself, and fpga program is too big for stm32F4 flash so i can't config fpga from stm32f4.

you know, new device will bring lot of problems and high cost to design. and i still have problems with lvds output on fpga and so on