单片机中的定时器输入捕捉应用案例

碧海潮生 2020-12-11 ⋅ 16 阅读

一、什么是定时器输入捕捉?

定时器输入捕捉是指利用单片机的定时器模块来捕捉外部信号的状态变化,并在捕捉到信号边沿后进行相应的处理操作。通常用于测量外部脉冲信号的频率、脉宽等。

二、定时器输入捕捉的基本原理

定时器输入捕捉基于定时器的计数功能和外部引脚的输入功能。在定时器输入捕捉模式下,当定时器接收到外部信号的边沿触发时,会记录下当前定时器的计数值,并可以根据需要进行进一步的处理。

三、定时器输入捕捉的应用案例

1. 测量脉冲信号的频率

假设我们需要测量一个外部信号的频率,比如一个开关的闪烁频率。我们可以利用定时器输入捕捉功能来实现。

具体的步骤如下:

(1)配置定时器的输入捕捉模式,选择合适的边沿触发方式。

(2)在定时器中断服务函数中统计捕捉到的脉冲数量。

(3)根据捕捉到的脉冲数量和定时器的周期计算出频率。

代码示例:

#define CAPTURE_PIN P2     	// 外部信号的引脚
#define TIMER1_CAP  1      	// 使用定时器1的输入捕捉功能

void Init_Timer1_InputCapture()
{
    TMOD |= (1 << TIMER1_CAP); 	// 配置定时器1的输入捕捉模式
    TCON |= (1 << T1_GATE);    	// 允许通过对外部引脚INT1的触发进行输入捕捉
    
    EA = 1;                    	// 允许全局中断
    ET1 = 1;                   	// 允许定时器1中断
    EX1 = 1;                   	// 允许INT1中断
}

unsigned int pulseCount = 0;		// 记录捕捉到的脉冲数量

void Timer1_InputCapture() interrupt 3
{
    if (TF1)
    {
        pulseCount++;           // 每次溢出,说明脉冲周期已经超过定时器的计数范围,可以增加脉冲数量计数
        TF1 = 0;                // 清除定时器1的溢出标志
    }
}

void main()
{
    Init_Timer1_InputCapture();	// 初始化定时器1输入捕捉功能
    
    while(1)
    {
        // TODO: 其他代码
        
        // 计算频率
        unsigned long frequency = pulseCount * TIMER1_PERIOD;	// TIMER1_PERIOD为定时器的周期
        pulseCount = 0;		// 重置脉冲数量,准备下一次计数
    }
}

2. 测量脉冲信号的脉宽

类似地,我们也可以利用定时器输入捕捉来测量脉冲信号的脉宽。

具体步骤如下:

(1)配置定时器的输入捕捉模式,选择合适的边沿触发方式。

(2)在定时器中断服务函数中记录捕捉到的边沿的时间戳。

(3)根据两个边沿的时间戳差值和定时器的频率计算出脉宽。

代码示例:

#define CAPTURE_PIN P2     	// 外部信号的引脚
#define TIMER1_CAP  1      	// 使用定时器1的输入捕捉功能

void Init_Timer1_InputCapture()
{
    TMOD |= (1 << TIMER1_CAP); 	// 配置定时器1的输入捕捉模式
    TCON |= (1 << T1_GATE);    	// 允许通过对外部引脚INT1的触发进行输入捕捉
    
    EA = 1;                    	// 允许全局中断
    ET1 = 1;                   	// 允许定时器1中断
    EX1 = 1;                   	// 允许INT1中断
}

unsigned int risingEdgeTime = 0;   	// 记录上升沿的时间戳
unsigned int fallingEdgeTime = 0;	// 记录下降沿的时间戳

void Timer1_InputCapture() interrupt 3
{
    if (TF1)
    {
        risingEdgeTime = fallingEdgeTime = 0;   // 定时器溢出时,表示没有信号输入
        TF1 = 0;                        // 清除定时器1的溢出标志
    }
    
    if (INT1 == 0)  // 下降沿触发
    {
        fallingEdgeTime = TH1 * 256 + TL1;	// 记录下降沿的时间戳
    }
    else            // 上升沿触发
    {
        risingEdgeTime = TH1 * 256 + TL1;	// 记录上升沿的时间戳
    }
}

void main()
{
    Init_Timer1_InputCapture();	// 初始化定时器1输入捕捉功能
    
    while(1)
    {
        // TODO: 其他代码
        
        if (risingEdgeTime != 0 && fallingEdgeTime != 0)
        {
            unsigned int pulseWidth = fallingEdgeTime - risingEdgeTime;	// 脉冲宽度
            risingEdgeTime = 0;		// 清除时间戳,等待下一次捕捉
            fallingEdgeTime = 0;
        }
    }
}

四、总结

通过定时器的输入捕捉功能,我们可以方便地应用于各种需要测量外部信号频率、脉宽等的场景中。同时,根据不同的需求和定时器的功能,可以实现更多的应用,比如输入捕捉用于编码器的计数等。

以上案例只是定时器输入捕捉功能在单片机中的一种应用,希望能对你理解单片机定时器的输入捕捉功能有所帮助。


全部评论: 0

    我有话说: