C2000基础-时钟树介绍及使用
C2000时钟系统摘要 C2000系列微控制器提供灵活的时钟系统,包含四种时钟源:主内部振荡器INTOSC2(默认10MHz)、备份振荡器INTOSC1、外部辅助时钟AUXCLKIN和外部晶振XTAL。系统支持通过PLL进行倍频,并通过多级分频器生成不同频率的时钟信号。TI提供的DriverLib库包含时钟配置API,如SysCtl_setClock()用于设置系统时钟,SysCtl_getClo
第二章 时钟树介绍及基础使用
1. 时钟源
芯片上所有的时钟均来自四个时钟源中的一个,分别是INTOSC2、INTOSC1、AUXCLKIN、XTAL
1.1 INTOSC2
INTOSC2 为主内部振荡器。上电时,器件由片内10MHz振荡器(INTOSC2)提供时钟。INTOSC2是主要的内部时钟源,也是复位时的默认系统时钟。该振荡器用于运行引导ROM,并可作为应用程序的系统时钟源。
需注意:INTOSC2的频率容差范围较宽,无法满足CAN模块的时序要求。使用CAN模块时必须外接振荡器。当INTOSC2作为系统时钟源时,GPIO19(X1)和GPIO18(X2)可作为通用GPIO引脚使用。
1.2 INTOSC1
INTOSC1 为备份内部振荡器,一个冗余的片上10MHz振荡器。INTOSC1作为备用时钟源,默认仅用于看门狗定时器和缺失时钟检测电路(MCD)的时钟供给。若启用MCD功能且检测到系统时钟丢失,则系统PLL会被旁路,所有系统时钟会自动连接到INTOSC1。此外,开发者也可手动选择INTOSC1作为系统时钟源,用于调试目的。
1.3 AUXCLKIN
AUXCLKIN 为辅助时钟输入。器件支持通过 GPIO29(AUXCLKIN)引脚接入额外的外部时钟源。该时钟必须为单端3.3V的外部时钟信号,可用作MCAN模块的时钟源。其频率限制和时序要求详见《TMS320F28P55x实时微控制器数据手册》。该外部时钟可直接连接至GPIO29引脚。

1.4 XTAL
XTAL 为外部时钟源。可以作为主系统和CAN1位时钟源使用。外部时钟源使用 X1/GPIO19 和 X2/GPIO18 引脚输入。它支持3种输入信号的方式:
- 一个单端3.3V外部时钟,可以直接连到X1,X2可以作为GPIO使用。

- 一个外部晶振,该晶振可通过X1和X2连接起来,同时负载电容也需要连接到位。

- 一个外部谐振器,通过X1和X2与地相连。

2. 基于时钟的延时函数使用
在 TI 的工程模板中,给我们准备好了一个可以微秒时间的延时函数:DEVICE_DELAY_US(x)。

使用方法也很简单,要延时多少微秒,就往里面填多少值就好了。
需要注意的是其参数中 DEVICE_SYSCLK_FREQ 为默认的150MHz,如果我们的主频被修改了,它就不准确了。除非我们主动修改 DEVICE_SYSCLK_FREQ 为我们修改后的主频。
后面的代码可以以微秒作为基数,将其再度封装出延时毫秒、秒的功能。这样在处理一些软件时序时就有了延时功能。
void delay_ms(int x)
{
while(x--)
{
DEVICE_DELAY_US(1000);
}
}
void delay_s(int x)
{
while(x--)
{
delay_ms(1000);
}
}
2.1 硬件说明
使用外部时钟源:20MHz 的外部晶振输入,将工程原本的 150MHz 主频配置为 50MHz,通过 CCS 自带的 CIO 功能输出当前主频,并在主循环中执行 LED 间隔 1 秒闪烁的代码。
2.2 CCS工程
2.2.1 CCS&syscfg配置

