嵌入式——定时器工作原理

嵌入式------定时器工作原理

一句话总结:定时器 = 时钟信号 + 分频器 + 计数器 + 通知机制------通过固定频率、修改计数值,实现高精度延时控制。


第 1 章 · 为什么需要硬件定时器

1.1 核心概念

一句话总结 :软件循环延时(如 for 循环空转)精度低、浪费 CPU,硬件定时器是独立于 CPU 运行的精确计时方案。

生活类比:软件延时就像你盯着手表数秒------你什么别的事都做不了(浪费 CPU),而且数久了还会数错(精度低)。硬件定时器就像买个厨房定时器------设定好时间后它自己倒计时,到点了叮一声通知你,期间你可以安心做菜(CPU 干别的活)。


1.2 先看对比:软件延时 vs 硬件定时器

软件延时:循环空转,浪费 CPU

cpp 复制代码
// 粗略延时约 1 秒(不精确!)
void delay_approx_1s() {
    for (int i = 0; i < 1000; i++) {        // 外层 1000 次
        for (int j = 0; j < 50000; j++) {   // 内层 5 万次
            __asm("nop");                   // 空操作,什么都不做
        }
    }
}

问题:

  • 精度低:循环次数只是"估算",不同编译器优化结果不同
  • 浪费 CPU:CPU 在空转,不能做任何其他工作
  • 不可移植:换个 CPU 频率,延时时间就变了

硬件定时器:独立计时,释放 CPU

cpp 复制代码
// 硬件定时器配置(以 STM32 为例)
void timer_init_1s() {
    // ① 时钟源:内部晶振 72 MHz
    // ② 分频系数:7200 → 计数器频率 = 72 MHz / 7200 = 10 KHz
    // ③ 计数值:10000 → 定时时间 = 10000 / 10 KHz = 1 秒
    TIM2->PSC  = 7200 - 1;     // 设置分频系数
    TIM2->ARR  = 10000 - 1;    // 设置计数值(自动重装载)
    TIM2->DIER = TIM_DIER_UIE; // 使能中断
    TIM2->CR1  = TIM_CR1_CEN;  // 启动定时器
    // CPU 可以去做其他事了!
}

// 定时器中断服务函数(1 秒后自动调用)
void TIM2_IRQHandler() {
    if (TIM2->SR & TIM_SR_UIF) {
        TIM2->SR = ~TIM_SR_UIF;  // 清除中断标志
        toggle_LED();            // 翻转 LED
    }
}

#mermaid-svg-L8CROciJ1BnUVkoV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-L8CROciJ1BnUVkoV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-L8CROciJ1BnUVkoV .error-icon{fill:#552222;}#mermaid-svg-L8CROciJ1BnUVkoV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-L8CROciJ1BnUVkoV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-L8CROciJ1BnUVkoV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-L8CROciJ1BnUVkoV .marker.cross{stroke:#333333;}#mermaid-svg-L8CROciJ1BnUVkoV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-L8CROciJ1BnUVkoV p{margin:0;}#mermaid-svg-L8CROciJ1BnUVkoV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-L8CROciJ1BnUVkoV .cluster-label text{fill:#333;}#mermaid-svg-L8CROciJ1BnUVkoV .cluster-label span{color:#333;}#mermaid-svg-L8CROciJ1BnUVkoV .cluster-label span p{background-color:transparent;}#mermaid-svg-L8CROciJ1BnUVkoV .label text,#mermaid-svg-L8CROciJ1BnUVkoV span{fill:#333;color:#333;}#mermaid-svg-L8CROciJ1BnUVkoV .node rect,#mermaid-svg-L8CROciJ1BnUVkoV .node circle,#mermaid-svg-L8CROciJ1BnUVkoV .node ellipse,#mermaid-svg-L8CROciJ1BnUVkoV .node polygon,#mermaid-svg-L8CROciJ1BnUVkoV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-L8CROciJ1BnUVkoV .rough-node .label text,#mermaid-svg-L8CROciJ1BnUVkoV .node .label text,#mermaid-svg-L8CROciJ1BnUVkoV .image-shape .label,#mermaid-svg-L8CROciJ1BnUVkoV .icon-shape .label{text-anchor:middle;}#mermaid-svg-L8CROciJ1BnUVkoV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-L8CROciJ1BnUVkoV .rough-node .label,#mermaid-svg-L8CROciJ1BnUVkoV .node .label,#mermaid-svg-L8CROciJ1BnUVkoV .image-shape .label,#mermaid-svg-L8CROciJ1BnUVkoV .icon-shape .label{text-align:center;}#mermaid-svg-L8CROciJ1BnUVkoV .node.clickable{cursor:pointer;}#mermaid-svg-L8CROciJ1BnUVkoV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-L8CROciJ1BnUVkoV .arrowheadPath{fill:#333333;}#mermaid-svg-L8CROciJ1BnUVkoV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-L8CROciJ1BnUVkoV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-L8CROciJ1BnUVkoV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-L8CROciJ1BnUVkoV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-L8CROciJ1BnUVkoV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-L8CROciJ1BnUVkoV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-L8CROciJ1BnUVkoV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-L8CROciJ1BnUVkoV .cluster text{fill:#333;}#mermaid-svg-L8CROciJ1BnUVkoV .cluster span{color:#333;}#mermaid-svg-L8CROciJ1BnUVkoV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-L8CROciJ1BnUVkoV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-L8CROciJ1BnUVkoV rect.text{fill:none;stroke-width:0;}#mermaid-svg-L8CROciJ1BnUVkoV .icon-shape,#mermaid-svg-L8CROciJ1BnUVkoV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-L8CROciJ1BnUVkoV .icon-shape p,#mermaid-svg-L8CROciJ1BnUVkoV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-L8CROciJ1BnUVkoV .icon-shape .label rect,#mermaid-svg-L8CROciJ1BnUVkoV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-L8CROciJ1BnUVkoV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-L8CROciJ1BnUVkoV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-L8CROciJ1BnUVkoV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ❌ 软件延时
✅ 硬件定时器
需要延时 1 秒
用什么方式?
CPU 空转循环

什么其他事都不能做
设置定时器参数后

CPU 去干别的

