Part Number:TMS320F28027
Hello forum,
I am trying to set up a TMS320F28027 C2000 microcontroller to act as an RTC for use in other functions on the chip. I have a crystal hooked up, and set up Timer2 to use the crystal. It seems to work, but I am not getting the accuracy that I am looking for.
It uses a 12 Mhz crystal that is supposed to be 15ppm, and I calculated the load capacitors to be 6pF using the formula C = 2(CL - Cstray), assuming 5pF Cstray, CL is 8pF.
The timer has a 11999 prescaler, which means the timer should count every 1ms * period, which means it should trigger every second, which just adds 1 to a 32 bit number. It seems that after 20 hours, it is 20 seconds out, which is 0.0556% or 556ppm, not even close to the expected 15ppm!
This is the first time I have implemented a crystal in my design, so I'm not 100% sure I am doing it right, or really what accuracy I should be able to expect. I should also mention that it is powered off of a 3.3V buck regulator, and the jtag debugger is attached and connected. I'm not sure if this changes anything, like does the debugger supply a clock that overrides any crystal?
Anyways, does anyone have any ideas or advice as to why I'm not getting the accuracy I need, or is my expectation unreal, and I should just get a dedicated clock chip? I would prefer to not have a separate chip if at all possible.
The crystal: https://www.digikey.ca/product-detail/en/avx-corp-kyocera-corp/CX3225SB12000D0GZJC1/1253-1696-1-ND/5995243
The Capacitors: https://www.digikey.ca/product-detail/en/tdk-corporation/C1608C0G1H060D080AA/445-5037-1-ND/2093652
The (relevant) board layout:
The Code:
uint32_t clock_period = 1000; //in ms uint32_t clock_time_s = 0; //in s uint32_t clock_time_s_offset = 0; void initClockTimer() { myTimer2 = TIMER_init((void *)TIMER2_BASE_ADDR, (size_t)sizeof(TIMER_Obj)); EALLOW; PIE_registerSystemIntHandler(myPie, PIE_SystemInterrupts_TINT2, (intVec_t) &clockInterrupt); EDIS; TIMER_stop(myTimer2); CLK_setTimer2Src(myClk, CLK_Timer2Src_ExtOsc); TIMER_setPeriod(myTimer2, clock_period); TIMER_setPreScaler(myTimer2, 11999); TIMER_reload(myTimer2); TIMER_setEmulationMode(myTimer2, TIMER_EmulationMode_RunFree); TIMER_enableInt(myTimer2); TIMER_start(myTimer2); CPU_enableInt(myCpu, CPU_IntNumber_14); Clock_setPosixTime(1447459200); } void Clock_setPosixTime(uint32_t t) { clock_time_s_offset = t - clock_time_s; } #pragma CODE_SECTION(clockInterrupt, "ramfuncs"); __interrupt void clockInterrupt(void) { GPIO_toggle(myGpio, GPIO_Number_0); clock_time_s++; }