学习目标:I/O口的配置,掌握定时器1的模模式,两种实现方式,查询方式和中断方式
【模模式】:
当定时器运行在模模式,16位计数器从0x0000开始,每个活动时钟边沿增加1。当计数器达到T1CC0,寄存器T1CC0H:T1CC0L保存的最终计数值,计数器将复位到0x0000,并继续递增。如果定时器开始于T1CC0以上的一个值,当达到最终计数值(0xFFFF)时,设置标志IRCON.T1IF和T1STAT.CH0IF(注意不是T1STAT.OVFIF)。如果设置了相应的中断屏蔽位TIMIF.OVFIM、T1CCTL0.IM、IEN1.T1EN和总中断IEN0.EA,计数器溢出将产生一个中断请求。模模式可以用于周期不是0xFFFF的应用程序。
使用模模式时,必须要开启通道0的输出比较功能,所以,此时不仅仅只是简单的中断溢出。主要的注意事项如下:
1) 模模式需要开启通道0的输出比较模式,否则计数器到了0xFFFF时,才会产生溢出中断,也就是说如果没有设置通道0的输出比较模式,计数器的值到了T1CC0H:T1CC0L设置的比较值后也不会产生溢出中断。
2) T1的模模式不是普通的溢出中断,和连续计数模式不同,它必须设置通道0的输出比较功能,使能中断时,也是使能通道0的输出比较中断屏蔽位。产生中断时的中断标志也是通道0的输出比较中断标志,而不是计数溢出标志。
计数器的操作展示如下图:
模模式查询方式下,初始化程序
1 1 /****************************************************************************** 2 2 *函 数 名:InitT1 3 3 *功 能:定时器1初始化,系统不配置时钟默认2分频,即16M 4 4 *入口参数:无 5 5 *出口参数:无 6 6 ******************************************************************************/ 7 7 void InitT1(void) 8 8 { 9 9 T1CTL = 0x0e; //定时器1设置为128分频,模计数器模式 10 10 T1CC0L = 0xff; //模值1024,定时器1通道0捕获/比较值低位 11 11 T1CC0H = 0x9f; //定时器1通道0捕获/比较值高位 12 12 T1CCTL0 = 0x44; //通道0比较功能,并且开通道0中断 13 13 T1STAT = 0X21; //通道0,中断有效。这一句在裸机程序中可有可无 14 14 }
1 1 /****************************************************************************** 2 2 *程序入口函数 3 3 ******************************************************************************/ 4 4 int main(void) 5 5 { 6 6 InitClock(); 7 7 InitLED(1); //LED初始化,熄灭LED1 8 8 InitT1(); //定时器1初始化 9 9 10 10 while(1) 11 11 { 12 12 if(T1STAT & (1<<0)) //检测定时器1通道0是否中断 13 13 { 14 14 T1STAT &= ~(1<<0); //清中断标志 15 15 LED1 = !LED1; //LED闪烁 16 16 } 17 17 } 18 18 }
这里判断的是T1STAT.CH0IF(定时器1通道0中断标志),经过实验验证也可以判断IRCON.T1IF(定时器1中断标志)。
定时器初始化程序
1 /****************************************************************************** 2 *函 数 名:InitT1 3 *功 能:定时器1初始化,系统不配置时钟默认2分频,即16M 4 *入口参数:无 5 *出口参数:无 6 ******************************************************************************/ 7 void InitT1(void) 8 { 9 T1CTL = 0x0e; //定时器1设置为128分频,模计数器模式 10 T1CC0L = 0xff; //模值1024,定时器1通道0捕获/比较值低位 11 T1CC0H = 0x9f; //定时器1通道0捕获/比较值高位 12 T1CCTL0 = 0x44; //通道0比较功能,并且开通道0中断 13 T1STAT = 0X21; //通道0,中断有效。这一句在裸机程序中可有可无 14 TIMIF |= (1<<6); //定时器1溢出中断使能 15 IEN1 |= (1<<1); //定时器1中断使能 16 EA = 1; //开总中断 17 }
中断服务程序
1 /****************************************************************************** 2 *函 数 名:Timer1_ISR 3 *功 能:定时器1中断服务程序 4 *入口参数:无 5 *出口参数:无 6 ******************************************************************************/ 7 #pragma vector = T1_VECTOR 8 __interrupt void Timer1_ISR(void) 9 { 10 LED1 = !LED1; 11 IRCON &= ~0x02; 12 T1STAT &= ~0x01; 13 }
第12行产生的中断是定时器1通道0中断,而不是定时器1的溢出中断,故只需要清除T1STAT的第1位,不需要清除第5位