到时自动中断通知
CPU 被占用 100% ❌
精度低 ❌
不可移植 ❌
CPU 可做其他任务 ✅
精度高 ✅
通用性强 ✅

🎯 对比结论 :软件延时 → CPU 空转,精度低、浪费资源 。硬件定时器 → 硬件独立计时,CPU 释放、精度高、可移植。


1.3 知识对比表:软件延时 vs 硬件定时器

对比维度 软件延时(循环空转) 硬件定时器
CPU 占用 100% 占用,无法做其他事 启动后 CPU 空闲,到时才中断
精度 低(受编译器、CPU 频率影响) 高(由晶振频率决定)
可移植性 ❌ 不同平台需重新调参 ✅ 原理通用,只需改寄存器配置
功耗 高(CPU 一直在跑) 低(CPU 可以休眠)
实现复杂度 低(几行循环) 中(需配置寄存器)
典型场景 快速原型验证 所有需要精确延时的场景

第 2 章 · 定时器的硬件组成

2.1 核心概念

一句话总结:硬件定时器由"时钟源 → 分频器 → 计数器 → 通知机制"四部分组成,就像一条流水线。

生活类比:定时器就像一条"计时流水线"------时钟源是流水线的马达(提供动力节奏),分频器是减速齿轮(把马达转速调慢),计数器是计件工人(每来一个零件数一个数),通知机制是铃铛(数够了叮一声)。


2.2 定时器四大部分

#mermaid-svg-2ryCPEdHnyJAavQd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2ryCPEdHnyJAavQd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2ryCPEdHnyJAavQd .error-icon{fill:#552222;}#mermaid-svg-2ryCPEdHnyJAavQd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2ryCPEdHnyJAavQd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2ryCPEdHnyJAavQd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2ryCPEdHnyJAavQd .marker.cross{stroke:#333333;}#mermaid-svg-2ryCPEdHnyJAavQd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2ryCPEdHnyJAavQd p{margin:0;}#mermaid-svg-2ryCPEdHnyJAavQd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2ryCPEdHnyJAavQd .cluster-label text{fill:#333;}#mermaid-svg-2ryCPEdHnyJAavQd .cluster-label span{color:#333;}#mermaid-svg-2ryCPEdHnyJAavQd .cluster-label span p{background-color:transparent;}#mermaid-svg-2ryCPEdHnyJAavQd .label text,#mermaid-svg-2ryCPEdHnyJAavQd span{fill:#333;color:#333;}#mermaid-svg-2ryCPEdHnyJAavQd .node rect,#mermaid-svg-2ryCPEdHnyJAavQd .node circle,#mermaid-svg-2ryCPEdHnyJAavQd .node ellipse,#mermaid-svg-2ryCPEdHnyJAavQd .node polygon,#mermaid-svg-2ryCPEdHnyJAavQd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2ryCPEdHnyJAavQd .rough-node .label text,#mermaid-svg-2ryCPEdHnyJAavQd .node .label text,#mermaid-svg-2ryCPEdHnyJAavQd .image-shape .label,#mermaid-svg-2ryCPEdHnyJAavQd .icon-shape .label{text-anchor:middle;}#mermaid-svg-2ryCPEdHnyJAavQd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2ryCPEdHnyJAavQd .rough-node .label,#mermaid-svg-2ryCPEdHnyJAavQd .node .label,#mermaid-svg-2ryCPEdHnyJAavQd .image-shape .label,#mermaid-svg-2ryCPEdHnyJAavQd .icon-shape .label{text-align:center;}#mermaid-svg-2ryCPEdHnyJAavQd .node.clickable{cursor:pointer;}#mermaid-svg-2ryCPEdHnyJAavQd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2ryCPEdHnyJAavQd .arrowheadPath{fill:#333333;}#mermaid-svg-2ryCPEdHnyJAavQd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2ryCPEdHnyJAavQd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2ryCPEdHnyJAavQd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2ryCPEdHnyJAavQd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2ryCPEdHnyJAavQd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2ryCPEdHnyJAavQd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2ryCPEdHnyJAavQd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2ryCPEdHnyJAavQd .cluster text{fill:#333;}#mermaid-svg-2ryCPEdHnyJAavQd .cluster span{color:#333;}#mermaid-svg-2ryCPEdHnyJAavQd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2ryCPEdHnyJAavQd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2ryCPEdHnyJAavQd rect.text{fill:none;stroke-width:0;}#mermaid-svg-2ryCPEdHnyJAavQd .icon-shape,#mermaid-svg-2ryCPEdHnyJAavQd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2ryCPEdHnyJAavQd .icon-shape p,#mermaid-svg-2ryCPEdHnyJAavQd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2ryCPEdHnyJAavQd .icon-shape .label rect,#mermaid-svg-2ryCPEdHnyJAavQd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2ryCPEdHnyJAavQd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2ryCPEdHnyJAavQd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2ryCPEdHnyJAavQd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 定时器硬件组成
① 时钟源

晶振/系统时钟

提供基础频率
② 分频器

Prescaler

降低时钟频率
③ 计数器

Counter

递增/递减计数
④ 通知机制

中断 / GPIO
100 Hz → 周期 0.01s
÷ 10 → 10 Hz → 周期 0.1s
初始值 100 → 每 0.1s 减1

→ 10 秒后到 0
到 0 时触发中断

或 GPIO 翻转


2.3 时钟信号(Clock Signal)

一句话总结:时钟信号是数字电路的"心跳"------没有时钟,芯片就不工作。

生活类比:时钟信号就像音乐节拍器的"滴答声"------每一声滴答,电路就完成一个动作。节拍越快(频率越高),动作越快;节拍越慢,动作越慢。

频率与周期的关系

