TIM是定时器模块的简称。TIM的核心是一个16位的自由定时器(TCNT)。有8个完整的16位的捕捉/比较(IC/OC)通道。 模块运行时,16位的自由定时器按照设定的时钟频率在0x0000~0xFFFF之间循环计时。
本例通过MC9S12XS128的TIM模块的输出比较做一个简单的定时器。
以下为本例所用到的寄存器的介绍:
TIOS寄存器
TIOS 寄存器用于指定各个通道的功能,即工作于 IC还是 OC方式
当 IOSn=0 时,对应的通道 n 为输入捕捉(1C)通道
当 IOSn=1 时,通道 n为输出比较(OC)通道
OC7M寄存器
OC7 具有特殊地位,它匹配时可以直接改变其他 7 个输出引脚的状态,并覆盖各个引脚原来的匹配动作结果,寄存器 OC7M 决定哪些通道将处于 OC7 的管理之下。 OC7M 中的各位与 PORTT 口寄存器的各位一一对应。当通过TIOS 将某个通道设定为输出比较时,将 OC7M 中的相应位置 1,对应的引脚就是输出状态,与 DDR 中的对应位的状态无关。但 OC7Mn 并不改变DDR相应位的状态。 OC7M 具有更高的优先级,它优于通过 TCTL1 和 TCTL2 寄存器中的 OMn和 OLn 设定的引脚动作,若 OC7M 中某个位置 1,就会阻止相应引脚上由 OM和 OL设定的动作。
OC7D寄存器
OC7M 对于其他 OC输出引脚的管理限于将某个二进制值送到对应引脚, 这个值保存在寄存器OC7D中的对应位中。当 OC7 匹配成功后, 若某个OC7Mn=1,则内部逻辑将OC7Dn 送到对应引脚
OC7D中的各位与PORTT口寄存器的各位一一对应。 当通道7比较成功时,如果 OC7M 中的某个位为 1, OC7D中的对应位将被输出到 PORTT的对应引脚
当 OC7M 中的某个位为 1 时,通道 7 匹配成功的动作如果与通道 6-0 的动作发生在同一个周期,前者将覆盖后者。因此各个通道的动作将依赖于 OC7D中各个位的设置
TCNT寄存器
TCNT是递增计数器,它不停地对内部时钟信号计数、程序可随时读取,但在普通模式下禁止写入。TCNT应按字访问,分别访问高、低字节可能得到错误的结果
TSCR1寄存器
TSCR1 寄存器是定时器模块的总开关,它决定模块是否启动以及在中断等待、BDM 方式下的行为,还包括标志的管理方式。其各位的意义如下:
TEN:定时器使能位,此外它还控制定时器的时钟信号源。
要使用定时器模块的 IC/OC 功能,必须将 TEN 置位。如果因为某种原因定时器没有使能,脉冲累加器也将得不到 ECLK/64 时钟,因为 ECLK/64 是由定时器的分频器产生的,这种情况下,脉冲累加器将不能进行引脚电平持续时间的累加
0:主计时器、包括计数器均被禁止,有利于降低功耗
1:定时器使能,正常工作
TSWAI:等待模式下计时器关闭控制位
注意定时器中断不能用于使 MCU 退出等待模式
0:在中断等待模式下允许 MCU 继续运行
1:当 MCU进入中断等待模式时,禁止计时器
TSFRZ:在冻结模式下计时器和计数器停止位
0:在冻结模式下允许计时器和计数器继续运行
1:在冻结模式下禁止计时器和计数器,用于仿真调试
注意:TSFRZ不能停止脉冲累加
TFFCA:定时器标志快速清除选择位
0:定时器标志普通清除方式
1:定时器标志快速清除方式
PRNT:精确定时器开启位
0: 使用传统定时器,预分频因子由TSCR2中的PR2,PR1,PR0决定
1: 使用精确定时器,预分频因子由PTPSR寄存器决定
TTOV寄存器
TOVx:溢出绑定管脚标志位
TOVx 在输出比较时,如果发现溢出,则绑定该管脚。这一功能仅在输出比较模式下有效,它的优先级高出强制输出比较,而低于通道 7 的输出比较
0:输出比较的管脚发生溢出时绑定功能不发生作用
1:输出比较的管脚发生溢出时绑定功能使能
TCTL1-TCTL4寄存器
TCTL1-TCTL4 分为两组,分别对 IC 和 OC 电路进行设定,每组 16 个二进制位,每两个二进制位管理一个通道。其中 TCTL1、TCTL2 设定各个 OC 通道匹配时的动作,包括切断OC与输出引脚的联系,而 TCTL3、TCTL4设定 IC响应引脚的何种动作,包括禁止 IC的响应。各个控制位的作用如下:
OMn、 OLn 分别设定输出方式和输出电平,这 8 对控制位(OM7、 OL7-OMO、OL0)编码后用于指定通道比较成功后的输出动作。如果每对当中至少有一个为 1,对应引脚就固定为相应通道的输出,而与DDRT 中的对应位无关。当二者同时为 0 时,OC与输出引脚断开
EDGnB、EDGnA 输入捕捉边沿控制位,这 8 对控制位(EDG7B、EDG7A—EDGOB、EDGOA)对输入捕捉的边沿检测电路进行设置。当二者同时为 0 时,IC与输入引脚断开
注意:为了使 OMn、OLn 指定的引脚动作有效,OC7M 中的对应位必须清 0。若要使用16 位脉冲累加器 A和 B,并使它们分别独立于 IC/OC7 和 IC/OC0,必须设置对应的 IOSn:1、OMn=0、OLn=0,同时寄存器 OC7M 中的C7M7、OC7M0 位必须清 0
TIE寄存器
TIE 寄存器中的位与状态寄存器 TFLG1 中的标志位相对应。如果将 TIE 中的某位清 0,
相应的标志位就不能引起硬件中断。如果被置 1,相应的标志位就可以引起中断。
C7I-C0I:输入捕捉/输出比较“x”中断使能
TSCR2寄存器
TOI:计时器溢出中断使能
0:中断被禁止
1:当 TOF 标志被置位时发出硬件中断请求
TCRE:时钟计数器复位使能
该位在通道 7 成功输出比较之后允许时钟计数器复位。该操作模式类似于递增型计数器
0:计数器复位禁止,计数器自由计数
1:通道 7 成功输出比较后计数器将被复位
如果 TC7=0x0000并且 TCRE=1,TCNT将继续保持0x0000
如果 TC7=0xFFFF 并且 TCRE=1,当 TCNT 从0xFFFF 到0x0000 之间被复位后TOF将永远不被置位
PR2,PR1,PR0:计数器预分频选择
TFLG1、TFLG2寄存器
TFLG1、TFLG2 为中断标志寄存器,其中 TFLG1 对应 8 个 IC/OC通道,当某 CnF=1 时说明对应的 IC/OC 通道有动作。TFLG2 只有一个标志位TOF,作为核心计数器的中断请求标志。当 TOF=1 时说明核心计数器溢出。要清除某个标志位,只需向该位写1,向某位写 0 不影响该位的状态。当TSCR 中的 TFFCA 位置位时,读 IC 通道或写 OC 通道 (0x10-0x1F)将自动清除该通道标志CnF,对 TCNT的任何访问将自动清除 TFLG2。
CnF:IC/OC通道中断请求标志
0:上次清除标志以来,IC/OC 通道没有有效动作
1:IC/OC 通道已经出现动作
TOF:定时器溢出标志,当 16 位自由定时器从0xFFFF回滚到0x0000 时,该位置位。将0x80 写入到 TFLG2 将自动清除该位
TCxH and TCxL寄存器
每个 IC或 OC通道都设置有一个 16 位的寄存器,对于 IC(输入捕捉)通道,当通道的边沿探测器检测到由 EDGnA、EDGnB指定的条件时,将自由定时器的值捕捉到寄存器 TCn,随后程序可以读取和处理;对于 OC(输出比较)通道,程序将预定的时刻写入到 TCn,当自由定时器的值与其相等时,触发由OMn、OLn所指定的输出动作。定时器模块共有 TC7-TC0等 8 个 16 位IC/OC寄存器。 对于设定为 IC 的通道,相应通道写操作无意义
以下为完整代码:
#include #include "derivative.h" #define LED PORTB_PB0 //定义连接发光二级管的PORTB_PB0口数据寄存 //器为LED,写'0'亮,写'1' 灭 #define LED_dir DDRB_DDRB0 //定义连接发光二级管的PORTB_PB0口方向寄存器 //为LED_dir,写'0'做输入口,写'1'做输出口 void INIT_PLL(void) //初始化锁相环 { CLKSEL_PLLSEL=0; //内部总线时钟来源于外部晶振 PLLCTL_PLLON=0; //关闭PLL SYNR=0x40 | 0x03; REFDV=0x80 | 0x01; POSTDIV=0x00; //PLL为64MHz PLLCTL_PLLON=1; //打开PLL _asm(nop); _asm(nop); //执行两个机器周期 while(CRGFLG_LOCK==0); //根据CRGFLG寄存器的LOCK位,确定PLL是否稳定 LOCK==1 稳定,==0 不稳定 CLKSEL_PLLSEL =1; //选择PLL作为时钟源 } void initialize_ect(void) //初始化ECT模块 { TSCR1_TFFCA = 1; // 定时器标志位快速清除 TSCR1_TEN = 1; // 允许定时器正常工作 TIOS = 0xff; // 输出比较,指定所有通道为输出比较方式 TCTL1 = 0x00; // 后四个通道设置为定时器与输出引脚断开 TCTL2 = 0x00; // 前四个通道设置为定时器与输出引脚断开 TIE = 0x00; // 禁止所有通道定时中断 TSCR2 = 0x07; // 预分频系数pr2-pr0:111,分频因子128,时钟周期为4us, TFLG1 = 0xff; // 清除各IC/OC中断标志位 TFLG2 = 0xff; // 清除自由定时器中断标志位 } void main(void) { DisableInterrupts; //禁止所有中断打开 INIT_PLL(); //初始化PLL模块,busclock=32MHz LED_dir = 1; //设置PB0口为输出口 LED = 0; //初始化LED为亮 initialize_ect(); //初始化定时器模块 EnableInterrupts; //允许开启所有中断 for(;;) { TFLG1_C0F = 1; //清除标志位 TC0 = TCNT + 31250; //设置输出比较时间为0.125s while(TFLG1_C0F == 0); //等待,直到发生输出比较事件 TFLG1_C0F = 1; //清除标志位 TC0 = TCNT + 31250; //设置输出比较时间为0.125s while(TFLG1_C0F == 0); //等待,直到发生输出比较事件 TFLG1_C0F = 1; //清除标志位 TC0 = TCNT + 31250; //设置输出比较时间为0.125s while(TFLG1_C0F == 0); //等待,直到发生输出比较事件 TFLG1_C0F = 1; //清除标志位 TC0 = TCNT + 31250; //设置输出比较时间为0.125s while(TFLG1_C0F == 0); //等待,直到发生输出比较事件 LED = ~LED; //反转灯的状态 } } 计数器时钟周期计算: 本例中设置busclock = 32MHz,预分频系数为128 时钟周期 = 128/32MHz = 4μs 输出比较时间计算: TC0存放比较的数字,用当前TCNT的值加上一个数放入TC0,当TCNT循环计数等于TC0时,发生溢出事件,此时向溢出标志位写入1,清除标志位,开始重新计时 比较时间 = 31250 * 4μs = 0.125s 通过四次这样的操作,会产生一个0.5sLED闪烁一次的现象
上一篇:FreeRTOS简单任务调度实现
下一篇:SCI中断接收