打印
[其它应用]

定时器/计数器的工作原理

[复制链接]
125|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-12-4 13:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单片机中的定时器/计数器(Timer/Counter)是用于时间测量和事件计数的重要模块。它们可以用来生成精确的延时、测量外部信号的频率或周期、捕获外部事件的时间戳等。理解定时器/计数器的工作原理对于单片机编程和系统设计非常重要。以下是定时器/计数器的基本工作原理和常见功能的详细介绍:

1. 定时器/计数器的基本概念
1.1 定时器(Timer)
功能:用于生成精确的时间延迟。
工作原理:定时器通过内部时钟源(通常是单片机的系统时钟)进行递增计数,达到设定值后产生中断或触发特定事件。
1.2 计数器(Counter)
功能:用于对外部事件进行计数。
工作原理:计数器通过外部输入信号进行递增计数,达到设定值后产生中断或触发特定事件。
2. 定时器/计数器的结构
2.1 计数寄存器(Counter Register)
功能:存储当前的计数值。
位宽:常见的位宽有8位、16位和32位。
2.2 预分频器(Prescaler)
功能:对输入时钟进行分频,降低计数频率。
作用:增加定时器/计数器的范围和分辨率。
2.3 模寄存器(Mode Register)
功能:设置定时器/计数器的工作模式。
常见模式:
定时器模式:内部时钟源计数。
计数器模式:外部时钟源计数。
自动重装载模式:计数器达到设定值后自动重新加载初始值。
捕捉模式:捕获外部事件的时间戳。
比较模式:比较计数值和预设值,匹配时产生中断。
2.4 控制寄存器(Control Register)
功能:控制定时器/计数器的启停、中断使能等。
位设置:
启动位:控制定时器/计数器的启停。
中断使能位:控制是否产生中断。
工作模式位:设置定时器/计数器的工作模式。
3. 定时器/计数器的工作原理
3.1 定时器模式
工作过程:
初始化:设置定时器的工作模式、初始值和中断使能。
启动:通过控制寄存器启动定时器。
计数:定时器根据内部时钟源递增计数。
比较:当计数值达到设定值时,产生中断或触发特定事件。
重载:如果是自动重装载模式,计数器自动重新加载初始值,继续计数。
3.2 计数器模式
工作过程:
初始化:设置计数器的工作模式、初始值和中断使能。
启动:通过控制寄存器启动计数器。
计数:计数器根据外部输入信号递增计数。
比较:当计数值达到设定值时,产生中断或触发特定事件。
重载:如果是自动重装载模式,计数器自动重新加载初始值,继续计数。
4. 定时器/计数器的配置
4.1 设置工作模式
示例代码(C语言,假设使用8051单片机):
// 设置定时器0为模式1(16位定时器)
TMOD = 0x01;  // 设置定时器0的工作模式
TH0 = 0xFC;   // 设置高8位初始值
TL0 = 0x18;   // 设置低8位初始值
TR0 = 1;      // 启动定时器0
ET0 = 1;      // 使能定时器0中断
EA = 1;       // 使能全局中断
4.2 设置预分频器
示例代码(C语言,假设使用STM32单片机):
// 设置定时器2的预分频器
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 9999;   // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 预分频器值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_Cmd(TIM2, ENABLE); // 启动定时器2
4.3 中断处理
示例代码(C语言,假设使用8051单片机):
void Timer0_ISR() interrupt 1 {
    // 清除定时器0中断标志
    TF0 = 0;
    // 执行中断服务程序
    // ...
}

void main() {
    // 初始化定时器0
    TMOD = 0x01;  // 设置定时器0为模式1
    TH0 = 0xFC;   // 设置高8位初始值
    TL0 = 0x18;   // 设置低8位初始值
    TR0 = 1;      // 启动定时器0
    ET0 = 1;      // 使能定时器0中断
    EA = 1;       // 使能全局中断

    while (1) {
        // 主程序循环
    }
}

5. 实际应用示例
5.1 定时器生成延时
示例代码(C语言,假设使用8051单片机):
#include <8051.h>

void Timer0_ISR() interrupt 1 {
    static unsigned int count = 0;
    TF0 = 0;  // 清除定时器0中断标志
    count++;
    if (count >= 1000) {  // 延时1秒
        count = 0;
        // 执行延时后的操作
    }
}

void main() {
    TMOD = 0x01;  // 设置定时器0为模式1
    TH0 = 0xFC;   // 设置高8位初始值
    TL0 = 0x18;   // 设置低8位初始值
    TR0 = 1;      // 启动定时器0
    ET0 = 1;      // 使能定时器0中断
    EA = 1;       // 使能全局中断

    while (1) {
        // 主程序循环
    }
}

5.2 计数器测量外部信号频率
示例代码(C语言,假设使用STM32单片机):
#include "stm32f10x.h"

void TIM2_Config(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能TIM2和GPIOA的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 配置PA0为输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  // 上拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置TIM2
    TIM_TimeBaseStructure.TIM_Period = 65535;  // 自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 预分频器值
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    // 配置TIM2的输入捕获通道
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x00;
    TIM_ICInit(TIM2, &TIM_ICInitStructure);

    // 使能TIM2的中断
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    // 配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 启动TIM2
    TIM_Cmd(TIM2, ENABLE);
}

void TIM2_IRQHandler(void) {
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        // 清除中断标志
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        // 执行中断服务程序
        // ...
    }
}

int main(void) {
    TIM2_Config();
    while (1) {
        // 主程序循环
    }
}

总结
定时器/计数器是单片机中非常重要的模块,通过合理配置和使用,可以实现多种时间测量和事件计数功能。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_42300449/article/details/143835480

使用特权

评论回复
沙发
咕咕呱呱孤寡| | 2024-12-4 13:52 | 只看该作者
感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1981

主题

15794

帖子

12

粉丝