在时钟树选项页下,选择 CPUCLK 选项,开始对 CPUCLK 时钟树进行配置。
-
使能
XTAL时钟源,其输入频率为 20MHz。 -
XRAL_OR_X1中选择 XTAL。 -
OSCLKSRCSEL中选择使用 X1_XTAL。 -
在 SYSPLL 中的
PLL_REFDIV中,选择 1 分频。 -
在 SYSPLL 中的
PLL_IMULT中,选择 30 倍频。 -
在 SYSPLL 中的
PLL_ODIV中,选择 2 分频。 -
在
SYSCLKDIVSEL中,选择 6 分频。 -
最终得到主频
CPUCLK频率为 50MHz。
配置板载的蓝灯引脚 GPIO20 为输出模式。

2.2.2 用户代码
我们修改的时钟树配置代码生成在 clocktree.h 文件中,主要是其中的 DEVICE_OSCSRC_FREQ、DEVICE_SETCLOCK_CFG、DEVICE_SYSCLK_FREQ 宏定义。
而工程下有一个默认配置文件 device.h,其中进行了工程默认时钟主频的配置,它也定义了 DEVICE_SETCLOCK_CFG等3个宏定义。为了不冲突,我们将 clocktree.h 中定义的频率调整后的宏定义直接覆盖更新到 device.h 中。
#define MY_DEVICE_OSCSRC_FREQ 20000000U
//
// Define to pass to SysCtl_setClock(). Will configure the clock as follows:
// SYSPLL ENABLED
// SYSCLK = 50 MHz = 20 MHz (OSCCLK) * 30 (IMULT) / (1 (REFDIV) * 2 (ODIV) * 6 (SYSCLKDIVSEL))
#define MY_DEVICE_SYSCLK_FREQ ((DEVICE_OSCSRC_FREQ * 30) / (1 * 2 * 6))
//
#define MY_DEVICE_SETCLOCK_CFG (SYSCTL_OSCSRC_XTAL | SYSCTL_IMULT(30) | \
SYSCTL_REFDIV(1) | SYSCTL_ODIV(2)| \
SYSCTL_SYSDIV(6) | SYSCTL_PLL_ENABLE | \
SYSCTL_DCC_BASE_0)


