Как генерировать высокочастотные часы с высокой стабильностью из микроконтроллера?

Я использую микроконтроллер TivaC launchpad TM4C123G для генерации тактовой частоты 40 МГц, но я проверил ее на осциллографе, и она не похожа на прямоугольную, а скорее на синусоидальную, вот скриншот:

введите описание изображения здесь

и вот мой код:

#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
 ADC_SETUP(); 
 }

с другой стороны я сгенерировал другие часы с тем же кодом, но с частотой 421 кГц, и это выглядит правильно:

введите описание изображения здесь

любые предложения о том, как сделать 40 МГц более стабильным и точным?

Компенсируйте свой пробник и для начала используйте более короткий заземляющий провод.
Правильное завершение также поможет.

Ответы (2)

Ваши контакты GPIO не могут достаточно быстро переключаться между низким и высоким уровнем сигнала.

На частоте 40 МГц период одного цикла составляет 25 нс. Вот определение скорости нарастания выводов GPIO из документа http://www.ti.com/lit/ds/spms376e/spms376e.pdf :

введите описание изображения здесь

Для одного цикла вам понадобится один нарастающий и один спадающий фронт.

Как видно из диаграммы выше, в лучшем случае это составит 16,7 нс (привод 8 мА с отключенным контролем скорости нарастания). Таким образом, в этом случае ваши выводы будут тратить большую часть времени на поворот сигнала вверх или вниз. И это более или менее то, что мы видим на вашей картинке осциллографа.

Я так понимаю, это лучшее, что может сделать мой микроконтроллер, и решения этой проблемы нет?
если вам действительно нужно, чтобы на выходе была прямоугольная волна, вы можете поставить на выходе очень быстрый компаратор, чтобы преобразовать импульс обратно в прямоугольную волну. С другой стороны, зачем вообще нужен прямоугольный сигнал? Если вы хотите синхронизировать что-то, это может нормально работать с искаженным сигналом.
@AbdelrahmanTarief О, альтернативным способом получения вашего сигнала было бы генерирование часов с использованием PLL, такого как Si5351, управляемого через I²C. Например, Si5351 работает на частоте до 200 МГц и имеет скорость нарастания 1,5 нс в худшем случае. Это даже не дорого.
Сгенерируйте более медленную частоту и умножьте ее с помощью внешнего PLL или используйте какой-нибудь кварцевый генератор, который не имеет ничего общего с микроконтроллером, и стробируйте его, если вам нужно.

Сначала понизьте частоту до 10 МГц, чтобы увидеть, что происходит. Вы увидите плоскую часть между всплеском переднего края и задним краем.

Затем улучшите зонд осциллографа с помощью компенсации (очень небольшой эффект на этих частотах - второе изображение показывает хорошо компенсированный зонд) и улучшенного заземления (может иметь огромное значение ...)

Затем попробуйте прекращение серии (S-термин). Резистор 27-100 Ом (начните с 56) может красиво выровнять передний фронт - слишком высокий, и он будет округлен. Термин S должен быть как можно ближе к контакту ввода-вывода, но я ожидаю, что его подключение к контакту Launchpad будет достаточно хорошим. Вы также можете поэкспериментировать с различной силой возбуждения и контролем скорости нарастания — лучшее решение будет зависеть от внешней проводки, но S-образное окончание — полезное дополнение к некоторым быстрым сигналам.

Наконец, восстановите тактовую частоту до 40 МГц и посмотрите на улучшение. (Возможно, стоит добавить больше изображений к вопросу).