- 根据引用中的代码,可以看出`#define DEVICE_OSCSRC_FREQ 20000000U`表示设备的参考时钟频率为20MHz。这个值是在代码中预定义的,如果实际使用的设备参考时钟频率不同,需要相应地修改代码中的值。另外,根据引用中的说明,这个参考时钟是由OSCCLK提供的,而OSCCLK的来源可以是内部时钟源1(INTOSC1)、内部时钟源2(INTOSC2)或外部时钟(XTAL),具体的选择由寄存器OSCCLKSRCSEL来控制。
- #define DEVICE_SETCLOCK_CFG (SYSCTL_OSCSRC_XTAL | SYSCTL_IMULT(10) | \
SYSCTL_FMULT_NONE | SYSCTL_SYSDIV(2) | \
SYSCTL_PLL_ENABLE) -
这是一个宏定义,它定义了一个名为DEVICE_SETCLOCK_CFG的常量,其值为一个按位或运算的结果。具体来说,这个常量的值由以下几个部分组成:
- SYSCTL_OSCSRC_XTAL:使用外部晶体振荡器作为系统时钟源。
- SYSCTL_IMULT(10):使用10作为内部时钟倍频系数。
- SYSCTL_FMULT_NONE:不使用分数倍频。
- SYSCTL_SYSDIV(2):使用2作为系统时钟分频系数。
- SYSCTL_PLL_ENABLE:启用PLL(锁相环)。因此,这个宏定义的作用是设置设备的时钟配置,使其使用外部晶体振荡器作为时钟源,使用10作为内部时钟倍频系数,不使用分数倍频,使用2作为系统时钟分频系数,并启用PLL。
-
uint32_t
SysCtl_getClock(uint32_t clockInHz)
{
uint32_t temp;
uint32_t oscSource;
uint32_t clockOut;//
// Don't proceed if an MCD failure is detected.
//
if(SysCtl_isMCDClockFailureDetected())
{
//
// OSCCLKSRC2 failure detected. Returning the INTOSC1 rate. You need
// to handle the MCD and clear the failure.
//
clockOut = SYSCTL_DEFAULT_OSC_FREQ;
}
else
{
//
// If one of the internal oscillators is being used, start from the
// known default frequency. Otherwise, use clockInHz parameter.
//
oscSource = HWREG(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
(uint32_t)SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M;if((oscSource == (SYSCTL_OSCSRC_OSC2 >> SYSCTL_OSCSRC_S)) ||
(oscSource == (SYSCTL_OSCSRC_OSC1 >> SYSCTL_OSCSRC_S)))
{
clockOut = SYSCTL_DEFAULT_OSC_FREQ;
}
else
{
clockOut = clockInHz;
}//
// If the PLL is enabled calculate its effect on the clock
//
if((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &
(SYSCTL_SYSPLLCTL1_PLLEN | SYSCTL_SYSPLLCTL1_PLLCLKEN)) == 3U)
{
//
// Calculate portion from fractional multiplier
//
temp = (clockInHz * ((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
SYSCTL_SYSPLLMULT_FMULT_M) >>
SYSCTL_SYSPLLMULT_FMULT_S)) / 4U;//
// Calculate integer multiplier and fixed divide by 2
//
clockOut = clockOut * ((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
SYSCTL_SYSPLLMULT_IMULT_M) >>
SYSCTL_SYSPLLMULT_IMULT_S);//
// Add in fractional portion
//
clockOut += temp;//
// Calculate PLL divider
//
temp = ((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
SYSCTL_SYSPLLMULT_ODIV_M) >>
SYSCTL_SYSPLLMULT_ODIV_S) + 1U;//
// Divide dividers
//
if(temp != 0U)
{
clockOut /= temp;
}
}if((HWREG(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) != 0U)
{
clockOut /= (2U * (HWREG(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M));
}
}return(clockOut);
} -
这是一个名为SysCtl_getClock的函数,它接受一个参数clockInHz,表示时钟频率。该函数的作用是获取系统时钟的频率。函数首先检查是否检测到MCD故障,如果检测到,则返回默认的OSC频率。否则,如果使用内部振荡器之一,则从已知的默认频率开始。否则,使用传入的clockInHz参数。如果启用PLL,则计算其对时钟的影响。最后,如果设置了PLLSYSCLKDIV,则将时钟频率除以2 * PLLSYSCLKDIV。
-
bool
SysCtl_setClock(uint32_t config)
{
uint16_t divSel;
uint32_t pllMult;
uint32_t retries, oscSource, pllLockStatus;
uint32_t timeout;
bool status = false;
uint32_t mult;//
// Check the arguments.
//
ASSERT((config & SYSCTL_OSCSRC_M) <= SYSCTL_OSCSRC_M);//
// Don't proceed to the PLL initialization if an MCD failure is detected.
//
if(SysCtl_isMCDClockFailureDetected())
{
//
// OSCCLKSRC2 failure detected. Returning false. You'll need to clear
// the MCD error.
//
status = false;
}
else
{
//
// Configure oscillator source
//
oscSource = config & SYSCTL_OSCSRC_M;
SysCtl_selectOscSource(oscSource);//
// Bypass PLL
//
EALLOW;
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &=
~SYSCTL_SYSPLLCTL1_PLLCLKEN;
EDIS;//
// Delay of at least 60 OSCCLK cycles required post PLL bypass
//
SysCtl_delay(11U);//
// Get the PLL multiplier settings from config
//
pllMult = ((config & SYSCTL_IMULT_M) << SYSCTL_SYSPLLMULT_IMULT_S);pllMult |= (((config & SYSCTL_FMULT_M) >> SYSCTL_FMULT_S) <<
SYSCTL_SYSPLLMULT_FMULT_S);pllMult |= (((config & SYSCTL_ODIV_M) >> SYSCTL_ODIV_S) <<
SYSCTL_SYSPLLMULT_ODIV_S);//
// Get the PLL multipliers currently programmed
//
mult = ((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
SYSCTL_SYSPLLMULT_IMULT_M) >> SYSCTL_SYSPLLMULT_IMULT_S);mult |= (HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
SYSCTL_SYSPLLMULT_FMULT_M);mult |= (HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
SYSCTL_SYSPLLMULT_ODIV_M);//
// Lock PLL only if the multipliers need update
//
if(mult != pllMult)
{
//
// Configure PLL if enabled
//
if((config & SYSCTL_PLL_ENABLE) == SYSCTL_PLL_ENABLE)
{
//
// Set dividers to /1
//
EALLOW;
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) = 0U;
EDIS;//
// Loop to retry locking the PLL should the DCC module
// indicate that it was not successful.
//
for(retries = 0U; (retries < SYSCTL_PLL_RETRIES); retries++)
{
//
// Turn off PLL
//
EALLOW;
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &=
~SYSCTL_SYSPLLCTL1_PLLEN;SysCtl_delay(3U);
//
// Write multiplier, which automatically turns on the PLL
//
HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) = pllMult;//
// Wait for the SYSPLL lock counter or a timeout
//
timeout = SYSCTL_PLLLOCK_TIMEOUT;
pllLockStatus = HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLSTS) &
SYSCTL_SYSPLLSTS_LOCKS;while((pllLockStatus != 1U) && (timeout != 0U))
{
pllLockStatus = HWREGH(CLKCFG_BASE +
SYSCTL_O_SYSPLLSTS) &
SYSCTL_SYSPLLSTS_LOCKS;
timeout--;
}
EDIS;//
// Check PLL Frequency using DCC
//
status = SysCtl_isPLLValid(oscSource,
(config &
(SYSCTL_IMULT_M |
SYSCTL_FMULT_M |
SYSCTL_ODIV_M)));//
// Check DCC Status, if no error break the loop
//
if(status)
{
break;
}
}
}
else
{
status = true;
}
}
else
{
status = true;
}
//
// If PLL locked successfully, configure the dividers
//
if(status)
{
//
// Set divider to produce slower output frequency to limit current
// increase.
//
divSel = (uint16_t)(config & SYSCTL_SYSDIV_M) >> SYSCTL_SYSDIV_S;EALLOW;
if(divSel != (126U / 2U))
{
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) =
(HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
~(uint16_t)SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) |
(divSel + 1U);
}
else
{
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) =
(HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
~(uint16_t)SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) | divSel;
}EDIS;
//
// Enable PLLSYSCLK is fed from system PLL clock
//
EALLOW;
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) |=
SYSCTL_SYSPLLCTL1_PLLCLKEN;
EDIS;//
// ~200 PLLSYSCLK delay to allow voltage regulator to stabilize
// prior to increasing entire system clock frequency.
//
SysCtl_delay(40U);//
// Set the divider to user value
//
EALLOW;
HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) =
(HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
~SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) | divSel;
EDIS;
}
}return(status);
} -
bool是一种布尔类型,只有两个值:True和False。在这个函数中,bool类型的变量status被用来表示函数是否成功执行。如果函数成功执行,则status为True,否则为False。
该函数是一个用于设置系统时钟的函数。它首先检查传入的参数是否合法,然后配置振荡器源并绕过PLL。接下来,它获取PLL乘数设置并检查当前程序的PLL乘数。如果需要更新乘数,则锁定PLL并写入新的乘数。如果PLL成功锁定,则配置分频器以产生较慢的输出频率,以限制电流增加。最后,它将PLLSYSCLK使能,并设置分频器以用户值。
device.h
最新推荐文章于 2024-07-18 18:07:02 发布