更新工程的 empty_driverlib_main.c 文件为以下代码:
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "c2000ware_libraries.h"
#include "stdio.h" //导入用以支持 printf
//任意毫秒延时
void delay_ms(int x)
{
while(x--)
{
//调用 TI 自带的微秒延时
DEVICE_DELAY_US(1000);
}
}
void main(void)
{
Device_init();
Device_initGPIO();
Interrupt_initModule();
Interrupt_initVectorTable();
Board_init();
C2000Ware_libraries_init();
EINT;
ERTM;
//重新配置系统时钟
SysCtl_setClock(DEVICE_SETCLOCK_CFG);
//获取当前主频并输出
printf("clk = %ld\r\n", SysCtl_getClock(DEVICE_OSCSRC_FREQ) );
while(1)
{
GPIO_togglePin(GPIO_BLUE);//蓝灯的引脚状态切换
delay_ms(1000);//延时1000ms
}
}
3. C2000 时钟系统与配置总结 (基于DriverLib)
注:本总结以TMS320F2837x/Dx系列为例,其架构在C2000产品线中具有代表性。其他型号如F2833x或F28004x概念相通,但具体时钟源、分频器数量和多路选择器可能存在差异,请务必查阅具体芯片的技术参考手册 (TRM) 和 DriverLib用户指南。
3.1 时钟树概述与核心组件
C2000的时钟系统通常比ARM Cortex-M系列更简洁,但非常灵活和强大,旨在满足实时控制应用的精确时序要求。
-
核心时钟路径(简化流程):
时钟源 -> PLL (倍频) -> CPU时钟 -> SYSCLKOUT -> 外设时钟 (HSPCLK, LSPCLK) / 系统外设时钟 -
主要组件说明:
组件 功能 C2000特点 时钟源 提供原始时钟信号。 1. 内部振荡器 (INTOSC):低成本,精度较低。
2. 外部晶体振荡器 (XTAL) + 内部OSC:高精度。
3. 外部时钟源 (EXTSYSCLK):直接输入方波。PLL 锁相环。将输入时钟倍频到更高的核心系统时钟。 C2000 PLL配置灵活,通过 PLLCR和PLLSTS寄存器控制。支持旁路模式。系统时钟 (SYSCLKOUT) PLL输出的时钟,是CPU和大多数外设的时钟源。 所有时序的核心参考。例如,SYSCLKOUT=200MHz。 预分频器 对SYSCLKOUT进行分频,产生不同速度的时钟域。 - HSPCLK: 高速外设时钟 (ePWM, HRPWM, eCAP)。
- LSPCLK: 低速外设时钟 (SCI, SPI, I2C)。
- ADC时钟: 通常由SYSCLKOUT或HSPCLK分频得到。
3.2 时钟初始化与配置函数
-
核心配置流程(四步关键操作):
-
配置PLL旁路(确保系统从安全时钟启动)
-
配置时钟源(选择OSC源,等待稳定)
-
配置并启用PLL(设置倍频系数,等待锁定)
-
配置外设时钟分频器(设置HSPCLK, LSPCLK等的速度)
-
-
基础配置示例(配置外部10MHz晶振,通过PLL倍频到200MHz):
#include "driverlib.h" void main(void) { // 1. 初始化器件控制(必须首先调用) Device_init(); // 此函数会初始化一些基本控制,但通常不会直接配置PLL到最终状态 // 2. 禁用PLL并进入旁路模式(安全操作) SysCtl_disablePLL(SYSCTL_PLL_ENABLE_CTL_DISABLE); // 先禁用PLL DEVICE_DELAY_US(100); // 短暂延迟 SysCtl_setPLLBypassMode(SYSCTL_PLL_BYPASS_MODE_ENABLE); // 启用旁路,直接使用时钟源 // 3. 配置时钟源 - 使用外部10MHz晶体 // 假设XTAL=10MHz,配置内部振荡器电路来驱动它 SysCtl_setClockSource(SYSCTL_CLOCK_SOURCE_EXTERNAL); // 或 SYSCTL_CLOCK_SOURCE_OSCCLK SysCtl_setOscSource(SYSCTL_OSCSRC_XTAL); // 明确设置振荡器源为外部晶体 // 等待外部晶振稳定(检查XREADY位) while(SysCtl_getOscStatus(SYSCTL_OSC_STATUS_XTAL) != SYSCTL_OSC_STATUS_XTAL_READY) {} // 4. 配置PLL倍频系数并启用PLL // 目标频率 = (CLKIN * PLLCR.DIV) / (PLLSTS.DIVSEL) / 2 // F2837x: 常用配置是 PLLCR.DIV=40, PLLSTS.DIVSEL=0 (除以2) -> (10MHz * 40) / 2 = 200MHz SysCtl_setPLLMultiplier(40); // 设置PLLCR寄存器的DIV值 SysCtl_setPLLDivider(SYSCTL_PLL_DIVIDER_DIV_2); // 设置DIVSEL=0, 即除以2 SysCtl_setPLLBypassMode(SYSCTL_PLL_BYPASS_MODE_DISABLE); // 退出旁路模式,接入PLL SysCtl_enablePLL(SYSCTL_PLL_ENABLE_CTL_ENABLE); // 正式使能PLL // 5. 等待PLL锁定 while(SysCtl_getPLLStatus() != SYSCTL_PLL_STATUS_LOCK) {} // 6. 配置外设时钟预分频器 // 设置高速外设时钟HSPCLK = SYSCLKOUT / 2 = 100MHz SysCtl_setHSPCLKDIV(SYSCTL_HSPCLKDIV_DIV_2); // 设置低速外设时钟LSPCLK = SYSCLKOUT / 4 = 50MHz SysCtl_setLSPCLKDIV(SYSCTL_LSPCLKDIV_DIV_4); // 此时,系统时钟SYSCLKOUT已运行在200MHz // CPU时钟也等于SYSCLKOUT (C28x内核) // ... 其他外设初始化 ... } -
关键配置函数详解:
函数 (DriverLib - F2837x) 说明 参数示例与解释 SysCtl_disablePLL()/SysCtl_enablePLL()禁用/使能PLL。 SYSCTL_PLL_ENABLE_CTL_DISABLESYSCTL_PLL_ENABLE_CTL_ENABLESysCtl_setPLLBypassMode()设置PLL旁路模式。 SYSCTL_PLL_BYPASS_MODE_ENABLE(使用原始时钟源)SYSCTL_PLL_BYPASS_MODE_DISABLE(使用PLL输出)SysCtl_setClockSource()选择系统时钟源。 SYSCTL_CLOCK_SOURCE_OSCCLK(主OSC)SYSCTL_CLOCK_SOURCE_AUX(辅助时钟源)SysCtl_setOscSource()选择主振荡器源。 SYSCTL_OSCSRC_XTAL(外部晶体)SYSCTL_OSCSRC_INT(内部振荡器)SysCtl_setPLLMultiplier(uint16_t multiplier)设置PLL倍频系数 (PLLCR.DIV)。 multiplier = 目标频率 * 2 * DIVSEL / CLKIN
例如:10MHz -> 200MHz, DIV=40, DIVSEL=0SysCtl_setPLLDivider(SysCtl_PLLDivider divider)设置PLL后分频器 (PLLSTS.DIVSEL)。 SYSCTL_PLL_DIVIDER_DIV_1(DIVSEL=2)SYSCTL_PLL_DIVIDER_DIV_2(DIVSEL=0) 常用SYSCTL_PLL_DIVIDER_DIV_4(DIVSEL=1)SysCtl_getPLLStatus()获取PLL锁定状态。 返回值需与 SYSCTL_PLL_STATUS_LOCK比较SysCtl_setHSPCLKDIV()设置高速外设时钟分频。 SYSCTL_HSPCLKDIV_DIV_1(HSPCLK=SYSCLKOUT)SYSCTL_HSPCLKDIV_DIV_2(HSPCLK=SYSCLKOUT/2)SysCtl_setLSPCLKDIV()设置低速外设时钟分频。 SYSCTL_LSPCLKDIV_DIV_2(LSPCLK=SYSCLKOUT/2)SYSCTL_LSPCLKDIV_DIV_4(LSPCLK=SYSCLKOUT/4)
3.3 时钟源与PLL配置详解
-
PLL配置公式(F2837x):
SYSCLKOUT = (CLKIN * PLLCR.DIV) / (PLLSTS.DIVSEL_VALUE) / 2DIVSEL (寄存器值) Divider Value DriverLib 宏 0 /2 SYSCTL_PLL_DIVIDER_DIV_21 /4 SYSCTL_PLL_DIVIDER_DIV_42 /1 SYSCTL_PLL_DIVIDER_DIV_13 Reserved 计算示例:
-
目标:CLKIN=10MHz, SYSCLKOUT=200MHz。
-
计算:选择DIVSEL=0 (/2)。代入公式:
200 = (10 * DIV) / 2=>DIV = 40。 -
代码:
SysCtl_setPLLMultiplier(40);+SysCtl_setPLLDivider(SYSCTL_PLL_DIVIDER_DIV_2);
-
-
常见时钟源配置:
场景 配置步骤 内部振荡器 (INTOSC) 1. SysCtl_setOscSource(SYSCTL_OSCSRC_INT);
2. (可选) 调整内部振荡器精度(如果有相关函数)。
3. PLL配置公式中的CLKIN为内部振荡器频率(如10MHz)。外部晶体 (10MHz) 1. 硬件连接晶体和负载电容。
2.SysCtl_setOscSource(SYSCTL_OSCSRC_XTAL);
3. 等待稳定while(!SysCtl_getOscStatus(SYSCTL_OSC_STATUS_XTAL));
4. PLL配置公式中的CLKIN为晶体频率。外部有源时钟 1. 将时钟信号连接到XCLKIN或X1引脚(取决于芯片)。
2. 配置GPIO复用为时钟输入功能。
3.SysCtl_setClockSource(...)选择正确的源。
4. PLL配置公式中的CLKIN为外部时钟频率。
3.4 外设时钟配置
系统时钟配置好后,需要为各个外设配置其运行时钟。
-
ePWM (HRPWM) 时钟:
ePWM模块的时钟来自HSPCLK。// 假设SYSCLKOUT=200MHz, HSPCLK配置为100MHz SysCtl_setHSPCLKDIV(SYSCTL_HSPCLKDIV_DIV_2); // HSPCLK = 200MHz / 2 = 100MHz // 在初始化ePWM时,其时间基准周期(TBPRD)和比较值(CMPA)的计算都基于HSPCLK(100MHz) EPWM_setTimeBasePeriod(myEPWM1_BASE, 10000); // 周期 = 10000 TBCLK counts // TBCLK = HSPCLK / (HSDIVIDER * CLKDIV) -> 通常直接分频HSPCLK EPWM_setClockPrescaler(myEPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // TBCLK = HSPCLK = 100MHz -
串口 (SCI) 时钟:
SCI模块的时钟来自LSPCLK。// 假设SYSCLKOUT=200MHz, LSPCLK配置为50MHz SysCtl_setLSPCLKDIV(SYSCTL_LSPCLKDIV_DIV_4); // LSPCLK = 200MHz / 4 = 50MHz // 配置SCI波特率,计算基于LSPCLK SCI_setBaudRate(mySCI_BASE, 115200, 50000000); // 波特率115200, LSPCLK=50MHz -
ADC时钟:
ADC时钟通常有独立的分频器,源可以是SYSCLKOUT或HSPCLK(取决于芯片)。// 配置ADC核心时钟分频器 // ADC_CLK = (SYSCLKOUT / ADCDIV) ADC_setCoreClockDivider(myADC_BASE, ADC_CORE_CLOCK_DIVIDER_4); // ADC clock = 200MHz / 4 = 50MHz // 配置采样窗口周期(基于ADC_CLK) ADC_setSamplingWindow(myADC_BASE, ADC_SAMPLE_WINDOW_10_ADC_CLKS);
4. 关键注意事项
-
启动顺序:配置PLL时必须遵循 “禁用 -> 旁路 -> 配置 -> 使能 -> 等待锁定” 的顺序,否则可能导致芯片锁死或运行不稳定。
-
时钟验证:
-
在调试时,可以使用GPIO toggle或CCS的寄存器查看器来验证时钟频率是否配置正确。
-
例如,将GPIO配置为输出,在主循环中翻转,用示波器测量实际频率,应与计算值相符。
- 低功耗模式:
-
C2000支持IDLE、STANDBY、HALT等低功耗模式,这些模式会动态地门控(关闭)时钟。
-
使用
SysCtl_setLowPowerMode(SYSCTL_LOW_POWER_MODE_IDLE);等函数进入,通过中断唤醒。
- 看门狗时钟:
- 看门狗有独立的时钟源(通常是INTOSC),即使系统主时钟失效,看门狗依然能工作,这是重要的安全特性。配置看门狗时需注意其分频设置。
- 芯片间差异:
- F28004x等较新的系列,其时钟配置API和寄存器名称可能与F2837x有所不同(例如使用
CLK_setPLLMultiplier等函数),但核心概念(时钟源、PLL、分频)是一致的。始终以您所使用的芯片的文档为准。
文中完整参考代码:https://github.com/hazy1k/C2000-Quick-Start-Guide-CCS/tree/main/TMS320F28P550/2.code
更多推荐



所有评论(0)