#mermaid-svg-qY8bEtx1zpL8znDV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qY8bEtx1zpL8znDV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qY8bEtx1zpL8znDV .error-icon{fill:#552222;}#mermaid-svg-qY8bEtx1zpL8znDV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qY8bEtx1zpL8znDV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qY8bEtx1zpL8znDV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qY8bEtx1zpL8znDV .marker.cross{stroke:#333333;}#mermaid-svg-qY8bEtx1zpL8znDV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qY8bEtx1zpL8znDV p{margin:0;}#mermaid-svg-qY8bEtx1zpL8znDV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qY8bEtx1zpL8znDV .cluster-label text{fill:#333;}#mermaid-svg-qY8bEtx1zpL8znDV .cluster-label span{color:#333;}#mermaid-svg-qY8bEtx1zpL8znDV .cluster-label span p{background-color:transparent;}#mermaid-svg-qY8bEtx1zpL8znDV .label text,#mermaid-svg-qY8bEtx1zpL8znDV span{fill:#333;color:#333;}#mermaid-svg-qY8bEtx1zpL8znDV .node rect,#mermaid-svg-qY8bEtx1zpL8znDV .node circle,#mermaid-svg-qY8bEtx1zpL8znDV .node ellipse,#mermaid-svg-qY8bEtx1zpL8znDV .node polygon,#mermaid-svg-qY8bEtx1zpL8znDV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qY8bEtx1zpL8znDV .rough-node .label text,#mermaid-svg-qY8bEtx1zpL8znDV .node .label text,#mermaid-svg-qY8bEtx1zpL8znDV .image-shape .label,#mermaid-svg-qY8bEtx1zpL8znDV .icon-shape .label{text-anchor:middle;}#mermaid-svg-qY8bEtx1zpL8znDV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qY8bEtx1zpL8znDV .rough-node .label,#mermaid-svg-qY8bEtx1zpL8znDV .node .label,#mermaid-svg-qY8bEtx1zpL8znDV .image-shape .label,#mermaid-svg-qY8bEtx1zpL8znDV .icon-shape .label{text-align:center;}#mermaid-svg-qY8bEtx1zpL8znDV .node.clickable{cursor:pointer;}#mermaid-svg-qY8bEtx1zpL8znDV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qY8bEtx1zpL8znDV .arrowheadPath{fill:#333333;}#mermaid-svg-qY8bEtx1zpL8znDV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qY8bEtx1zpL8znDV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qY8bEtx1zpL8znDV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qY8bEtx1zpL8znDV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qY8bEtx1zpL8znDV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qY8bEtx1zpL8znDV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qY8bEtx1zpL8znDV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qY8bEtx1zpL8znDV .cluster text{fill:#333;}#mermaid-svg-qY8bEtx1zpL8znDV .cluster span{color:#333;}#mermaid-svg-qY8bEtx1zpL8znDV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qY8bEtx1zpL8znDV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qY8bEtx1zpL8znDV rect.text{fill:none;stroke-width:0;}#mermaid-svg-qY8bEtx1zpL8znDV .icon-shape,#mermaid-svg-qY8bEtx1zpL8znDV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qY8bEtx1zpL8znDV .icon-shape p,#mermaid-svg-qY8bEtx1zpL8znDV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qY8bEtx1zpL8znDV .icon-shape .label rect,#mermaid-svg-qY8bEtx1zpL8znDV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qY8bEtx1zpL8znDV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qY8bEtx1zpL8znDV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qY8bEtx1zpL8znDV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 频率 → 周期
100 Hz
周期 = 1/100 = 0.01 秒

每 0.01 秒跳变一次
10 Hz
周期 = 1/10 = 0.1 秒

每 0.1 秒跳变一次
1 Hz
周期 = 1/1 = 1 秒

每 1 秒跳变一次

频率 含义 单个周期 典型用途
1 Hz 每秒 1 次电平跳变 1 秒 秒针计时
100 Hz 每秒 100 次电平跳变 0.01 秒(10 毫秒) 低精度定时器
1 KHz 每秒 1000 次电平跳变 0.001 秒(1 毫秒) 通用定时器
1 MHz 每秒 100 万次电平跳变 0.000001 秒(1 微秒) 高精度定时器

核心公式:周期(秒)= 1 ÷ 频率(Hz)


2.4 分频器(Prescaler)

一句话总结:分频器就像一个"减速齿轮"------把高速的时钟信号降速,让计数器能适应。

生活类比:汽车发动机转速很高(几千转/分钟),不能直接驱动车轮,需要变速箱(分频器)降速。同样,芯片的主频很高(MHz 级别),不能直接送给计数器,需要分频器降速到合适的频率。

分频计算示例

#mermaid-svg-WBCIvaQUsmXIUeFW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WBCIvaQUsmXIUeFW .error-icon{fill:#552222;}#mermaid-svg-WBCIvaQUsmXIUeFW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WBCIvaQUsmXIUeFW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WBCIvaQUsmXIUeFW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WBCIvaQUsmXIUeFW .marker.cross{stroke:#333333;}#mermaid-svg-WBCIvaQUsmXIUeFW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WBCIvaQUsmXIUeFW p{margin:0;}#mermaid-svg-WBCIvaQUsmXIUeFW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW .cluster-label text{fill:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW .cluster-label span{color:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW .cluster-label span p{background-color:transparent;}#mermaid-svg-WBCIvaQUsmXIUeFW .label text,#mermaid-svg-WBCIvaQUsmXIUeFW span{fill:#333;color:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW .node rect,#mermaid-svg-WBCIvaQUsmXIUeFW .node circle,#mermaid-svg-WBCIvaQUsmXIUeFW .node ellipse,#mermaid-svg-WBCIvaQUsmXIUeFW .node polygon,#mermaid-svg-WBCIvaQUsmXIUeFW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WBCIvaQUsmXIUeFW .rough-node .label text,#mermaid-svg-WBCIvaQUsmXIUeFW .node .label text,#mermaid-svg-WBCIvaQUsmXIUeFW .image-shape .label,#mermaid-svg-WBCIvaQUsmXIUeFW .icon-shape .label{text-anchor:middle;}#mermaid-svg-WBCIvaQUsmXIUeFW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WBCIvaQUsmXIUeFW .rough-node .label,#mermaid-svg-WBCIvaQUsmXIUeFW .node .label,#mermaid-svg-WBCIvaQUsmXIUeFW .image-shape .label,#mermaid-svg-WBCIvaQUsmXIUeFW .icon-shape .label{text-align:center;}#mermaid-svg-WBCIvaQUsmXIUeFW .node.clickable{cursor:pointer;}#mermaid-svg-WBCIvaQUsmXIUeFW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WBCIvaQUsmXIUeFW .arrowheadPath{fill:#333333;}#mermaid-svg-WBCIvaQUsmXIUeFW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WBCIvaQUsmXIUeFW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WBCIvaQUsmXIUeFW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WBCIvaQUsmXIUeFW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WBCIvaQUsmXIUeFW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WBCIvaQUsmXIUeFW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WBCIvaQUsmXIUeFW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WBCIvaQUsmXIUeFW .cluster text{fill:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW .cluster span{color:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WBCIvaQUsmXIUeFW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WBCIvaQUsmXIUeFW rect.text{fill:none;stroke-width:0;}#mermaid-svg-WBCIvaQUsmXIUeFW .icon-shape,#mermaid-svg-WBCIvaQUsmXIUeFW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WBCIvaQUsmXIUeFW .icon-shape p,#mermaid-svg-WBCIvaQUsmXIUeFW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WBCIvaQUsmXIUeFW .icon-shape .label rect,#mermaid-svg-WBCIvaQUsmXIUeFW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WBCIvaQUsmXIUeFW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WBCIvaQUsmXIUeFW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WBCIvaQUsmXIUeFW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 外部时钟

