跳过中断直接讲TM中断是不是有些超前了?
由于最近参加了一个项目,真是忙的不要不要的,没办法,只有抽了点放假的时间来更新下自己的博文,希望对正在学习HT单片机的同学有帮助。
重庆合泰初赛是5月15日,嗯,大概还有1个月时间。希望自己小组能顺利通过初赛,也不枉我这几周对HT单片机的学习。
(声明下,这篇博文是我在完成外部中断情况下来讲述的,如果不知道的还是先看看手册,因为我在使用时中间出了点小问题,所以暂时先不更新外部中断。后面更新了(三)就可以忽略此信息。)
前文有讲过,任何关于单片机开发,或者外设都离不开手册的说明,这次也不例外。
而本次实验并不需要任何外设,依然会用前面博文(一)中的2个LED灯进行。
1、先讲述下什么时候会用到TM定时器。
学过51的肯定都做过这个led闪烁的实验(HT与51的定时器区别真的不是一般的大)。然而没做过项目的可能只是粗略的了解了一下,而做过项目的肯定知道TM定时器,比如超声波测距(这个实验在我项目之内,后面我会看情况更新),这便是运用了TM计数功能,单片机内部计数从发送超声波到接收超声波时间,然后用公式S=340*t/2便可算出距离。而计时功能主要用于中断的产生,每过多少时间就会进入中断产生其他操作,就比如每过1ms就让超声波发一次波。有人就会问了,为什么不用GCC_delay()函数?有这些问题的人,大可去试试,的确也能完成简单的操作,但是更为复杂的操作就不行了。
下面我只截手册上有用的信息,其他信息就自己多看看TM定时器与中断部分。
2、
有些理论得知道,HT单片机中的TM定时器有3中类型,分别是简易、标准、增强型,只要了解了简易型,其他两种基本能随意上手,它们三种有功能的限制,具体是哪些,就请自己看看手册。本次实验用的是简易型的TM0,那么10bit CTM是什么意思,就是10位,这个先了解,下面会仔细的讲解。
3、
TM中断,在讲此之前请不要用51的思想去理解。
HT内部中有比较器,比较器就是用来对比电压的,超过某个电压就会出现警报之类的,也可以用来进行计数器的对比,TM计数器都是从0开始向上计数,当计数器的值与比较器预设的值相同时,就会触发中断,计数器清零,从新开始计数。本次实验用的简易型TM定时/计数器,所以比较器只能用A或P。(计数器=计时器)
比较器这个东西先不用管。
放上此图,方便理解。
4、经过上面讲解大概知道了TM定时器的一些基本内容。
下面便开始讲解一些寄存器,此内容关系到如何编程。
这是TM总的寄存器。就比如目录一样。其中TMnC0(n=0,1,2,3)与TMnC1最为重要。
我先放上我自己的TM初始化程序,一一进行讲解。
void tm_init(void)
{
_tm0c0=0x00; //TM0 FSYS/4=0.5us
_tm0c1=0xc1; //定时/计数器模式与A配对
_tm0al=0x8f;
_tm0ah=0x03; //比较器初值d1000
_t0on=1; //开定时器
_t0ae=1; //tm0,比较器A中断使能
_mf0e=1; //多功能中断使能
_emi=1; //开总中断
}
(提醒:在HT编译软件中,每用到内部程序,都会以_xxxx的形式出现)
TMnC0:
结合我的程序:
_tm0c0=0x00;(0000 0000)
其他的可以先不看,我只讲下bit 6~4 位时什么意思,即选择时钟位是什么意思,在博文(一)我就计算过一次频率,这里依然是计算频率,fsys是什么意思,看过我第一篇博文的都有印象吧。
这里就不废话了,直接告诉结论:bit 6~4位选择000,即fsys/4。注释中fsys/4=0.5us,意思就是计数器加一个1花了0.5us。如果想用其他时钟,可以自己去计算一下时间。
TMnC1:
结合我的程序:
_tm0c1=0xc1;(1100 0001)
其他自己看下,只需记住最后一位是1,即选择了TM0与比较器A配对。
既然选择了与比较器A配对,那么就要设置比较器A的预设值。
可以看出比较器A有2个寄存器,TMnAL(n=0,1,2,3)、TMnAH。其中L是低8位,H是高2位,所以比较器A是10位的,记忆力好的可以还记得TH0也是10位的。
10位是什么意思?就是计数器中00 0000 0000开始计数到11 1111 1111就满了,就会溢出,产生未知的中断。
看上面的程序可以知道我给的是1000,就是表示每过0.5us*1000=0.5ms就会产生一次中断。
TnON是寄存器TMnC0的一部分,即寄存器里面的8位可以单独拿出来赋值。
TnON=1用于打开定时器。
定时器讲完了,就开始讲中断了。
我只截图重要部分,后面有时间我会将外部中断部分补上。
下面截图要结合我的程序对应着看。
为什么要开多功能中断?看下图,,,- -!我没找到图,我清楚的记得,TM中断也属于多功能中断。
到此为止,基本是就知道了TM定时器该怎么初始化了。
下面开始将中断服务程序。(跳过了中断真还不好讲呢。。。)
放上我的程序:
void __attribute((interrupt(0x14))) tim_int(void)
{
_emi=0; //关总中断
_t0af=0; //清除TM2比较器A中断标志位
i--;
if(!i){
_pf=~_pf;
i=2000;
}
_emi=1; //开总中断
}
中断服务程序名函数格式为:void __attribute((interrupt(0x14))) tim_int(void),不多讲,不懂的自己看V3手册或者等更新外部中断。 - -。 V3手册在前面介绍过。
中断程序功能说明:每进入一次中断i就会加1,直到加了2000次,即一秒,便会是led闪烁。
注意两点:
1、进入一个中断服务程序后必须关掉中断,防止进入其他程序中。
2、标志位必须手动清除。
放上剩下的程序:
#include "HT66F70A.h"
#include "type.h"
volatile unsigned int i;
unsigned char num,flag,x;
void main(void)
{
_pfc=0x00; //输出模式
_wdtc=0b10101011; //关狗
tm_init(); //tm0初始化
i=2000;
_pf=0x00; //关LED
while(1);
}
main中的功能主要是初始化功能。
至此,TM定时器中断led灯1s闪烁实验便结束了。
总结下:
1、HT与51定时器有一丢丢相似,51是直接直接给计数器赋值后等计数溢出便进入中断,而HT是与比较器对比,相同后才进入中断,HT的计数器只能读,不能去修改它,这就是我最开始最不明白的一点,不能修改计数器怎么计数?
2、因为TM定时器非常复杂,牵扯到了比较器,中断,与时钟频率,导致初学者不能很快的上手,博主也是花了一周左右才入了门。提醒下,就是手册中会有单独来讲比较器与振荡器,其实这两部分根本不用去管。我虽然看完了,但最后发现根本没用到。
3、关于中断的问题,希望大家先实现了外部中断,或者其他中断实验的基础上再学习TM中断,不然的话会非常复杂难懂。
关于上文提到的超声波测距,看情况更新吧。
在此希望本博文对大家学习有所帮助。