1.3. 系统控制:时钟与初始化

系统控制模块管理芯片的时钟、复位、看门狗和 CPU 定时器。

1.3.1. 时钟系统

┌────────────┐    ┌──────────────┐    ┌─────────────┐
│ 外部晶振    │    │  PLL 配置     │    │  CPU 时钟    │
│ (OSC/XTAL) │───→│  PLLCR[DIV]  │───→│  CLKIN       │
│ 20~35 MHz  │    │  + PLLSTS    │    │  150 MHz    │
└────────────┘    └──────────────┘    └──────┬──────┘
                                              │
                                     ┌────────┴────────┐
                                     │  外设时钟分频     │
                                     │  HSPCLK=75MHz   │
                                     │  LSPCLK=37.5MHz │
                                     └─────────────────┘

1.3.1.1. PLL 配置

// F28335: 输入 30 MHz → 150 MHz CPU 时钟
// 配置: PLLCR = 10 (×10 ÷ 2 = 5 倍频)
// CLKIN = 30 MHz × (PLLCR / 2) = 150 MHz

void InitPll(uint16_t pllcr, uint16_t pllsts)
{
    // 1. 断开 PLL
    SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;  // 分频器 = /2

    // 2. 设置倍频
    SysCtrlRegs.PLLCR.bit.DIV = pllcr;  // ×10

    // 3. 等待 PLL 锁定
    while (SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1) { }

    // 4. 设置最终分频
    SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;  // 不分频
}

重要

F28335 常用的时钟配置:

晶振 (MHz)

PLLCR

DIVSEL

CPU 时钟 (MHz)

20

10

3 (/1)

100

30

10

3 (/1)

150

20

10

2 (/2)

50

1.3.1.2. 外设时钟使能

void EnablePeripheralClocks(void)
{
    EALLOW;

    // 使能 ePWM 时钟
    SysCtrlRegs.PCLKCR0.bit.EPWM1ENCLK = 1;
    SysCtrlRegs.PCLKCR0.bit.EPWM2ENCLK = 1;
    SysCtrlRegs.PCLKCR0.bit.ECAP3ENCLK = 1;

    // 使能 ADC 时钟(高速时钟 HSPCLK)
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;

    // 使能 SCI 时钟(低速时钟 LSPCLK)
    SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1;
    SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 1;

    // 使能 SPI / I2C 时钟
    SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1;
    SysCtrlRegs.PCLKCR1.bit.I2CAENCLK = 1;

    EDIS;
}

警告

默认情况下所有外设时钟**都是关闭的**。 使用外设前必须先使能对应的时钟。这是常见的遗漏点。

1.3.2. 看门狗

void DisableWatchdog(void)
{
    EALLOW;
    SysCtrlRegs.WDCR = 0x00E8;  // WDPS=111 (/128), WDDIS=1(禁用)
    // Bit 7-6: 00 (保留)
    // Bit 5-3: 111 (分频 /128)
    // Bit 2-0: WDCHK = 101 必须写入 101 才有效
    EDIS;
}

void ServiceWatchdog(void)
{
    EALLOW;
    SysCtrlRegs.WDKEY = 0x0055;  // 第一步
    SysCtrlRegs.WDKEY = 0x00AA;  // 第二步(必须在 512 个 OSCCLK 内)
    EDIS;
}
看门狗定时周期:
WDCLK = OSCCLK / (WDPS × 512)
若 OSCCLK = 30 MHz, WDPS = /64:
WDCLK = 30e6 / (64 × 512) ≈ 915 Hz
超时 = 1 / 915 ≈ 1.09 ms

1.3.3. CPU 定时器

F28335 有三个 32 位 CPU 定时器(Timer 0/1/2),Timer 2 保留给实时操作系统。

struct CPUTIMER_VARS {
    volatile uint32_t  RegsAddr;
    uint32_t  CPUFreqInMHz;
    uint32_t  PeriodInUSec;
};

void InitCpuTimers(void)
{
    // Timer 0: CPU 频率 150 MHz, 周期 1ms
    ConfigCpuTimer(&CpuTimer0, 150, 1000);
    CpuTimer0Regs.TCR.bit.TIE = 1;   // 使能中断
    CpuTimer0Regs.TCR.bit.TSS = 0;   // 启动
}

// 定时器中断服务函数
interrupt void cpu_timer0_isr(void)
{
    CpuTimer0.InterruptCount++;      // 每 1ms 递增
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;  // 应答中断
}

备注

  • Timer 0:用户可用,可触发 PIE 中断

  • Timer 1:用户可用,不触发中断(轮询)

  • Timer 2:保留给 RTOS(如 TI-RTOS、SYS/BIOS)

1.3.4. 系统初始化流程

void main(void)
{
    // 步骤 1:系统控制初始化
    InitSysCtrl();              // PLL + 看门狗 + 外设时钟

    // 步骤 2:GPIO 初始化
    InitGpio();                 // 配置 GPIO 功能

    // 步骤 3:PIE 中断初始化
    DINT;                       // 关闭全局中断
    InitPieCtrl();              // PIE 控制寄存器
    IER = 0x0000;              // 关闭 CPU 中断
    IFR = 0x0000;              // 清除标志
    InitPieVectTable();        // 初始化中断向量

    // 步骤 4:外设初始化
    InitAdc();
    InitEPwm();
    InitSci();

    // 步骤 5:用户初始化
    EALLOW;
    PieVectTable.TINT0 = &cpu_timer0_isr;  // 注册中断
    EDIS;
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;     // 使能 Timer 0
    IER |= M_INT1;                          // 使能 CPU INT1
    EINT;                                   // 开启全局中断

    // 步骤 6:主循环
    while (1) {
        // 后台任务
    }
}