在嵌入式系统中,定时器(Timer)是一种极其重要的外设,用于实现延时、计数和事件调度。本文将深入探讨 PIC16F1719 微控制器中的 Timer2,涵盖其配置方法、应用实例以及常见问题的解决方案。
Timer2 是一个 8 位的定时器,与其他定时器相比,它具有一些独特的特性。它可以通过外部晶振(通常是内部时钟源)产生精确的时间延迟,广泛用于生成PWM信号和定时中断。
在 PIC16F1719 中配置 Timer2 包括设置预分频器、周期寄存器和后分频器。下面的代码展示了如何配置 Timer2:
c// 设置预分频器为 16
T2CONbits.T2CKPS = 0b10;
// 设置周期寄存器 PR2 为 255
PR2 = 255;
// 设置 Timer2 初始值为 0
TMR2 = 0;
// 设置后分频器为 15
T2CONbits.T2OUTPS = 0b1110;
// 启动 Timer2
T2CONbits.TMR2ON = 1;
// 启用 Timer2 中断
PIE1bits.TMR2IE = 1;
// 启用外设中断
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
在使用 Timer2 时,我们通常需要利用其产生的中断来执行周期性任务。中断服务例程(ISR)是处理这些定时中断的地方。以下是一个简单的 ISR 示例,它每秒钟切换 LED 状态:
cvoid __interrupt() isr(void){
static unsigned char count = 0;
if (PIR1bits.TMR2IF) {
PIR1bits.TMR2IF = 0; // 清除 Timer2 中断标志位
count++;
if (count >= 122) { // 调整计数值以匹配所需的时间间隔
count = 0;
LATDbits.LATD1 ^= 1; // 切换 LED 状态
}
}
}
LED 不闪烁:如果你的 LED 不闪烁,首先检查 Timer2 的配置是否正确。确认预分频器和后分频器的设置符合需求,同时确保中断服务例程能够正确处理 Timer2 中断。
中断未触发:确保 Timer2 中断已启用,且全局和外设中断已开启。检查 PIE1bits.TMR2IE
和 INTCONbits.GIE
的设置是否正确。
计数器周期不符:调整 PR2 寄存器和后分频器值,确保 Timer2 的周期与实际需求相符。通过计算公式验证设置是否符合预期。
c/* PIC16F1719 配置位设置 */
#pragma config FOSC = INTOSC /* 振荡器选择位 (INTOSC 振荡器: CLKIN 引脚上的 I/O 功能) */
#pragma config WDTE = OFF /* 看门狗定时器使能 (WDT 禁用) */
#pragma config PWRTE = OFF /* 上电定时器使能 (PWRT 禁用) */
#pragma config MCLRE = ON /* MCLR 引脚功能选择 (MCLR/VPP 引脚功能为 MCLR) */
#pragma config CP = OFF /* 闪存程序存储器代码保护 (程序存储器代码保护禁用) */
#pragma config BOREN = OFF /* 低电压复位使能 (低电压复位禁用) */
#pragma config CLKOUTEN = OFF /* 时钟输出使能 (CLKOUT 功能禁用。CLKOUT 引脚上的 I/O 或振荡器功能) */
#pragma config IESO = ON /* 内外部切换模式 (内外部切换模式使能) */
#pragma config FCMEN = ON /* 故障安全时钟监控器使能 (故障安全时钟监控器使能) */
#pragma config WRT = OFF /* 闪存自写保护 (写保护关闭) */
#pragma config PPS1WAY = OFF /* 外设引脚选择单向控制 (PPSLOCK 位可以通过软件反复设置和清除) */
#pragma config ZCDDIS = ON /* 零交叉检测禁用 (ZCD 禁用。ZCD 可以通过设置 ZCDCON 的 ZCDSEN 位来启用) */
#pragma config PLLEN = ON /* 锁相环使能 (4x PLL 使能) */
#pragma config STVREN = ON /* 栈溢出/下溢复位使能 (栈溢出或下溢将导致复位) */
#pragma config BORV = LO /* 低电压复位电压选择 (低电压复位电压 (Vbor),选择低触发点。) */
#pragma config LPBOR = OFF /* 低功率低电压复位 (低功率低电压复位禁用) */
#pragma config LVP = ON /* 低电压编程使能 (低电压编程使能) */
/* 定义系统振荡器频率 */
#define _XTAL_FREQ (32000000ul)
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//counter variable
int count = 0;
void main(void) {
unsigned char index = 0;
/* 程序初始化设置 */
OSCCON = 0xF0; /* 设置 INTOSC 为 8MHz,并使用 4xPLL,使系统振荡器达到 32MHz */
INTCON = 0; /* 禁用所有中断源 */
PIE1 = 0;
PIE2 = 0;
PIE3 = 0;
// Allow PLL startup time ~2 ms
__delay_ms(10);
ANSELA = 0x00; // 将所有A端口引脚设置为数字模式
ANSELB = 0x00; // 将所有B端口引脚设置为数字模式
ANSELC = 0x00; // 将所有C端口引脚设置为数字模式
// Set PIN D1 as output
TRISDbits.TRISD1 = 0;
// Turn off LED
LATDbits.LATD1 = 0;
// Setup PORTD
TRISD = 0;
ANSELD = 0;
/////////////////////
// Configure Timer2
/////////////////////
// prescale = 16
T2CONbits.T2CKPS = 0b10;
// Set period to 255
PR2 = 255;
// Set TMR2 to 0
TMR2 = 0;
// postscale = 15
T2CONbits.T2OUTPS = 0b1110;
// enable timer2
T2CONbits.TMR2ON = 1;
// enable timer2 interrupt
PIE1bits.TMR2IE = 1;
// enable peripheral interrupt
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1; // 使能全局中断
while (1) {
// Main loop does nothing, all action in ISR
}
}
void __interrupt() isr(void){
static unsigned char count = 0;
if (PIR1bits.TMR2IF) {
PIR1bits.TMR2IF = 0; // 清除 Timer2 中断标志位
count++;
if (count >= 122) { // Adjust this count based on your desired period
count = 0;
LATDbits.LATD1 ^= 1; // Toggle LED state
}
}
}
Timer2 是 PIC16F1719 微控制器中功能强大的定时器之一,通过适当配置,可以用于生成精确的时间延迟和周期性任务。在配置 Timer2 时,需要确保所有相关寄存器和位设置正确无误。通过上述示例和解决方案,你可以轻松地实现 Timer2 的配置和应用。
希望这篇博客能帮助你更好地理解和使用 Timer2。如果你有更多问题或需要进一步的帮助,欢迎随时交流!
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!