ARM时钟初始化与GPT定时器深度解析

一、系统时钟初始化流程(clock.c)

阶段 1:为什么系统一开始必须初始化时钟?

目的 / 作用

  1. 决定 CPU 主频
  2. 决定 AHB / IPG 总线频率
  3. GPT、GPIO、UART、GIC 等外设提供时钟源
  4. 保证延时、定时、中断时序是"准确的"

❗如果不初始化:

  • GPT 计数不准
  • delay_us 完全不可信
  • 外设可能根本不工作

阶段 2:ARM 核心时钟配置(PLL1)

代码

  1. CCM->CCSR &= ~(1 << 8);
  2. CCM->CCSR |= (1 << 2);

做了什么?

含义
CCSR2 临时切换到 step clock
CCSR8 PLL1 bypass

目的

👉 切换 ARM 内核时钟源到安全时钟

👉 避免在改 PLL 时 CPU 跑飞


阶段 3:ARM 时钟分频(CACRR)

  1. CCM->CACRR &= ~(7 << 0);
  2. CCM->CACRR |= (1 << 0);

作用

  • 设置 ARM 核心时钟预分频
  • 1 表示 不分频 / 2 分频(依芯片定义)

注意点

  • ARM 核心最终频率 = PLL1 / CACRR
  • 分频过小 → CPU 太快 → 功耗高
  • 分频过大 → 系统整体变慢

阶段 4:配置 ARM PLL(PLL1)

  1. unsigned int t = CCM_ANALOG->PLL_ARM;
  2. t &= ~(3 << 14);
  3. t |= (1 << 13);
  4. t &= ~(0x7F << 0);
  5. t |= (88 << 0);
  6. CCM_ANALOG->PLL_ARM = t;

做了什么?

位段 含义
bit13 使能 PLL
bit6:0 倍频系数

👉 这里配置的是:

PLL1 = 24MHz × 88 = 1056MHz


阶段 5:切回 PLL1 作为 CPU 时钟

CCM->CCSR &= ~(1 << 2);

作用

👉 ARM 核心正式使用 PLL1 输出的高速时钟


阶段 6:配置 528PLL / 480PLL(外设时钟源)

CCM_ANALOG->PFD_528 = ...

CCM_ANALOG->PFD_480 = ...

目的

  • AHB、IPG、GPT、EPIT、UART 等外设提供稳定时钟
  • 不同 PFD → 不同频率

注意点

  • GPT 使用的是 IPG_CLK
  • IPG_CLK 又来自 AHB

阶段 7:配置 AHB / IPG / PERCLK

  1. CCM->CBCMR
  2. CCM->CBCDR
  3. CCM->CSCMR1

时钟关系链(非常重要)

PLL → AHB → IPG → GPT / GPIO / IOMUX

👉 你这里设置的是 经典推荐配置


阶段 8:使能所有外设时钟门控

clock_cg_init();

CCM->CCGRx = 0xFFFFFFFF;

作用

👉 打开所有模块的时钟

注意点

  • 方便调试
  • 实际产品中不推荐(功耗大)

二、GPT 定时器工作流程(gpt.c)
GPT = 一个"不断递增的硬件计数器"


阶段 1:为什么要用 GPT?

目的 / 作用

  1. 实现 精确 us / ms 延时
  2. 不依赖 CPU 空转频率
  3. 和系统主频解耦

对比:

  • while(t--) ❌ 不准
  • GPT 计数 ✅ 准确

阶段 2:GPT1 复位

  1. GPT1->CR |= (1 << 15);
  2. while ((GPT1->CR & (1 << 15)) != 0);

作用

  • 让 GPT 回到硬件初始状态
  • 清除所有历史配置

注意点

  • 必须等待硬件复位完成

阶段 3:配置 GPT 控制寄存器 CR

  1. t = GPT1->CR;
  2. t &= ~(7 << 26); // 时钟源
  3. t &= ~(3 << 18); // 工作模式
  4. t |= (1 << 9); // Free-run
  5. t &= ~(7 << 6);
  6. t |= (1 << 6); // 外设时钟
  7. t &= ~(1 << 1); // 关闭中断
  8. GPT1->CR = t;

