单片机程序设计中的定时器和计数器:精准控制时间和事件
发布时间: 2024-07-06 11:49:01 阅读量: 51 订阅数: 23
![单片机程序设计中的定时器和计数器:精准控制时间和事件](https://img-blog.csdnimg.cn/direct/3a71056fa2694cd7bb85076473db5937.png)
# 1. 单片机定时器和计数器的概述**
**1.1 定时器和计数器的概念**
定时器和计数器是单片机中重要的外设,它们可以对时间和事件进行测量和控制。定时器可以产生精确的时钟信号,而计数器可以记录事件发生的次数。
**1.2 定时器和计数器的功能**
定时器和计数器具有多种功能,包括:
* **时间测量和控制:**可以测量时间间隔、生成延时和调度周期性任务。
* **事件计数和处理:**可以计数外部事件的发生次数,并根据计数结果触发中断或执行特定操作。
* **时钟发生器:**可以产生内部或外部时钟信号,为单片机和其他外设提供时基。
* **波形发生器:**可以生成各种波形,如方波、三角波等。
# 2. 定时器编程技巧
### 2.1 定时器中断服务程序
#### 2.1.1 中断处理流程
当定时器溢出或比较匹配时,会产生中断请求。中断服务程序(ISR)将被调用来处理中断。ISR 的典型流程如下:
1. **保存寄存器:**保存 ISR 执行前 CPU 寄存器的值,以备 ISR 执行结束后恢复。
2. **清除中断标志:**清除定时器溢出或比较匹配中断标志,以防止中断重复触发。
3. **执行中断处理:**执行中断处理代码,例如更新变量、设置标志或触发其他事件。
4. **恢复寄存器:**恢复 ISR 执行前保存的寄存器值。
5. **退出 ISR:**执行 `reti` 指令退出 ISR,返回到中断发生前的代码。
#### 2.1.2 中断优先级设置
大多数单片机支持中断优先级设置,允许为不同的中断源分配不同的优先级。当多个中断同时发生时,具有更高优先级的中断将被优先处理。中断优先级通常通过寄存器或配置位进行设置。
### 2.2 定时器模式选择
定时器可以配置为不同的模式,以满足不同的应用需求。常见的定时器模式包括:
#### 2.2.1 捕获模式
捕获模式允许定时器捕获外部事件的发生时间。当外部事件发生时,定时器会将当前计数值存储到一个捕获寄存器中。捕获模式常用于测量脉冲宽度或频率。
#### 2.2.2 比较模式
比较模式允许定时器在达到预设的比较值时产生中断或输出信号。当定时器计数值与比较值匹配时,定时器会触发中断或输出一个脉冲。比较模式常用于生成周期性波形或测量时间间隔。
#### 2.2.3 PWM 模式
PWM(脉冲宽度调制)模式允许定时器生成可变占空比的脉冲波形。通过改变定时器比较值,可以控制脉冲的宽度。PWM 模式常用于控制电机速度、调光或生成音频信号。
**代码示例:**
```c
// 定时器 0 捕获模式配置
TCCR0A |= (1 << WGM01); // 设置为 CTC 模式
TCCR0B |= (1 << CS01); // 设置为分频 8
OCR0A = 255; // 设置比较值
// 定时器 1 比较模式配置
TCCR1A |= (1 << WGM12); // 设置为 CTC 模式
TCCR1B |= (1 << CS11); // 设置为分频 8
OCR1A = 65535; // 设置比较值
// 定时器 2 PWM 模式配置
TCCR2A |= (1 << WGM21) | (1 << WGM20); // 设置为 Fast PWM 模式
TCCR2B |= (1 << CS21); // 设置为分频 8
OCR2A = 255; // 设置比较值
```
**逻辑分析:**
* **捕获模式:**定时器 0 配置为 CTC 模式,分频为 8。当外部事件发生时,定时器计数值将被捕获到 OCR0A 寄存器中。
* **比较模式:**定时器 1 配置为 CTC 模式,分频为 8。当定时器计数值达到 OCR1A 寄存器中的比较值时,定时器将触发中断。
* **PWM 模式:**定时器 2 配置为 Fast PWM 模式,分频为 8。OCR2A 寄存器中的比较值控制脉冲的宽度。
# 3. 计数器编程技巧
### 3.1 计数器中断服务程序
计数器中断服务程序(ISR)是当计数器达到预设值时执行的代码块。它用于响应计数器事件,例如溢出或比较匹配。
#### 3.1.1 计数器溢出中断
计数器溢出中断发生在计数器达到其最大值并从 0 重新开始时。此中断可用于创建延时函数或周期性任务调度。
#### 3.1.2 计数器比较中断
计数器比较中断发生在计数器值与预设比较值匹配时。此中断可用于测量脉冲宽度或频率。
### 3.2 计数器模式选择
计数器模式决定了计数器如何响应外部事件。有三种主要模式:
#### 3.2.1 上升沿计数模式
此模式下,计数器仅在外部信号上升沿时递增。
#### 3.2.2 下降沿计数模式
此模式下,计数器仅在外部信号下降沿时递增。
#### 3.2.3 双沿计数模式
此模式下,计数器在外部信号的上升沿和下降沿都递增。
### 代码示例
以下代码展示了如何使用计数器溢出中断创建延时函数:
```c
#include <avr/io.h>
#include <util/delay.h>
// 延时 100ms
void delay_100ms() {
// 设置计数器为溢出模式
TCCR1B |= (1 << WGM12);
// 设置溢出比较值
OCR1A = 15624;
// 启用计数器溢出中断
TIMSK1 |= (1 << TOIE1);
// 等待溢出中断发生
while (!(TIFR1 & (1 << TOV1)));
// 清除溢出标志
TIFR1 |= (1 << TOV1);
}
int main() {
// 初始化计数器
TCCR1B |= (1 << CS10); // 使用内部时钟
// 调用延时函数
delay_100ms();
return 0;
}
```
### 逻辑分析
此代码使用 AVR 单片机的 16 位定时器 1。它将定时器配置为溢出模式,并在溢出比较值寄存器 (OCR1A) 中设置溢出比较值。当计数器达到溢出比较值时,将触发溢出中断。中断服务程序清除溢出标志,从而允许计数器重新开始计数。
### 参数说明
* `TCCR1B`:定时器 1 控制寄存器 B,用于设置时钟源和计数模式。
* `WGM12`:溢出模式位,设置为 1 以启用溢出模式。
* `OCR1A`:溢出比较值寄存器,用于设置溢出比较值。
* `TIMSK1`:定时器 1 中断屏蔽寄存器,用于启用或禁用中断。
* `TOIE1`:溢出中断使能位,设置为 1 以启用溢出中断。
* `TIFR1`:定时器 1 中断标志寄存器,用于清除中断标志。
* `TOV1`:
0
0