cancel
Showing results for 
Search instead for 
Did you mean: 

Maximum Output Speed

knabbers
Associate II
Posted on January 07, 2012 at 06:09

Hi,

I am curious as to what the '50MHz' output speed of the GPIO ports refers to (with correct configuration bits set). Is it the maximum frequency of a square wave output, or does it have something to do with the rise/fall times?

The camera module I am using works with an STM32-driven 5MHz square wave, but not a 12MHz one. The 5MHz square wave shows to be exactly 1.65V (3.3V/2), however, the 12MHz waveform shows 0.3V-0.5V, which suggests that the signal is never reaching 3.3V - the rise time is too long. Unfortunately I do not have an oscilloscope so can't see what's going on.

It seems strange because other people seem to have managed something akin what I am trying to do.

The following are quotes from 

http://forums.leaflabs.com/topic.php?id=774

:

- ''

That 50MHz refers to the speed that the external electrical signal driven by a GPIO pin changes from low to high, or vice versa; the rise-time. This configures the rate that the drive transistors work at.''

- ''

The best I have achieved is 18MHz to toggle a pin repeatedly with some odd-looking code, but 12MHz was okay.''

- ''If all that is needed is a square wave at a fixed frequency on a pin, it would be almost as easy to program one of the timers ... 

When I loaded data too, it came down to about 12MHz.''

If anybody has any insight to offer, I'm all ears!

#maximum-output-speed
6 REPLIES 6
Posted on January 07, 2012 at 14:59

It controls the slew rate of the pin, how hard it drives high/low. The amount of external loading will impact how effectively this occurs. If you are trying to drive a high load, consider using an external buffer.

Using code to drive GPIOs at high frequencies is a fools errand. Use a timer to generate fast/accurate frequencies, or peripherals like SPI, synchronous USART for clock/data type applications. Think creatively, and avoid bit level processing in software, try to do 8 or 16-bit at a time to achieve some decimation.

With high timer rates you definitely don't want them generating interrupts as they will assuredly saturate the processor, you could experiment, I have in the past, but off the top of my head I'd say below 100 KHz.

Also think creatively about the frequency you run the processor at. You can use different crystals and PLL settings that hit magic frequencies, and maybe run below the 72 MHz ceiling, but will mesh better with the rates the external hardware works optimally with. The STM32 is not good with fractional settings. For instance if you need a clean 256 KHz, you'll need to run at 32 or 64 MHz.

Consider using the MCO pin for higher frequencies, should be capable of 36 MHz, perhaps 48-50 MHz if you under clock. Timer pins, perhaps 18 MHz, I'm sure they'd go higher, but will grind and be generally inflexible. At these rates I'd be using different hardware, with finer granularity. I'd need to stick a scope on the board to give you a high confidence number.

Also consider F2 or F4 series parts, or external clocks.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
knabbers
Associate II
Posted on January 07, 2012 at 16:25

Thanks for the response;

I am using a timer (in output compare mode) to create a waveform. Also, I am not using any interrupts. I simply need to generate a square wave of 12Mhz. The same thing happens when the pin (on an STM32-H103 dev. board) is not connected to anything - could the dev. board pin header be limiting the output frequency to 5Mhz? I have tried using the MCO pin with the same results. Other than this, it seems as though an external buffer might be the only way to go.

Posted on January 07, 2012 at 17:10

I don't have a part/scope to hand right now, but I'm pretty sure I've gotten at least 8 MHz.

I don't think a header would be a problem, I guess I'd start by looking at the bulk capacitance on the 3V supply.

Also provide the timer initialization code, at high rates you want a zero prescaler (ie DIV 1)
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
knabbers
Associate II
Posted on January 07, 2012 at 17:38

Thanks for your input, I'll be able to get my hands on a scope in a few days so I guess I'll just wait until then. The prescaler value is left at default - zero, but some strange things are happening.

pmoore
Associate II
Posted on January 10, 2012 at 19:57

James:

As I recall, you stated the output signal voltage dropped at higher frequencies, so it is very possible that you have too much capacitive loading on the output pin (a scope or logic probe can easily be too much capacitive load). 

Using a CMOS buffer on the output may be required to drive your target load at 12MHz.

You might have stated this already, but be sure the GPIO pin configuration is in push-pull mode and not open drain with a pull-up.

It is also possible that you don't have enough low ESR capacitance on the power supply pins for the processor.  You might want to add an additional 1uf to 4.7uF quality (X7R or better ceramic) capacitor to each power pin.

reffahcs
Associate II
Posted on January 11, 2012 at 03:42

Not sure if you got it working yet, but here's my code for exactly the same problem. I had to generate a 12 MHz clock using TIM3 via GPIO. I'm using a MCBSTM32C dev board.

Like the previous poster mentioned, check the config of the GPIO pin. In my case, for PC6, besides remapping the TIM3 pins to use PC6, I had to configure the GPIO for PC6 to use the alternate function as well.

Regards,

Tim

int main(void)

{

RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;

RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;

GPIOC->CRL = 0x0b000000;                                                            // Enable pin 6 @ 50mhz

AFIO->MAPR = AFIO_MAPR_TIM3_REMAP;                                        // Remap TIM3 pins to PC6, 7, 8 and 9

TIM3->PSC = 2;                                                                                // Set prescaler to 2 (PSC + 1 = 3; SYSCLK(72MHz) / 3 = 12 MHz)

TIM3->ARR = 1;                                                                                 // Auto reload value

TIM3->CCR1 = 1;                                                                                // Start PWM duty for channel 1

TIM3->CCMR1 = TIM_CCMR1_OC1M;

TIM3->CCER = TIM_CCER_CC1E;                                                        // Enable compare on channel 1

TIM3->CR1  = TIM_CR1_CEN;                                                            // Start timer

//TIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)

//NVIC_EnableIRQ(TIM3_IRQn); // Enable interrupt from TIM3 (NVIC level)

while (1) {}

}