device.h

  1. 根据引用中的代码,可以看出`#define DEVICE_OSCSRC_FREQ 20000000U`表示设备的参考时钟频率为20MHz。这个值是在代码中预定义的,如果实际使用的设备参考时钟频率不同,需要相应地修改代码中的值。另外,根据引用中的说明,这个参考时钟是由OSCCLK提供的,而OSCCLK的来源可以是内部时钟源1(INTOSC1)、内部时钟源2(INTOSC2)或外部时钟(XTAL),具体的选择由寄存器OSCCLKSRCSEL来控制。 
  2. #define DEVICE_SETCLOCK_CFG         (SYSCTL_OSCSRC_XTAL | SYSCTL_IMULT(10) |  \
                                         SYSCTL_FMULT_NONE | SYSCTL_SYSDIV(2) |   \
                                         SYSCTL_PLL_ENABLE)
  3. 这是一个宏定义,它定义了一个名为DEVICE_SETCLOCK_CFG的常量,其值为一个按位或运算的结果。具体来说,这个常量的值由以下几个部分组成:
    - SYSCTL_OSCSRC_XTAL:使用外部晶体振荡器作为系统时钟源。
    - SYSCTL_IMULT(10):使用10作为内部时钟倍频系数。
    - SYSCTL_FMULT_NONE:不使用分数倍频。
    - SYSCTL_SYSDIV(2):使用2作为系统时钟分频系数。
    - SYSCTL_PLL_ENABLE:启用PLL(锁相环)。

    因此,这个宏定义的作用是设置设备的时钟配置,使其使用外部晶体振荡器作为时钟源,使用10作为内部时钟倍频系数,不使用分数倍频,使用2作为系统时钟分频系数,并启用PLL。

  4. 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);
    }

  5. 这是一个名为SysCtl_getClock的函数,它接受一个参数clockInHz,表示时钟频率。该函数的作用是获取系统时钟的频率。函数首先检查是否检测到MCD故障,如果检测到,则返回默认的OSC频率。否则,如果使用内部振荡器之一,则从已知的默认频率开始。否则,使用传入的clockInHz参数。如果启用PLL,则计算其对时钟的影响。最后,如果设置了PLLSYSCLKDIV,则将时钟频率除以2 * PLLSYSCLKDIV。 

  6. 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);
    }

  7. bool是一种布尔类型,只有两个值:True和False。在这个函数中,bool类型的变量status被用来表示函数是否成功执行。如果函数成功执行,则status为True,否则为False。

    该函数是一个用于设置系统时钟的函数。它首先检查传入的参数是否合法,然后配置振荡器源并绕过PLL。接下来,它获取PLL乘数设置并检查当前程序的PLL乘数。如果需要更新乘数,则锁定PLL并写入新的乘数。如果PLL成功锁定,则配置分频器以产生较慢的输出频率,以限制电流增加。最后,它将PLLSYSCLK使能,并设置分频器以用户值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值