100 Hz

周期: 0.01s
分频器

÷ 10
定时器输入

10 Hz

周期: 0.1s
计数器

每 0.1s 减 1

计算过程:

  • 外部时钟频率:100 Hz(周期 0.01 秒)
  • 分频系数:10
  • 分频后频率:100 ÷ 10 = 10 Hz(周期 0.1 秒)
  • 计数器每 0.1 秒减 1

2.5 计数器(Counter)

一句话总结:计数器就像"倒计时秒表"------设定初值后,每个时钟周期减 1,减到 0 时定时完成。

生活类比:煮鸡蛋定时器------你设定 10 分钟(初始值),每过 1 分钟指针走一格(减 1),走到 0 时铃响(定时完成)。设定值越大,煮得越久。

计数器的递减过程

复制代码
初始值 = 10,每 0.1 秒减 1
时间轴:0s    0.1s   0.2s   0.3s   ...   0.9s   1.0s
计数值:10 →   9 →    8 →    7 →   ...   1 →    0(定时完成!)

定时时间计算公式

复制代码
定时时间 = 计数值 × 分频后的时钟周期
         = 计数值 × (分频系数 / 外部时钟频率)

示例计算:

外部时钟 分频系数 分频后周期 计数值 定时时间 应用场景
100 Hz 10 0.1 s 100 10 秒 慢速传感器采样
100 Hz 10 0.1 s 10 1 秒 LED 闪烁
100 Hz 10 0.1 s 1 0.1 秒 按键消抖
1 MHz 1000 0.001 s 1000 1 秒 通用场景
1 MHz 1000 0.001 s 1 1 毫秒 高速脉冲输出

#mermaid-svg-imSwnjeEM2Qv5Vub{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-imSwnjeEM2Qv5Vub .error-icon{fill:#552222;}#mermaid-svg-imSwnjeEM2Qv5Vub .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-imSwnjeEM2Qv5Vub .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-imSwnjeEM2Qv5Vub .marker{fill:#333333;stroke:#333333;}#mermaid-svg-imSwnjeEM2Qv5Vub .marker.cross{stroke:#333333;}#mermaid-svg-imSwnjeEM2Qv5Vub svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-imSwnjeEM2Qv5Vub p{margin:0;}#mermaid-svg-imSwnjeEM2Qv5Vub .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub .cluster-label text{fill:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub .cluster-label span{color:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub .cluster-label span p{background-color:transparent;}#mermaid-svg-imSwnjeEM2Qv5Vub .label text,#mermaid-svg-imSwnjeEM2Qv5Vub span{fill:#333;color:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub .node rect,#mermaid-svg-imSwnjeEM2Qv5Vub .node circle,#mermaid-svg-imSwnjeEM2Qv5Vub .node ellipse,#mermaid-svg-imSwnjeEM2Qv5Vub .node polygon,#mermaid-svg-imSwnjeEM2Qv5Vub .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-imSwnjeEM2Qv5Vub .rough-node .label text,#mermaid-svg-imSwnjeEM2Qv5Vub .node .label text,#mermaid-svg-imSwnjeEM2Qv5Vub .image-shape .label,#mermaid-svg-imSwnjeEM2Qv5Vub .icon-shape .label{text-anchor:middle;}#mermaid-svg-imSwnjeEM2Qv5Vub .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-imSwnjeEM2Qv5Vub .rough-node .label,#mermaid-svg-imSwnjeEM2Qv5Vub .node .label,#mermaid-svg-imSwnjeEM2Qv5Vub .image-shape .label,#mermaid-svg-imSwnjeEM2Qv5Vub .icon-shape .label{text-align:center;}#mermaid-svg-imSwnjeEM2Qv5Vub .node.clickable{cursor:pointer;}#mermaid-svg-imSwnjeEM2Qv5Vub .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-imSwnjeEM2Qv5Vub .arrowheadPath{fill:#333333;}#mermaid-svg-imSwnjeEM2Qv5Vub .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-imSwnjeEM2Qv5Vub .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-imSwnjeEM2Qv5Vub .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-imSwnjeEM2Qv5Vub .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-imSwnjeEM2Qv5Vub .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-imSwnjeEM2Qv5Vub .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-imSwnjeEM2Qv5Vub .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-imSwnjeEM2Qv5Vub .cluster text{fill:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub .cluster span{color:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-imSwnjeEM2Qv5Vub .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-imSwnjeEM2Qv5Vub rect.text{fill:none;stroke-width:0;}#mermaid-svg-imSwnjeEM2Qv5Vub .icon-shape,#mermaid-svg-imSwnjeEM2Qv5Vub .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-imSwnjeEM2Qv5Vub .icon-shape p,#mermaid-svg-imSwnjeEM2Qv5Vub .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-imSwnjeEM2Qv5Vub .icon-shape .label rect,#mermaid-svg-imSwnjeEM2Qv5Vub .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-imSwnjeEM2Qv5Vub .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-imSwnjeEM2Qv5Vub .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-imSwnjeEM2Qv5Vub :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 需要定时 T 秒
确定外部时钟频率 f_clk
选择分频系数 N
分频后周期 = N / f_clk
计数值 = T / 分频后周期
设置计数器初值 = 计数值

