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) {
// 后台任务
}
}