# How to generate high frequency clock with high stability from a microcontroller?

I am using TivaC launchpad TM4C123G microcontroller, to generate a clock of 40 MHZ but I tested it on the oscilloscope and it doesn't look like a square wave it's more like a sinusoidal here is a screenshot:

and here is my code:

#include <lm4f120h5qr.h>
#include <stdbool.h>
#include <stdint.h>
#include "driverlib/sysctl.c"
#include "driverlib/pin_map.h"

void SYS_CLOCK(){  SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); }
// Microcontroller Frequency 80MHZ

void CLK1_SETUP(unsigned long Period){
SYSCTL->RCGCWTIMER |= (0x1<<0);
WTIMER0->CTL &= ~(1<<8);
WTIMER0->CFG = 0x00000004;
WTIMER0->TBMR |= (0xA<<0);
WTIMER0->TBILR = Period;
WTIMER0->TBMATCHR =Period/2;
WTIMER0->CTL |= (1<<8);

SYSCTL->RCGCGPIO |= (1<<2);
GPIOC->DIR |= (0x1<<5);
GPIOC->DEN |= (0x1<<5);
GPIOC->PUR |= (0x1<<5);
GPIOC->AFSEL |= (0x1<<5);
GPIOC->AMSEL &= ~(0x1<<5);
GPIOC->PCTL |= 0X00700000;
}

void CLK2_SETUP(unsigned long Period){
SYSCTL->RCGCWTIMER |= (0x1<<1);
WTIMER1->CTL &= ~(1<<8);
WTIMER1->CFG = 0x00000004;
WTIMER1->TBMR |= (0xA<<0);
WTIMER1->TBILR = Period;
WTIMER1->TBMATCHR =Period/2;
WTIMER1->CTL |= (1<<8);

GPIOC->DIR |= (0x1<<7);
GPIOC->DEN |= (0x1<<7);
GPIOC->PUR |= (0x1<<7);
GPIOC->AFSEL |= (0x1<<7);
GPIOC->AMSEL &= ~(0x1<<7);
GPIOC->PCTL |= 0X70000000;
}

void main()
{
SYS_CLOCK();
CLK1_SETUP(2); //40MHZ~25nsec~2
CLK2_SETUP(190);//421KHZ~2.375usec~190
}


on the other side I generated another clock with the same code but with a frequency of 421 KHZ and it looks correct:

any suggestions on how to make the 40 MHZ more stable and accurate ?

-
Compensate your probe, and use a shorter ground lead for starters. – Matt Young Jan 11 at 2:57
@MattYoung ok thanks I will try this. – Abdelrahman Tarief Jan 11 at 3:13
A proper termination will help too. – Austin Jan 11 at 3:59

Your GPIO pins aren't able to change between low and high signal fast enough.

At 40 Mhz the period of a single cycle is 25 ns. Here is the definition of the slew rate of GPIO pins from document http://www.ti.com/lit/ds/spms376e/spms376e.pdf:

For a single cycle you need at one raising and one falling edge.

As seen in the chart above in the best case that'll add up to 16.7ns (8-mA drive with slew rate control disabled). So in this case your pins will spend most of the time of the period slewing the signal up or down. And that's more or less what we're seeing on your oscilloscope picture as well.

-
so what I understand, this is the best my microcontroller can do and there is no solution for this problem ? – Abdelrahman Tarief Jan 11 at 4:11
if you really need the output to be a square wave, you can put a really fast comparator at the output to shape the pulse back to a square wave. On the other hand, why do you need the signal to be a square wave at the first place? If you want to clock something it may just work fine with the distorted signal. – Nils Pipenbrinck Jan 11 at 4:25
@AbdelrahmanTarief Oh, an alternative way to get your signal would be to generate the clock using a PLL like the Si5351 controlled via I²C. For example the Si5351 goes up to 200Mhz and has a slew rate of 1.5ns worst case. It's not even expensive. – Nils Pipenbrinck Jan 11 at 4:34
Generate a slower frequency and multiply it up with an external PLL, or use some sort of crystal oscillator that has nothing to do with the microcontroller, and gate it if you need to. – Scott Seidman Jan 11 at 14:05

First drop the frequency to 10MHz to help see what's going on. You'll see a flattish portion between the rising-edge spike and the falling edge.

Then improve the scope probe, by compensation (very small effect at these frequencies - the second image shows a well compensated probe) and improved earthing (can make a huge difference ...)

Then try series termination (S-term). A resistor of 27-100 ohms (start with 56) can square up the leading edge nicely - too high and it'll be rounded. The S-term should be as close to the I/O pin as possible, but I expect attaching it to the Launchpad pin will be good enough. You can also experiment with the different drive strengths and slew rate control - the best solution will depend on the external wiring, but an S-termination is a useful addition to some fast signals.

Finally, restore the clock to 40MHz and see the improvement. (It may be worth adding more images to the question).

-