定时开始!

一句话总结 :固定时钟频率后,改计数值就能改定时时间------计数值越大,定时越长。


2.6 通知机制

一句话总结:定时器到点后通过"中断"或"GPIO 电平变化"通知 CPU------就像闹钟到点后响铃或亮灯。

方式一:中断通知


定时器(独立运行) CPU(正在执行主程序) 定时器(独立运行) CPU(正在执行主程序) #mermaid-svg-gim7jlC15b5UgjB3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gim7jlC15b5UgjB3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gim7jlC15b5UgjB3 .error-icon{fill:#552222;}#mermaid-svg-gim7jlC15b5UgjB3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gim7jlC15b5UgjB3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gim7jlC15b5UgjB3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gim7jlC15b5UgjB3 .marker.cross{stroke:#333333;}#mermaid-svg-gim7jlC15b5UgjB3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gim7jlC15b5UgjB3 p{margin:0;}#mermaid-svg-gim7jlC15b5UgjB3 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gim7jlC15b5UgjB3 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-gim7jlC15b5UgjB3 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gim7jlC15b5UgjB3 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-gim7jlC15b5UgjB3 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-gim7jlC15b5UgjB3 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-gim7jlC15b5UgjB3 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-gim7jlC15b5UgjB3 .sequenceNumber{fill:white;}#mermaid-svg-gim7jlC15b5UgjB3 #sequencenumber{fill:#333;}#mermaid-svg-gim7jlC15b5UgjB3 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-gim7jlC15b5UgjB3 .messageText{fill:#333;stroke:none;}#mermaid-svg-gim7jlC15b5UgjB3 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gim7jlC15b5UgjB3 .labelText,#mermaid-svg-gim7jlC15b5UgjB3 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-gim7jlC15b5UgjB3 .loopText,#mermaid-svg-gim7jlC15b5UgjB3 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-gim7jlC15b5UgjB3 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gim7jlC15b5UgjB3 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-gim7jlC15b5UgjB3 .noteText,#mermaid-svg-gim7jlC15b5UgjB3 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-gim7jlC15b5UgjB3 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gim7jlC15b5UgjB3 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gim7jlC15b5UgjB3 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gim7jlC15b5UgjB3 .actorPopupMenu{position:absolute;}#mermaid-svg-gim7jlC15b5UgjB3 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-gim7jlC15b5UgjB3 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gim7jlC15b5UgjB3 .actor-man circle,#mermaid-svg-gim7jlC15b5UgjB3 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-gim7jlC15b5UgjB3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 计数器递减中... CPU 暂停当前任务 10 → 9 → 8 → ... → 1 → 0 发出中断请求(IRQ) 跳转到中断服务函数 执行定时任务(如翻转 LED) 返回主程序继续执行

方式二:GPIO 电平变化

定时器状态 GPIO 引脚电平 外部设备看到的
正在倒计时 低电平(0V) 设备关闭
定时完成 高电平(3.3V) 设备开启/触发

这种方式不需要 CPU 参与,适合直接驱动外部设备(如触发 LED 亮灭、启动电机)。


2.7 知识对比表:中断 vs GPIO

对比维度 中断通知 GPIO 电平变化
CPU 参与 ✅ 需要 CPU 响应中断 ❌ CPU 完全不需要参与
灵活性 高(可在中断中执行任意代码) 低(只能输出电平变化)
实时性 受中断响应时间影响 即时(硬件直接输出)
实现复杂度 较高(需配置中断向量表) 简单(只需配置 GPIO)
典型场景 需要执行特定代码(如刷新显示) 直接驱动外部设备(如 LED 闪烁)

第 3 章 · 完整工作流程与代码示例

3.1 定时器工作全流程

#mermaid-svg-PkhXoZCGPB1JxdOj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PkhXoZCGPB1JxdOj .error-icon{fill:#552222;}#mermaid-svg-PkhXoZCGPB1JxdOj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PkhXoZCGPB1JxdOj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PkhXoZCGPB1JxdOj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PkhXoZCGPB1JxdOj .marker.cross{stroke:#333333;}#mermaid-svg-PkhXoZCGPB1JxdOj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PkhXoZCGPB1JxdOj p{margin:0;}#mermaid-svg-PkhXoZCGPB1JxdOj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj .cluster-label text{fill:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj .cluster-label span{color:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj .cluster-label span p{background-color:transparent;}#mermaid-svg-PkhXoZCGPB1JxdOj .label text,#mermaid-svg-PkhXoZCGPB1JxdOj span{fill:#333;color:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj .node rect,#mermaid-svg-PkhXoZCGPB1JxdOj .node circle,#mermaid-svg-PkhXoZCGPB1JxdOj .node ellipse,#mermaid-svg-PkhXoZCGPB1JxdOj .node polygon,#mermaid-svg-PkhXoZCGPB1JxdOj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PkhXoZCGPB1JxdOj .rough-node .label text,#mermaid-svg-PkhXoZCGPB1JxdOj .node .label text,#mermaid-svg-PkhXoZCGPB1JxdOj .image-shape .label,#mermaid-svg-PkhXoZCGPB1JxdOj .icon-shape .label{text-anchor:middle;}#mermaid-svg-PkhXoZCGPB1JxdOj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PkhXoZCGPB1JxdOj .rough-node .label,#mermaid-svg-PkhXoZCGPB1JxdOj .node .label,#mermaid-svg-PkhXoZCGPB1JxdOj .image-shape .label,#mermaid-svg-PkhXoZCGPB1JxdOj .icon-shape .label{text-align:center;}#mermaid-svg-PkhXoZCGPB1JxdOj .node.clickable{cursor:pointer;}#mermaid-svg-PkhXoZCGPB1JxdOj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PkhXoZCGPB1JxdOj .arrowheadPath{fill:#333333;}#mermaid-svg-PkhXoZCGPB1JxdOj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PkhXoZCGPB1JxdOj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PkhXoZCGPB1JxdOj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PkhXoZCGPB1JxdOj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PkhXoZCGPB1JxdOj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PkhXoZCGPB1JxdOj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PkhXoZCGPB1JxdOj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PkhXoZCGPB1JxdOj .cluster text{fill:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj .cluster span{color:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PkhXoZCGPB1JxdOj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PkhXoZCGPB1JxdOj rect.text{fill:none;stroke-width:0;}#mermaid-svg-PkhXoZCGPB1JxdOj .icon-shape,#mermaid-svg-PkhXoZCGPB1JxdOj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PkhXoZCGPB1JxdOj .icon-shape p,#mermaid-svg-PkhXoZCGPB1JxdOj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PkhXoZCGPB1JxdOj .icon-shape .label rect,#mermaid-svg-PkhXoZCGPB1JxdOj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PkhXoZCGPB1JxdOj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PkhXoZCGPB1JxdOj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PkhXoZCGPB1JxdOj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
系统上电
外部晶振产生时钟信号
时钟信号进入定时器模块
分频器降频
计数器开始递减
计数器是否

