MSP430F5438A. Измерение отношения SMCLK vs ACLK с помощью TimerB0 для контроля и подстройки DCO. Тормозят что-то лыжи. Может кто идею подкинет? Обычная процедура измерения. Таймер тактируется от SMCLK, который соответственно от DCOCLKDIV=DCOCLK/2. На вход CCI6B внутренне подключан ACLK=XT1CLK. Режим синхронного захвата по фронту. После вычислений частота SMCLK иногда отличается вверх/вниз на 32768. Где косяк, понять не могу :( Может как-то двойная буферизация регистров CCR в TimerB влияет? Нафига они в TI вообще подвели ACLK именно к таймеру B? Во всех других сериях он к TimerA подключался, у которого двойной буферизации CCRx нету.
#pragma inline = forced
static void h_TimerB_prep (void)
//Функция подготовки таймера B0 к измерению SMCLK vs ACLK
//Возвращает: ничего
{ TB0CTL = TBCLGRP_0 | //инд.загрузка CCR
CNTL_0 | //16-и битный режим
TBSSEL_2 | ID_0 | //TB0CLK=SMCK/1
TBCLR;
TB0EX0 = 0x00; //TB0CLK=CLK/1
TB0CCTL0 = 0x00; //
TB0CCTL6 = CM_2 | //захват по заднему фронту
CCIS_1 | //CCI6B=ACLK
SCS | //синхронный захват
CLLD_0 | //захват с прямой записью в CCR6
CAP; //режим захвата
TB0CTL |= MC_2; //запуск таймера в режиме Continous
TB0CCTL6 &= ~CCIFG;
}
//-----------------------------------------------------------------------------
#pragma inline=forced
static uint16_t h_TimerB_SMCk()
//Функция измерения SMCLK относительно одного периода ACLK
//Возвращает: uint16_t - значение SMCLK/ACLK
{ uint16_t stp1, stp2;
TB0CCTL6 &= ~CCIFG;
while ((TB0CCTL6 & CCIFG) == 0);//ждем первого фронта
stp1 = TB0CCR6;
TB0CCTL6 &= ~CCIFG;
while ((TB0CCTL6 & CCIFG) == 0);//ждем второго фронта
stp2 = TB0CCR6;
return (stp2 - stp1);
}
Тут измерение
__bis_SR_register(SCG0); // Выключить FLL
h_TimerB_prep();
tmp = h_TimerB_SMCk();
h_TimerB_stop();
freq = (uint32_t)tmp * h_sysClkprm.aclk;
tmp типа uint16_t
freq и h_sysClkprm.aclk типа uint32_t