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

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

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


第 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 输出 定时到点后直接输出电平变化 红绿灯自动切换 ---

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

相关推荐
国服第二切图仔1 小时前
05-构建与特性开关
linux·服务器·ubuntu
2401_827501281 小时前
51单片机(四)DS18B20 数字温度传感器
c语言·51单片机
Thecozzy1 小时前
Skill和MCP和Subagent 的选择
linux·人工智能·ubuntu
2401_827501281 小时前
51单片机(三)串口通信(UART)、Modbus协议
单片机·嵌入式硬件·51单片机
振浩微433射频芯片2 小时前
5个IO控制20个LED?查理复用实战拆解
网络·单片机·物联网·学习·智能家居
硬核子牙2 小时前
代码展示大模型的智能
linux·chatgpt·agent
风曦Kisaki2 小时前
# Linux 系统资源查看命令总结(附命令快查表)
linux·运维·服务器
清水白石0083 小时前
Python 类定义阶段自动注册子类:从 `__init_subclass__` 到插件系统实战
linux·前端·python
2601_958352903 小时前
从智能安防到矿山预警:AR1105声源定位模组的行业应用与架构解析
人工智能·嵌入式硬件·架构·机器人·回音消除·声源定位