减到 0?
触发通知机制
发出中断请求
CPU 暂停当前任务
执行中断服务函数
返回主程序继续执行

3.2 经典示例:定时 1 秒让 LED 闪烁

需求分析

复制代码
外部时钟:72 MHz(STM32 典型值)
目标:每 1 秒翻转一次 LED

计算过程:
① 选择分频系数 7200 → 计数器频率 = 72 MHz / 7200 = 10 KHz
② 计数器周期 = 1 / 10 KHz = 0.0001 秒 = 0.1 毫秒
③ 要定时 1 秒,计数值 = 1 秒 / 0.0001 秒 = 10000

完整代码(STM32 裸机版)

cpp 复制代码
#include "stm32f10x.h"

// 定时器初始化:定时 1 秒
void Timer_Init(void) {
    // ① 使能定时器时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // ② 配置分频器和计数值
    // 72 MHz / 7200 = 10 KHz,周期 = 0.1 ms
    // 10000 × 0.1 ms = 1000 ms = 1 秒
    TIM_TimeBaseInitTypeDef tim;
    tim.TIM_Prescaler = 7200 - 1;      // 分频系数
    tim.TIM_Period    = 10000 - 1;     // 计数值
    tim.TIM_CounterMode = TIM_CounterMode_Down;  // 递减模式
    TIM_TimeBaseInit(TIM2, &tim);

    // ③ 使能中断
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    NVIC_EnableIRQ(TIM2_IRQn);

    // ④ 启动定时器
    TIM_Cmd(TIM2, ENABLE);
    // ★ 至此,CPU 可以去做其他任务了!
}

完整代码(ARM Linux 版)

在 Linux 系统中,应用程序不能直接操作硬件定时器寄存器(由内核管理),而是通过 Linux 提供的 timerfd API 来实现定时功能------内核帮你管理硬件定时器,你只需要读文件描述符就能知道定时是否到期。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/timerfd.h>   // timerfd 相关 API
#include <poll.h>           // poll 机制(类似中断的"通知")

int main(void) {
    // ① 创建定时器文件描述符
    // CLOCK_MONOTONIC:系统启动以来的单调时钟(不受系统时间调整影响)
    int timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (timer_fd == -1) {
        perror("timerfd_create");
        exit(1);
    }

    // ② 设置定时器参数
    struct itimerspec spec;
    spec.it_value.tv_sec = 1;      // 首次到期:1 秒后
    spec.it_value.tv_nsec = 0;
    spec.it_interval.tv_sec = 1;   // 之后每隔 1 秒触发一次(周期性)
    spec.it_interval.tv_nsec = 0;

    // ③ 启动定时器
    timerfd_settime(timer_fd, 0, &spec, NULL);
    printf("定时器已启动,每 1 秒到期一次\n");

    // ④ 主循环:用 poll 等待定时器到期(类似中断的"通知")
    struct pollfd pfd = { .fd = timer_fd, .events = POLLIN };

    while (1) {
        // poll 阻塞等待,直到定时器到期
        // 相当于:CPU 在做其他任务,定时器到期后"通知"poll 返回
        int ret = poll(&pfd, 1, -1);
        if (ret > 0 && (pfd.revents & POLLIN)) {
            // ★ 定时器到期!读取到期次数(消耗通知)
            uint64_t expirations;
            read(timer_fd, &expirations, sizeof(expirations));

            printf("1 秒到了!翻转 LED(实际开发中操作 GPIO)\n");
            // 在 ARM Linux 上操作 GPIO 可以通过:
            // - /sys/class/gpio 文件系统
            // - libgpiod 库
            // - 直接操作内存映射寄存器
        }

        // ★ CPU 在这里可以做其他事情!
        // 比如处理网络数据、用户输入等
        // process_network();
        // process_user_input();
    }

    close(timer_fd);
    return 0;
}

编译与运行:

bash 复制代码
# 在 ARM Linux(Ubuntu)上编译
gcc timer_example.c -o timer_example

# 运行
./timer_example
# 输出:
# 定时器已启动,每 1 秒到期一次
# 1 秒到了!翻转 LED(实际开发中操作 GPIO)
# 1 秒到了!翻转 LED(实际开发中操作 GPIO)
# ...(每 1 秒输出一次)

STM32 版 vs Linux 版对比

对比维度 STM32 裸机版 ARM Linux版
硬件操作 直接操作寄存器 通过内核 API(timerfd),不能直接操作硬件
定时器资源 芯片内部的硬件定时器(TIM2) 内核管理的通用定时器
通知方式 硬件中断(IRQ) poll/select/epoll 机制
分频/计数值 手动配置 PSC 和 ARR 寄存器 直接设置秒/纳秒(内核帮你算)
适用场景 裸机/RTOS,需要精确硬件控制 运行 Linux 的嵌入式系统(树莓派、ARM 开发板)
代码复杂度 需了解芯片手册 标准 POSIX API,更简洁

3.3 Linux 常用定时器库

除了内核提供的 timerfd,Linux 生态中有多个稳定且广泛使用的定时器库,适用于不同场景。

常用库一览

