PIC24系列单片机原理与开发 by Zeng 2012-6-9
第 5章 定时器/计数器及编程
5.1 概述
定时器/计数器是所有单片机都具备的功能模块,其核心部件是可编程的计数器。当计
数器的输入信号为芯片内周期不变的时钟脉冲时(如指令周期 Tcy,或 Tcy 的分频信号),其
计数值代
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
的是时间,这时称之为定时器(Timer)。若输入信号为引脚上的随机脉冲,则其
功能为计数器(Counter)。有时习惯上不加区分,都称定时器,至于它们是作为定时器还
是作为计数器,完全由用户编程指定。在嵌入式应用
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
中,几乎都离不开定时器,如等间
隔时间采样、信号频率或周期的测量、脉冲宽度的测量、PWM脉冲输出等。单片机内定时
器资源的位数、个数和种类直接关系到系统程序的设计,有时资源的不足可导致设计瓶颈。
PIC24 系列芯片配置了相当数量的定时器,大多数 PIC24F 芯片为 5 个 16 位的定时器,只
有少数几种 14pin、20pin 和 28pin 封装的 KA系列(如 PIC24F04KA201)为 3 个 16 位的定
时器。PIC24H 系列中有十几种型号的芯片有 9个 16 位的定时器。与 PIC 的 8 位单片机相比,
PIC24 系列提供了丰富的定时器模块,给用户的程序设计带来极大的方便。
PIC24 系列的每个定时器模块都有 3 个 16 位可读/写的寄存器:TMRx、PRx 和 TxCON,
x=1,2,…,为定时器的序号。
TMRx:16 位定时器寄存器,即工作寄存器(为“加”计数器)。
PRx:该定时器的 16 位周期寄存器。
TxCON:该定时器的 16 位控制寄存器。
每个定时器模块在中断控制寄存器中有与其相关的控制位:中断允许位 TxIE,中断标
志位 TxIF,中断优先级控制位 TxIP<2:0>。详见第 3 章中的“表 3-8 GA 系列的外设中断
向量和控制标志位”。
所有 16 位定时器模块都有相同的基本功能结构,但在功能上也有一些不同之处。根据
功能上的差异将定时器分为三种类型: A 类定时器、B 类定时器和 C 类定时器。
另外,B 类和 C 类定时器可以两个组合成为 32 位定时器,大大增加了定时/计数范围,
对于有些场合使用起来尤为方便。
5.2 定时器器结构
5.2.1 定时器的基本功能结构
PIC24 系列的定时器分成 A、B和 C三种类型,尽管各类定时器有其自己的特有功能,
图 5-1 定时器模块基本功能结构图
分频设置
TCKPS<1:0>
允许工作 TON
TMRx
PRx
比较器
复位
相等
中断标志
TxIF
同步
分频器
(1,8,64,256)
1x
01
00
定时/计数选择 TCS
门控
定时脉冲 Tcy
引脚
TxCK
2
周期寄存器
定时寄存器
TGATE 门控选择
PIC24系列单片机原理与开发 by Zeng 2012-6-9
但它们的基本功能结构是相同的。图 5-1 为定时器模块基本功能结构图。
定时器模块的寄存器均是 16 位、可读/写。图中 TMRx 是定时/计数工作寄存器,它是
一个增量型计数器,计数脉冲来源取决于控制寄存器 TxCON 中的 TCS 位,见表 5-1“定
时器控制寄存器 TxCON 各位功能定义”。若将 TCS位置“1”,则该定时器模块作计数器使
用,计数脉冲来源于引脚 TxCK,在引脚 TxCK上信号的上沿使 TMRx寄存器加 1(设分频
系数=1)。反之,若 TCS位=“0”,则计数脉冲来源于片内的系统时钟 fosc/2, 即指令周期
Tcy 信号,这时作为定时器功能使用。控制寄存器 TxCON 中的 TON 位控制定时器的运行/
停止。将 TON位置“1”,启动定时器工作;若将 TON位清“0”则定时器停止工作,TMRx
寄存器保持其原计数值。分频系数由控制寄存器 TxCON中的 TCKPS<1:0>位设置。
PRx 是周期寄存器,当 TMRx 寄存器中的计数值与 PRx 寄存器中值相同时(称为“周
期匹配”),中断标志位 TxIF置“1”,若允许该定时器中断,则向 CPU申请中断。需要注意
的是,在产生周期匹配时 TMRx 寄存器不会清零,而是在产生周期匹配后的下一时钟脉冲
TMRx寄存器才清零。因此,TMRx寄存器的计数周期为 PRx寄存器的值加 1。对于周期匹
配来说,第一次产生周期匹配的时间或计数值等于 PRx 寄存器中的设置值,之后产生的周
期匹配才为 PRx寄存器的值加 1。
注意,当周期寄存器 PRx 的值为 0时,定时器不能工作,周期匹配也不会产生定时器
中断。
工作在定时器方式时(TCS位=“0”),若将控制寄存器 TxCON 中门控位 TGATE置为“1”,
则定时器工作需同时满足 TON位为“1”和引脚 TxCK为“1”(高电平)两个条件,并且当
引脚 TxCK 由高电平变低电平(“1”→“0”)时,即引脚 TxCK 的下跳沿,置中断标志位
TxIF为“1”,向 CPU申请中断。这种工作方式称为门控定时器模式。注意,这种方式的周
期匹配不产生中断。门控定时方式很适合测量脉冲的宽度。
注意,PIC24FJ128GA 系列芯片只有 100pin 封装的有 T1CK~T5CK 引脚;80pin 封装
的有 T1CK~T4CK引脚;64pin封装的只有 T1CK引脚,无 T2CK~T5CK引脚。
5.2.2 A 类定时器
PIC24 系列芯片中的 Timer1 为 A 类定时器。Timer1 的定时/计数寄存器是 TMR1,周期
寄 存 器 是 PR1 , 控 制 寄 存 器 是 T1CON 。 Timer1 的 脉 冲 输 入 引 脚 为 T1CK
(SOSCO/T1CK/CN0/RC14)。
除了图 5-1 的定时器模块基本功能外,A 类型定时器还有下列独特的功能:
1. Timer1 的脉冲输入引脚 T1CK 是低功耗 32 kHz 振荡器的 SOSCO 端(详见“第 3
章 3.1.5 低功耗辅助振荡器(SOSC)”),因此可以使用此低功耗振荡器作为时钟源,
当然需设置 Timer1 的控制寄存器 T1CON 的 TCS位为“1”,让 Timer1 作计数器使
用。
2. Timer1的控制寄存器 T1CON中有一个同步选择位 TSYNC,若将 TSYNC位请”0” ,
则可以工作在异步模式(使用 T1CK引脚的外部时钟源,TCS位=“1”)。
3. 只有 Timer1具有芯片休眠(SLEEP)模式的唤醒功能。若设置 Timer1为异步方式时,
在休眠模式下 Timer1 保持工作,当 TMR1 寄存器与 PR1 寄存器的值相等时,若允
许 Timer1中断(位 T1IE=“1”),芯片从休眠模式唤醒。
5.2.3 B 类定时器
Timer2 和 Timer4 是 B 类型定时器。除了图 5-1 的定时器模块基本功能外,B 类型
定时器有下列独特的功能:
1. B 类定时器的 TxCON(T2CON,T4CON) 寄存器有一个 T32 控制位,若将位 T32
置 “1”,则 B 类定时器和 C 类定时器相连形成 32 位定时器,这时 B 类定时器
为 32 位定时器的低 16位。例如 Timer2和 Timer3可以构成 32位定时器,Timer4
PIC24系列单片机原理与开发 by Zeng 2012-6-9
和 Timer5可以构成 32位定时器。
2. B 类定时器无异步模式,它的工作总是与指令时钟同步。当使用 TxCK 引脚的外
部时钟源时(TCS 位=“1”),对外部时钟的高电平和低电平有一个最短时间的要
求,具体参数请见芯片数据手册。
5.2.4 C 类定时器
Timer3 和 Timer5 是 C 类定时器。除了图 5-1 的定时器模块基本功能外,C 类 型
定时器有下列独特的功能:
1. C 类定时器可以和 B 类定时器相连形成 32 位定时器,这时 C 类定时器为 32 位定
时器的高 16 位。例如,置 Timer2 的控制寄存器 T2CON 的 T32 位为“1”,Timer3
和 Timer2 构成 32 位定时器;若将 T4CON 的 T32 位置为”1”,Timer5:和 Timer4
则构成 32 位定时器。
2. 至少有一个 C 类定时器能够触发 A/D 转换(PIC24FJ128GA 系列为 Timer3)。关于
C类定时器触发 A/D 转换的功能和编程请见“第 6章 A/D 转换器及编程”。
3. C 类定时器无异步模式,它的工作总是与指令时钟同步。当使用 TxCK 引脚的外部
时钟源时(TCS 位=“1”),对外部时钟高电平和低电平有一个最短时间的要求。
5.2.5 控制寄存器
表5-1:定时器控制寄存器 TxCON 各位功能定义
其中: U=未用(读为0),R=可读, W=可写,-n =上电复位值,
R/W-0 U-0 R/W-0 U-0 U-0 U-0 U-0 U-0
TON 未用 TSIDL 未用 未用 未用 未用 未用
bit 15 bit 8
U-0 R/W-0 R/W -0 R/W-0 R/W-0 U-0 R/W-0 U-0
未用 TGATE TCKPS<1:0> T32 TSYNC TCS 未用
bit 7 bit 0
bit 15 TON
定时器计数器运行控制位: 1 = 启动定时器
0 = 停止定时器
bit 13 TSIDL 空闲模式停止位:1 = 当器件进入空闲模式时,定时器停止工作0 = 在空闲模式下定时器继续工作
bit 6 TGATE
门控时使能位, 当 TCS =0 时: 1 = 使能门控定时
0 = 禁止门控定时
当 TCS = 1 时:该位不起作用,读为 0。
bit 5-4 TCKPS<1:0>
时钟预分频选择位: 11 = 预分频比为 1:256
10 = 预分频比为 1:64
01 = 预分频比为 1:8
00 = 预分频比为 1:1
bit 3 T32
32位定时器选择位: 1 = TMRx 和 TMRy 形成 32 位定时器
0 = TMRx 和 TMRy 为独立的 16 位定时器
仅B类定时
器有
bit 2 TSYNC
Timer1 外部时钟输入同步选择位, 当 TCS = 1 时:
1 = 同步外部时钟输入
0 = 不同步外部时钟输入
当 TCS = 0 时:该位不起作用,读为 0。
仅A类定时
器Timer1
有
bit 1 TCS 时钟源选择位: 1 = 来自 TxCK 引脚的外部时钟0 = 内部时钟 (Fosc/2)
其余位 未用 读为0
PIC24系列单片机原理与开发 by Zeng 2012-6-9
表 5-1 为定时器模块的控制寄存器各控制位的功能定义 。其中,TSYNC 位
(T1CON<2>)只 Timer1 的 T1CON 寄存器有定义,其余控制寄存器中的相应位
(T2CON<2>~T5CON<2>位)未用。位 T32仅 B类定时器的(T2CON<3>, T4CON<3>)有定义。
当B类定时器使能 32 位工作模式(T2CON<3> = 1 或T4CON<3> = 1)时,C类定时器的
控制寄存器不起作用,所有定时器功能都通过T2CON或T4CON 进行设置。
5.3 工作模式
每个定时器模块均有三种工作模式,它们是:定时器模式、门控定时器模式和同步计数
器模式。Timer1还可工作在异步计数器模式。如前所述,工作模式由各定时器模块的控制寄
存器TxCON 中的相应位控制:
TCS位(TxCON<1>):定时器时钟源控制位。
TSYNC位(TxCON<2>):定时器同步控制位(仅 A 类Timer1有)。
TGATE位(TxCON<6>):定时器门控控制位。
TON 位(TxCON <15>)使能或禁止每个定时器模块。
5.3.1 定时器模式(16 位,非门控)
若将控制寄存器TxCON中的 TCS 位(TxCON<1>)清“0”,则工作于定时器模式。所有
类型的定时器都可以工作于定时器模式。在定时器模式下,定时器(确切地说是计数器,即
TMRx)的输入时钟由内部系统时钟(Fosc/2)提供。因为使用系统时钟源作为定时器时钟,
同步模式控制位 TSYNC(TxCON<2>)在该模式下不起作用。
设指令周期为Tcy, 预分频系数为 N,周期寄存器 PRx 所赋值为 X,则定时时间为:
T定时=Tcy*N*(X+1)
例如,(PRx)=8000-1,,指令时钟Fcy=32/2MHz=16MHz,。 由此可算得定时时间:
T定时 =8*8000/16=4000 (us)。
例5-1:设主振荡器8MHz,PLL 4倍频,利用Timer1定时,使端口RD的RD0输出周期为 2ms
的方波,即每 1ms 改变一次 RD0 的电平。
由所给条件知,指令时钟Fcy=32/2MHz=16MHz,T定时=1ms=1000us。设TCKPS<1:0>=01(预
分频系数=8),周期寄存器 PR1 所赋值为 X。
X=1000*Fcy/N-1=1000*16/8-1=2000-1=1999。
程序如下:
#include "p24FJ64GA006.h"
/* 配置1:JTAG接口OFF,代码不保护,允许写Flash,允许调试,禁Clip ON,ICD用PGC1/PGD1,
禁WDT,WDT的前分频32,WDT的后分频256 */
_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_ON & COE_OFF & ICS_PGx1 &
FWDTEN_OFF & FWPSA_PR32 & WDTPS_PS256)
/*配置2:禁双速启动,主振4xPLL, 禁时钟切换_禁保护监视,OSC2接晶振, XT晶振*/
_CONFIG2(IESO_OFF & FNOSC_PRIPLL & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_XT)
int main ( void )
{ TMR1 = 0; PR1 = 1999; //清Timer1计数器,置Timer1的周期寄存器
T1CON=0x8010; //启动TON=1,TCS位=0,TGATE位=0,内部时钟(fosc/2=16MHz),8分频
IFS0bits.T1IF = 0; //清Timer1的中断标志
SRbits.IPL = 3; //置 CPU 优先级为3
IPC0bits.T1IP = 4; // 置Timer1优先级4;
IEC0bits.T1IE = 1; //允许Timer1中断
PIC24系列单片机原理与开发 by Zeng 2012-6-9
定
时
器
TRISD=0xfffe; //RD0的方向为OUT
while(1){ ; } //死循环
}
// Timer1的中断服务程序
void __attribute__((__interrupt__,no_auto_psv)) _T1Interrupt(void)
{ if(LATDbits.LATD0) //将RD0取反
LATDbits.LATD0=0;
else
LATDbits.LATD0=1;
IFS0bits.T1IF = 0; //清Timer1的中断标志
}
注意,第一次产生中断为 999.5us,之后才是每1ms产生一次中断。这是由于TMR1寄存
器要在周期匹配后的下一个定时脉冲才清零。如果对第一次周期匹配(中断)有要求,则程
序中要作相应处理,例如初始化时将 TMR1设置成0xffff。
5.3.2 门控定时器模式
若将控制寄存器TxCON中的 TCS 位(TxCON<1>)清“0”和TGATE位(TxCON<6>)置“1”,
则定时器工作在门控模式。和“5.3.1”一样,定时器(确切地说是计数器,即 TMRx)的输
入时钟由内部系统时钟(Fosc/2)提供。这时定时器工作需同时满足TON位为“1”和引脚TxCK
为“1”(高电平)两个条件,引脚 TxCK 称为门控信号。
门控信号的下降沿使中断标志 TxIF 置 1 并产生中断(如果允许中断)。当发生定时
器周期匹配时(即工作寄存器 TMRx 中的计数值等于周期寄存器 PRx 中的值时),工作寄
存器TMRx 回零,但定时器不会置中断标志 TxIF。用门控定时器模式测量引脚 TxCK上的脉
冲宽度尤为方便。
例5-2:利用Timer1的门控定时,测量施加在引脚T1CK上的正脉冲宽度。
编程说明:设主振荡器8MHz,PLL 4倍频,指令时钟为16MHz。程序中取时钟预分频=8
(TCKPS<1:0>=01),TMR1的计时分辨率为0.5us。当定时器运行控制位 TON 为“1”时,引
脚T1CK的上升沿使定时器 TMR1开始计时。T1CK的下降沿停止TMR1计时,同时产生中断,此
时TMR1中的计时值就是所测脉冲宽度(单位为0.5us),在Timer1的中断服务程序中将TMR1
送脉冲宽度存储单元 PulseT,并请零TMR1,为下一个脉冲的测量作准备。
程序中SimPulsT()函数是利用T1CK与RC14 复用引脚,人为地用输出指令来模拟产生脉
宽信号,用来测试程序功能。在MPLAB SIM 软件模拟器环境下也可运行。
脉冲宽度测量的示意图和程序如下:
int PulseT; //存储所测脉冲宽度,单位0.5us
int main ( void )
{ TMR1 = 0; PR1 = 0xffff; //清Timer1计数器,置Timer1的周期寄存器为65535
T1CON=0x8050; // TON=1,TCS位=0,TGATE位=1,内部时钟(16MHz),8分频
TMR1 停止计时,
产生中断
Tx2
TMR1 停止计时,
产生中断
引脚 T1CK
Tx1
TMR1 开始计时
TMR1 开始计时
图 5-1 脉冲宽度测量
PIC24系列单片机原理与开发 by Zeng 2012-6-9
定
时
器
IFS0bits.T1IF = 0; //清Timer1的中断标志
SRbits.IPL = 3; //置 CPU 优先级为3
IPC0bits.T1IP = 4; // 置Timer1优先级4;
IEC0bits.T1IE = 1; //允许Timer1中断
while(1) //死循环
{ SimPulsT();} //产生模拟脉冲,用于测试程序
}
// Timer1的中断服务程序。引脚 T1CK 的下跳沿产生中断。
void __attribute__((__interrupt__,no_auto_psv)) _T1Interrupt(void)
{
PulseT =TMR1; //将所测的脉冲宽度送PulseT单元
TMR1 = 0; //清Timer1计数器,准备下次测量。
IFS0bits.T1IF = 0; //清Timer1的中断标志
}
void SimPulsT() //模拟被测的脉冲信号(RC14/T1CK )
{ int i;
TRISCbits.TRISC14=0; //RC14 的方向为输出
LATCbits.LATC14=1;
for(i=0;i<20000;i++) { ;} //延时
LATCbits.LATC14=0; //产生 RC14/T1CK 的脉冲信号
for(i=0; i<100; i++) { ;} //延时
}
5.3.3 同步计数器模式
所谓的同步计数器模式是指 CPU 在一个指令周期内的两个不同时刻点对外部时钟信号
进行采样,即每个指令周期对引脚上的信号采样2次,以确定输入的计数脉冲。这种模式也
就是通常所说的计数器方式。
当 TCS 控制位(TxCON<1>)置 1 时,定时器工作在同步计数器模式,外部时钟(即计
数脉冲)从TxCK 引脚输入,经预分频率后,TMRx寄存器在每个脉冲的上升沿进行加 1 计数。
对于 A 类定时器(如Timer1),若要运行在同步计数器模式,还需将控制寄存器的同
步选择位 TSYNC(TxCON<2>) 置“1”。对于 B 类和 C 类定时器,若作计数器用时,总是
工作在同步计数器模式。
同步计数器模式的定时器在休眠模式下不工作,因为同步电路在休眠模式下是关闭的。
另外,当定时器工作在同步计数器模式时,对外部时钟高、低电平时间有一个最小限制,具
体要求值可查芯片手册。
例5-3:Timer1为 16 位同步计数器模式。设主振荡器8MHz,PLL 4倍频,T1CK 引脚
每输入2000个脉冲,端口RD的RD0 改变一次电平。此例的编程除 T1CON的赋值(黑体部分)
不一样外,其余与例5-1完全一样,但工作原理变了。RD0 的电平的改变取决于 T1CK 引
脚的脉冲数。
int main ( void )
{ TMR1= 0; PR1= 1999; //清Timer1计数器,置Timer1的周期为2000
T1CON=0x8006; //启动 TON=1;TSYNC=1,TCS位=1;1分频。
IFS0bits.T1IF= 0; //清Timer1的中断标志
SRbits.IPL= 3; //置 CPU 优先级为3
IPC0bits.T1IP= 4; // 置Timer1优先级4;
IEC0bits.T1IE= 1; //允许Timer1中断
TRISD=0xfffe; //RD0的方向为OUT
PIC24系列单片机原理与开发 by Zeng 2012-6-9
定
时
器
while(1) { ; } //死循环
}
// Timer1的中断服务程序
void __attribute__((__interrupt__,no_auto_psv)) _T1Interrupt(void)
{
if(LATDbits.LATD0) //将RD0取反
LATDbits.LATD0=0;
else
LATDbits.LATD0=1;
IFS0bits.T1IF = 0; //清Timer1的中断标志
}
必须注意的是,工作在计数模式时,分频器仍然起作用,引脚上的输入脉冲经分频器后进
TMRx寄存器(即计数器).例如,若将上例T1CON中的分频系数设为8(T1CON=0x8016),则为每输
入16000个脉冲,端口RD的RD0 改变一次电平.
另外,第一次产生中断时为1999个计数脉冲,之后才是每2000个计数脉冲产生一次中断。
这是由于TMR1寄存器要在周期匹配后的下一个计数脉冲才清零。如果对第一次周期匹配(中
断)有要求,则程序中要作相应处理,例如初始化时将 TMR1设置成0xffff。
5.3.4 异步计数器模式(A 类定时器)
当TCS位=“1”和同步控制位(TxCON<2>)TSYNC=“0”时, A 类定时器(PIC24 系列
芯片中的Timer1 为A类定时器)工作在异步计数模式下。TxCK引脚输入的计数脉冲可与器件
系统时钟不同步。也就是说输入的计数脉冲与芯片系统时钟无关,但芯片对输入脉冲的高、
低电平最小时间有一定要求,即对输入脉冲的频率有一个上限要求。
异步计数模式可以在休眠(SLEEP)模式下工作,并且在周期寄存器匹配时产生中断(若允
许其中断)时,可唤醒CPU。
值得注意的是,对工作在异步计数模式的Timer1,因计数脉冲与指令时钟可能不同步,
当读寄存器TMR1时可能会产生误差。可采用连续读两次TMR1的方法,若两次读的值相同,则
数据有效。
5.4 32 位定时器/计数器
在大多数情况下,16位的定时器/计数器能满足设计需求。当用户需要更多位数的定时
或计数时,PIC24 系列可以将B 类和 C 类定时器组合成 32 位定时器/计数器。若将某B 类
定时器的TxCON寄存器的 T32 位置“1”,则该B 类定时器和与其相应的C 类定时器构成
32 位定时器,这时C类定时器为32位定时器的高16位,B 类定时器为低16位。
当配置为 32 位定时器时,B 类定时器的控制寄存器 TxCON 控制 32 位定时器的工作。
C 类定时器的 TxCON中的各控制位不起作用。中断入口和与中断相关的控制(中断允许、中
断标志和中断优先级控制位)则使用C 类定时器的,B类的中断入口和中断控制位不起作用。
对于片内有5个16位定时器的PIC24 芯片,若将Timer2的T2CON寄存器的T32位置“1”,
则B类的Timer2和C类Timer3构成32位定时器。TMR3:TMR2组成32位的定时/计数器, PR3:PR2
组成32位的周期寄存器。T2CON 控制 32 位定时器的工作, 中断入口、中断允许、中断标志
和中断优先级使用Timer3的。
若将Timer4的T4CON寄存器的T32位置“1”,则B类的Timer4和C类的Timer5构成32位定
时器。TMR5:TMR4组成32位的定时/计数器,PR5:PR4组成32位的周期寄存器,T4CON 控制
32 位定时器的工作, 中断入口、中断允许、中断标志和中断优先级使用Timer5的。
注意,和16位定时/计数器一样,32位的周期寄存器不能为零,否则不能工作。
注:输入捕捉和输出比较在 32 位定时器模式下不可用。
PIC24系列单片机原理与开发 by Zeng 2012-6-9
定
时
器
5.4.1 32 位定时/计数器的编程
和 16 位定时器模块一样,组合成 32 位工作时也有定时器、门控定时器和计数器几种
工作模式。
假如用Timer3_Timer2组合成32位工作模式,以下是作初始化的步骤和编程的基本要点:
置T32(T2CON<3>)= 1,Timer3_Timer2组成32位工作模式;
设置预分频系数n:TCKPS<1:0>(T2CON<5:4>)=n;
作定时器: 控制位TCS(T2CON<1>)= 0,若需门控 TGATE位(T2CON<6>)=1,否则
TGATE=0。作计数器: TCS(T2CON<1>)= 1;
设置好32位周期寄存器 PR3:PR2,PR3为高16位;
清零32位定时/计数器:TMR2=0;TMR3:=0;
启动32位定时/计数器工作:TON(T2CON<15>)= 1;
T3IE(IEC0<8>)为该32 位定时器的中断允许位;
T3IP<2:0>(IPC2<2:0>)为该 32 位定时器的中断优先级;
T3IF(IFS0<8>)为该 32 位定时器的中断标志位。当发生周期匹配,即TMR3:TMR2
中的32位计数值等于PR3:PR2中的预置值时,或门控模式下引脚T2CK产生下跳变
时,中断标志位T3IF(IFS0<8>)自动置”1”。
例 5-4:用 Timer3_Timer2 组成 32 位定时器来测量 50Hz 左右的工频信号周期,所测
信号经整形为方波后施加在引脚 INT0 端。为减少测量误差,程序中连续测量 16 个周期,取
其平均值。指令周期 Tcy=0.0625us(主振荡器 8MHz,PLL 4 倍频),定时器的预分频取 8,则
16 个周期的计数值为 16*20000/0.5=640000,可见用 32 位定时器可以装下,且不会溢出,
无需定时器中断。
char Counter;
union { unsigned int x1[2];
unsigned long Lx;
} CycT; //存放所测周期值 CycT.Lx
int main ( void )
{ Counter=0;
T2CON=0x0018; //TON=0,T32=1,TCS 位=0,8 分频(0.5us)。
TMR3=0; TMR2=0; //清 Timer3_Timer2_计数器
PR3=0xffff; PR2=0xffff;
SRbits.IPL=3; //置 CPU 优先级为 3
IEC0bits.T3IE=0; //禁止 Timer3 中断(禁止此 32 位定时器中断)
INTCON2bits.INT0EP=1; //INT0 下沿中断
IPC0bits.INT0IP=4; //置 INT0 的优先级为 4;
IFS0bits.INT0IF=0; //清 INT0 的中断标志
IEC0bits.INT0IE=1; //允许 INT0 中断
while(1){ ; } //死循环,可处理所测周期值 CycT.Lx
}
// INT0 的中断服务程序
void __attribute__((__interrupt__,no_auto_psv)) _INT0Interrupt(void)
{
if(Counter==16)
{ T2CONbits.TON=0; //停止计时, TMR3:TMR2 中为 16 个周期的测量值
CycT.x1[0]=TMR2; //C30 的数据格式是“低字”在前
CycT.x1[1]=TMR3; //CycT.Lx = TMR3:TMR2
TMR2=0; TMR3=0; //需先清 TMR2
PIC24系列单片机原理与开发 by Zeng 2012-6-9
Counter=0;
CycT.Lx= CycT.Lx>>4; //CycT.Lx 除以 16 后为所测周期值(单位:0.5us)
}
else
{ Counter++; T2CONbits.TON=1; } //启动定时
IFS0bits.INT0IF=0; //清 INT0 的中断标志
}
// 32 位定时器 Timer3_Timer2 的中断服务程序(因禁止中断,实际未起作用)
void __attribute__((__interrupt__,no_auto_psv)) _T3Interrupt(void)
{
IFS0bits.T3IF=0;
}
说明:在 INT0 的中断服务程序中,应先清零 TMR2,后清零 TMR3,否则 TMR3 清不了零。
这是因为在读 TMR2 时(语句:CycT.x1[0]=TMR2;), TMR3 的值同时被装载到它的保持寄存器
TMR3HLD;在清零 TMR2(语句:TMR2=0;)的同时 TMR3HLD 的值自动送 TMR3。详见下面的“5.4.2
32 位定时/计数器的的读写操作”。
例 5-5:Timer3_Timer2 组成 32 位计数器模式的编程。设 T2CK 引脚每输入 200000 个
脉冲,端口 RD 的 RD0 改变一次电平。
int main ( void )
{ T2CON=0x000a; // TON=0;T32=1,TCS位=1;1分频。
TMR2= -1; TMR3= -1; //为解决首次匹配周期少 1的问题,Timer2_Timer3_计数
器的赋初值 TMR3: TMR2=0xffffffff
PR3=0x0003; PR2=0x0d40-1; //200000=0x030d40
SRbits.IPL = 3; //置 CPU 优先级为 3
IPC2bits.T3IP = 4; //置 Timer3 优先级为 4
IFS0bits.T3IF = 0; //Timer3的中断标志清零
IEC0bits.T3IE = 1; //允许 Timer3中断(允许此 32位计数器中断)
T2CONbits.TON = 1; //启动计数器
TRISD=0xfffe; //RD0的方向为 OUT
while(1){ ; } //死循环
}
// 32位计数器 Timer3_Timer2 的中断服务程序(Timer3的中断入口)
void __attribute__((__interrupt__,no_auto_psv)) _T3Interrupt(void)
{ if(LATDbits.LATD0) //将 RD0取反
LATDbits.LATD0=0;
else
LATDbits.LATD0=1;
IFS0bits.T3IF = 0; //清 Timer3的中断标志
}
注意:PIC24FJ128GA 系列芯片只有80pin和100pin封装的有T2CK引脚,与RC1复用。
5.4.2 32 位定时/计数器的的读写操作
针对定时/计数器的32位工作方式,PIC24 系列芯片设计了额外的控制逻辑电路和保持
寄存器, 可使运行中的 32 位定时器(TMRx:TMRx-1)的高16位(TMRx: 高字,MSW)和低16位
(TMRx-1:低字,LSW)的读/写操作同步。对编程而言,每个 C 类定时器都有一个称为 TMRxHLD
的保持寄存器,如TMR3HLD、TMR5HLD。在读32 位定时器的低16位寄存器 TMRx-1 同
时,高16位寄存器 TMRx 中的值将自动送其TMRxHLD寄存器。在写32 位定时器的低16位寄存
器 TMRx-1 同时,相应的TMRxHLD寄存器中的内容将自动送高16位寄存器 TMRx。在程序设计
中,通常只有其对应的定时器被配置为 32 位工作,并且需要在定时器运行中作读写操作时
PIC24系列单片机原理与开发 by Zeng 2012-6-9
定
时
器
定
时
器
才使用 TMRxHLD 寄存器。
假设Timer3_Timer2 组成 32 位定时器。若要读取TMR3:TMR2中的内容时,用户应该首
先读 TMR2 寄存器。读 TMR2 寄存器同时,TMR3 的内容传送给了TMR3HLD中。然后用户再读
TMR3HLD,得到定时器的高16位值。
例如在例5-4中,可以将INT0的中断服务程序改为不停定时器来读取32位计数值。程
序如下:
void __attribute__((__interrupt__,no_auto_psv)) _INT0Interrupt(void)
{
If(Counter==16)
{ CycT.x1[0]= TMR2; //先读低16值,读的同时 TMR3HLD←TMR3
CycT.x1[1]= TMR3HLD; // CycT.Lx = TMR3:TMR2
TMR3HLD=0;
TMR2 = 0; //写TMR2的同时 TMR3HLD →TMR3
Counter=0;
CycT.Lx= CycT.Lx>>4; // CycT.Lx除以16后为所测周期值(单位:0.5us)
}
else
Counter++;
T2CONbits.TON = 1; //启动定时
IFS0bits.INT0IF=0; //清INT0的中断标志
}
例5-6:Timer3_Timer2组成32位的门控定时器模式的编程。测量施加在引脚T2CK上的
正脉冲宽度,设主振荡器8MHz,PLL 4倍频,指令时钟为16MHz。程序中取时钟预分频=8
(TCKPS<1:0>=01),计时分辨率为0.5us。本例的编程思路与例5-2相同。程序中对控制寄
存器T2CON的初始化采用位操作方式,使各控制位的初始化更为直观。
union { unsigned int x1[2];
unsigned long Lx;
} PulseT;
int main ( void )
{ T2CON=0x0000;
PR3=0xffff; PR2=0xffff; //周期寄存器置为最大值
T2CONbits.TGATE = 1; // TGATE为“1”,使能门控时
T2CONbits.TCS = 0; //TCS位为“0”,定时器模式
T2CONbits.TCKPS = 1; //8分频,分辨率:0.5us
T2CONbits.T32 = 1; //T32位为”1”,Timer3_Timer2 构成32位工作
TMR3HLD=0;
TMR2=0; //写TMR2时,TMR3HLD 同时送TMR3(清零)
SRbits.IPL = 3; //置 CPU 优先级为3
IPC2bits.T3IP = 4; //置 Timer3 优先级为4
IFS0bits.T3IF = 0; //清Timer3的中断标志
IFS0bits.T3IE = 0; //允许Timer3中断
T2CONbits.TON = 1; //允许定时器工作
while(1){ ; } //死循环,可在此处理所测的正脉冲宽度PulseT.Lx
}
/* 32位计数器 Timer3_Timer2的门控中断服务程序(Timer3的中断入口)。引脚 T2CK 的
下跳沿产生中断,将所测的脉冲宽度送 PulseT.Lx */
void __attribute__((__interrupt__,no_auto_psv)) _T3Interrupt(void)
PIC24系列单片机原理与开发 by Zeng 2012-6-9
{ PulseT.x1[0]= TMR2; //先读低16值, 读的同时 TMR3HLD←TMR3
PulseT.x1[1]= TMR3HLD; // PulseT.Lx = TMR3:TMR2
TMR3HLD = 0;
TMR2 = 0; //写TMR2的同时 TMR3HLD →TMR3, 准备下次测量。
IFS0bits.T3IF = 0; //清Timer3的中断标志
}
5.5 低功耗状态下的定时器工作
PIC24 系列芯片通过执行特殊的 PWRSAV 指令可进入休眠(SLEEP)和空闲待机(IDLE)两
种低功耗模式:
休眠模式:CPU、系统时钟和工作在系统时钟源下的任何外设都被禁止。这是芯片
的最小功耗模式。
空闲模式:CPU 被禁止,但系统时钟源继续工作。外设可继续工作,也可以选择将
其禁止。
5.5.1 休眠模式下的定时器工作
当芯片进入休眠模式后,系统时钟被禁止。如果定时器模块使用内部时钟源(Fosc/2)
运行,则该定时器被禁止。若A 类定时器若工作在异步计数器模式,则可以在休眠模式下继
续工作。
对于PIC24F 器件,T1mer2~Timer5和工作在定时器模式或同步计数器模式的Timer1在
休眠模式均停止工作。Timer1若配置成异步计数器模式(位TCS(T1CON<1>)=1,位TSYNC
(T1CON<2>)=0,位TON(T1CON<15>)=1,)运行,则在休眠模式下继续工作,并且当发生周期
匹配时可以产生中断,将芯片从休眠模式唤醒。
5.5.2 待机模式下的定时器工作
当芯片进入空闲模式后,只是CPU 停止执行指令,系统时钟仍然保持工作。定时器模块
可以选择在待机模式下继续工作。
定时器模块在空闲模式下是停止还是继续工作取决于用户对 TSIDL 位(TxCON<13>)的
设置。如果 TSIDL=0,在空闲模式下该模块将继续工作。反之,若 TSIDL = 1,在空闲模式
下该模块将停止工作。同理,继续工作的定时器模块产生的中断将使芯片退出待机模式,恢
复正常运行。
5.6 使用定时器模块的外设
5.6.1 输入捕捉/输出比较的时基
输入捕捉和输出比较外设可以选择两个定时器模块之一作为它们的时基。一般是选择
Timer2 或 Timer3。具体使用方法请参见“第10章 输入捕捉、输出比较和PWM”。
5.6.2 A/D 特殊事件触发信号
如果在 A/D 转换器的控制寄存器中选择触发源为“通用定时器比较触发”,则 C 类定
时器 Timer3 或 32 位模式下的 Timer3_Timer2 发生周期匹配时,能够产生启动 A/D 转换的
触发信号。关于定时器启动 A/D 转换的详细说明和编程方法请参见“第 6 章 A/D 转换器
及编程”。