关键配置解释

作用
bit9 自由运行模式
bit6 使用 IPG_CLK
bit1 不启用中断

👉 GPT 现在是 纯计数器模式


阶段 4:设置 GPT 预分频器

  1. GPT1->PR &= ~(0xFFF << 0);
  2. GPT1->PR |= (65 << 0);

作用

  • 将 IPG_CLK 分频
  • 假设 IPG = 66MHz

66MHz / (65+1) ≈ 1MHz

👉 CNT 每加 1 = 1μs


阶段 5:启动 GPT

GPT1->CNT = 0;

GPT1->CR |= (1 << 0);

作用

  • 清零计数器
  • 开始计数

阶段 6:delay_us 的完整工作流程

  1. old_count = GPT1->CNT;
  2. while (1)
  3. {
  4. new_count = GPT1->CNT;
  5. if (new_count != old_count)
  6. {
  7. if (new_count > old_count)
  8. count += new_count - old_count;
  9. else
  10. count += 0xFFFFFFFF - old_count + new_count;
  11. }
  12. if (count >= us)
  13. return ;
  14. old_count = new_count;
  15. }

这是在干什么?

👉 用硬件计数差值计算经过的时间

为什么要处理回绕?

  • GPT 是 32 位计数器
  • 会从 0xFFFFFFFF → 0
  • 必须处理溢出

阶段 7:delay_ms 的工作方式

  1. delay_ms(ms)
  2. {
  3. while (ms--)
  4. delay_us(1000);
  5. }

👉 本质还是 GPT


三、main.c 中的整体配合流程

  1. system_interrupt_init();
  2. clock_init();
  3. led_init();
  4. beep_init();
  5. key_init();
  6. gpt1_init();

顺序为什么这样?

1️⃣ 中断系统先准备好

2️⃣ 时钟先跑稳

3️⃣ GPIO / 外设再初始化

4️⃣ 定时器最后启动


while(1) 中发生了什么?

delay_us(1000 * 1000);

led_nor();

👉 GPT 在后台跑

👉 CPU 通过 CNT 判断时间

👉 精确 1 秒翻转 LED

相关推荐
hsjiasb9 小时前
FreeRTOS学习(二十六)——动态内存管理heap_1到heap_5
stm32·单片机·学习·学习笔记·freertos
LCG元10 小时前
STM32+ESP8266+MQTT 物联网气象站:从零搭建温湿度远程监测系统(附完整源码)
stm32·物联网·struts
FakeOccupational12 小时前
【电路笔记 STM32】Cortex-M7 内核上的数据缓存(D-Cache)结构+MPU+DMA&Cache+STM32CubeMX配置
笔记·stm32·缓存
殷忆枫12 小时前
基于K210与STM32的智能垃圾分类与物联网监管系统
stm32·物联网·分类
周洲083013 小时前
STM32 GPIO 外部中断深度解析:边沿触发 / 电平触发、NVIC 优先级配置、中断嵌套实战
stm32·单片机·嵌入式硬件
LCG元13 小时前
STM32F103 CAN 总线通信实战:标准库双机通信与过滤器配置精讲
stm32·单片机·嵌入式硬件
zlinear数据采集卡14 小时前
D223的PWM电机控制:6路独立脉冲+加减速算法深度解析
arm开发·stm32·嵌入式硬件·算法·fpga开发·架构
z203483152015 小时前
STM32单片机控制无源蜂鸣器播放《晴天》
stm32·单片机·嵌入式硬件
国科安芯17 小时前
详解ADC 规则组外部触发:CH2、CH3 与 TRGO2
运维·网络·单片机·嵌入式硬件·mcu·系统架构
ACP广源盛1392462567317 小时前
WAIC2026 国产算力浪潮@ACP#YLB3118 在算力矩阵中的存储定位与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件