库名 语言 特点 适用场景 典型项目
timerfd C 内核原生 API,fd 风格 简单定时、事件循环整合 系统编程
libevent C 事件驱动,支持多种 IO 复用 网络服务 + 定时任务的混合场景 Nginx、Memcached、Transmission
libuv C 跨平台,Node.js 底层库 高性能异步 I/O + 定时器 Node.js、Luvit
Boost.Asio C++ C++ 标准风格,asio 模型 C++ 项目中的定时和网络 大量 C++ 后端服务
POSIX timer C timer_create 标准 API 信号驱动型定时 兼容性要求高的场景

libevent 示例(最广泛使用的定时器库)

libevent 是 Linux 下最广泛使用的网络事件库,内置高效的定时器管理。Nginx、Memcached、Transmission 等知名项目都使用它。

cpp 复制代码
#include <stdio.h>
#include <event2/event.h>

// 定时器回调函数(相当于"中断服务函数")
void timer_callback(evutil_socket_t fd, short what, void *arg) {
    // 参数 arg 可以传入自定义数据
    const char *msg = (const char *)arg;
    printf("1 秒到了!%s\n", msg);
    // 在实际项目中,这里可以操作 GPIO、发送数据等
}

int main(void) {
    // ① 创建 libevent 事件基础(相当于"初始化定时器硬件")
    struct event_base *base = event_base_new();
    if (!base) {
        fprintf(stderr, "无法创建 event_base\n");
        return 1;
    }

    // ② 创建定时器事件
    // 参数:base, fd=-1(不用fd), 超时类型, 回调函数, 回调参数
    struct event *timer = event_new(base, -1,
                                    EV_PERSIST,  // 周期性触发
                                    timer_callback,
                                    (void *)"LED 翻转");

    // ③ 设置定时时间:1 秒
    struct timeval interval = { .tv_sec = 1, .tv_usec = 0 };
    event_add(timer, &interval);
    // ★ 至此,事件循环会自动管理定时器,无需手动维护

    printf("libevent 定时器已启动,每 1 秒触发一次\n");

    // ④ 进入事件循环(相当于 CPU 开始执行其他任务)
    // libevent 内部使用 epoll 监听事件,定时器到点后自动回调
    event_base_dispatch(base);

    // 清理
    event_free(timer);
    event_base_free(base);
    return 0;
}

编译与运行:

bash 复制代码
# 安装 libevent
sudo apt install libevent-dev

# 编译
gcc timer_libevent.c -o timer_libevent -levent

# 运行
./timer_libevent
# 输出:
# libevent 定时器已启动,每 1 秒触发一次
# 1 秒到了!LED 翻转
# 1 秒到了!LED 翻转
# ...(每 1 秒输出一次)

Boost.Asio 示例(C++ 项目首选)

cpp 复制代码
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>

void timer_callback(const boost::system::error_code& /*e*/,
                    boost::asio::steady_timer* t, int* count) {
    if (*count < 5) {
        std::cout << "1 秒到了!第 " << *count + 1 << " 次" << std::endl;
        ++(*count);

        // 重置定时器,开始下一次 1 秒计时
        t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
        t->async_wait(boost::bind(timer_callback,
                                  boost::asio::placeholders::error, t, count));
    }
}

int main(void) {
    boost::asio::io_context io;  // 相当于 event_base

    int count = 0;
    boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));

    // 异步等待,定时到点后回调 timer_callback
    t.async_wait(boost::bind(timer_callback,
                             boost::asio::placeholders::error, &t, &count));

    std::cout << "Boost.Asio 定时器已启动" << std::endl;

    // 进入事件循环
    io.run();

    std::cout << "定时器执行完毕" << std::endl;
    return 0;
}

编译与运行:

bash 复制代码
# 安装 Boost
sudo apt install libboost-all-dev

# 编译
g++ timer_boost.cpp -o timer_boost -lboost_system -lpthread

# 运行
./timer_boost
# 输出:
# Boost.Asio 定时器已启动
# 1 秒到了!第 1 次
# 1 秒到了!第 2 次
# ...(共 5 次后退出)

三种方式的对比

对比维度 timerfd(内核 API) libevent Boost.Asio
语言 C C C++
依赖 无(内核内置) 需安装 libevent-dev 需安装 libboost-all-dev
学习曲线 低 中 中高
功能范围 仅定时器 定时器+网络IO+信号 定时器+网络+文件+线程
事件循环 需自己实现(poll) 内置 event_base_dispatch 内置 io_context.run()
生产使用 系统级工具 Nginx、Memcached、Redis 大量 C++ 后端服务
推荐场景 简单定时任务 需要同时处理网络IO C++ 项目,需要完整异步框架

3.3 知识对比表:递减模式 vs 递增模式

对比维度 递减模式(Down) 递增模式(Up)
工作方式 从初值减到 0 从 0 加到初值
定时时长 初值 × 时钟周期 初值 × 时钟周期
典型应用 单次定时(One-shot) 周期性定时(Periodic)
实现直观性 更直观(像倒计时) 符合计数习惯

第 4 章 · 面试高频问答

Q1:定时时间怎么计算?

复制代码
定时时间 = 计数值 × (分频系数 / 外部时钟频率)

示例:外部时钟 1 MHz,分频系数 1000,计数值 1000

复制代码
分频后频率 = 1 MHz / 1000 = 1 KHz
分频后周期 = 1 / 1 KHz = 1 ms
定时时间 = 1000 × 1 ms = 1 秒

Q2:分频器的作用是什么?

把高频时钟降低到合适的频率,让计数器能在合理的时间范围内工作。

举例:1 MHz 时钟直接给 16 位计数器(最大 65535)

  • 不分频:最大定时 = 65535 × 1 µs = 65.5 毫秒
  • 分频 1000:最大定时 = 65535 × 1 ms = 65.5 秒

分频让定时范围从毫秒级扩展到了分钟级。

Q3:中断和轮询有什么区别?

#mermaid-svg-6vHywXkAKgmgMyMT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6vHywXkAKgmgMyMT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6vHywXkAKgmgMyMT .error-icon{fill:#552222;}#mermaid-svg-6vHywXkAKgmgMyMT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6vHywXkAKgmgMyMT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6vHywXkAKgmgMyMT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6vHywXkAKgmgMyMT .marker.cross{stroke:#333333;}#mermaid-svg-6vHywXkAKgmgMyMT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6vHywXkAKgmgMyMT p{margin:0;}#mermaid-svg-6vHywXkAKgmgMyMT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6vHywXkAKgmgMyMT .cluster-label text{fill:#333;}#mermaid-svg-6vHywXkAKgmgMyMT .cluster-label span{color:#333;}#mermaid-svg-6vHywXkAKgmgMyMT .cluster-label span p{background-color:transparent;}#mermaid-svg-6vHywXkAKgmgMyMT .label text,#mermaid-svg-6vHywXkAKgmgMyMT span{fill:#333;color:#333;}#mermaid-svg-6vHywXkAKgmgMyMT .node rect,#mermaid-svg-6vHywXkAKgmgMyMT .node circle,#mermaid-svg-6vHywXkAKgmgMyMT .node ellipse,#mermaid-svg-6vHywXkAKgmgMyMT .node polygon,#mermaid-svg-6vHywXkAKgmgMyMT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6vHywXkAKgmgMyMT .rough-node .label text,#mermaid-svg-6vHywXkAKgmgMyMT .node .label text,#mermaid-svg-6vHywXkAKgmgMyMT .image-shape .label,#mermaid-svg-6vHywXkAKgmgMyMT .icon-shape .label{text-anchor:middle;}#mermaid-svg-6vHywXkAKgmgMyMT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6vHywXkAKgmgMyMT .rough-node .label,#mermaid-svg-6vHywXkAKgmgMyMT .node .label,#mermaid-svg-6vHywXkAKgmgMyMT .image-shape .label,#mermaid-svg-6vHywXkAKgmgMyMT .icon-shape .label{text-align:center;}#mermaid-svg-6vHywXkAKgmgMyMT .node.clickable{cursor:pointer;}#mermaid-svg-6vHywXkAKgmgMyMT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6vHywXkAKgmgMyMT .arrowheadPath{fill:#333333;}#mermaid-svg-6vHywXkAKgmgMyMT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6vHywXkAKgmgMyMT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6vHywXkAKgmgMyMT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6vHywXkAKgmgMyMT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6vHywXkAKgmgMyMT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6vHywXkAKgmgMyMT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6vHywXkAKgmgMyMT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6vHywXkAKgmgMyMT .cluster text{fill:#333;}#mermaid-svg-6vHywXkAKgmgMyMT .cluster span{color:#333;}#mermaid-svg-6vHywXkAKgmgMyMT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6vHywXkAKgmgMyMT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6vHywXkAKgmgMyMT rect.text{fill:none;stroke-width:0;}#mermaid-svg-6vHywXkAKgmgMyMT .icon-shape,#mermaid-svg-6vHywXkAKgmgMyMT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6vHywXkAKgmgMyMT .icon-shape p,#mermaid-svg-6vHywXkAKgmgMyMT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6vHywXkAKgmgMyMT .icon-shape .label rect,#mermaid-svg-6vHywXkAKgmgMyMT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6vHywXkAKgmgMyMT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6vHywXkAKgmgMyMT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6vHywXkAKgmgMyMT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ❌ 轮询
✅ 中断
需要知道定时器是否完成
用什么方式监控?
CPU 不断检查标志位

while(!flag){}
定时器到时自动通知

CPU 做其他事
CPU 被占用 ❌
实时性差 ❌
实现简单 ✅
CPU 可做其他任务 ✅
实时性好 ✅
实现稍复杂

对比维度 中断 轮询
CPU 工作方式 定时器计时,CPU 做别的事 CPU 不断检查标志位
效率 高(CPU 不被浪费) 低(CPU 被占用检查)
实时性 好(立即响应) 差(取决于何时检查)
实现复杂度 较高(需配置中断向量) 简单(只需读寄存器)

附录 · 核心概念速查

概念 一句话总结 生活类比 核心公式
时钟信号 芯片的"心跳",决定工作节奏 音乐节拍器的滴答声 ---
频率(Hz) 每秒振动的次数 每秒钟眨眼的次数 周期 = 1/频率
分频器 降速齿轮,把高频变低频 汽车的变速箱 输出频率 = 输入频率 / 分频系数
计数器 倒计时器,每来一个时钟减 1 煮鸡蛋定时器 ---
计数值 倒计时起点,越大定时越长 闹钟设定的分钟数 定时时间 = 计数值 × 时钟周期
中断 定时到点后通知 CPU 来干活 烤箱到点后"叮"一声 ---
GPIO 输出 定时到点后直接输出电平变化 红绿灯自动切换 ---

一句话总结:定时器 = 外部时钟 → 分频 → 计数 → 通知------固定频率 + 修改计数值 = 精确控制延时时间。记住这条流水线,所有定时器都万变不离其宗。

相关推荐
逐光者9332 分钟前
STM32通信协议——I2C
stm32·单片机·嵌入式硬件
千秋岁rr4 分钟前
15.PWR电源控制
单片机·嵌入式硬件
额额额对了11 分钟前
嵌入式 Linux 启动程序文件
开发语言·嵌入式硬件·php
夏虫不可与之言冰24 分钟前
Windows WSL2 (Ubuntu) 搭建 ESP‑IDF 6.1 开发环境全过程演示
linux·windows·ubuntu·esp32·乐鑫科技·乐鑫eim·乐鑫代理商
甜甜的大香瓜38 分钟前
【MT32F006】MT32F006之PWM控制背光灯(白光)
单片机
李日华大战鸡红39 分钟前
FOC SVPWM过调制(学习记录)
stm32·单片机·学习
独孤九剑打醒他1 小时前
【原创开源·修订版】源-栅-漏-栅-源横向双栅MOS:从“被误解的短路”到“电流路径多值逻辑与顶层供电架构”
前端·嵌入式硬件·架构·开源·硬件工程
千里马021 小时前
STM32读取AD7606-4(HAL库)
stm32·单片机·嵌入式硬件
春涧草茶1 小时前
慢就是快12-12手动抛出异常
java·linux·前端
weixin_464078072 小时前
电路中补偿器的作用
嵌入式硬件