从GPIO实现控制LED发光二极管开始说起之四

掌握前面三节的内容我们已经可以解决很多问题了,但是我们会发现还有很多问题,比如说在模拟单总线的时候我们要精确的调整时间,而我们是采用空循环的形式实现时间延时的,具体一次循环会延时多久我们是不知道的,我们常用的做法是一遍遍调整:“觉得”时间短了,循环的次数大写,“觉得”时间长了,循环次数改小些......“觉得”实际上是不可靠的,耗费了你大量的精力在调节参数上,而且将宝贵的计算机运算能力放在空循环上,这不是一种浪费吗?有这个时间计算机做些别的,系统的运行速度不是更快?另外我们看看键盘扫描功能,程序一遍又一遍的查看某些端口,看其是否有信号的变化以判断是否有按键按下,但是实际我们按键的次数是非常有限的,计算机将自己的“精力”放在了查看端口上,这也导致系统效率的下降!你现在发现了这个问题,计算机科学家也发现了这个问题,他们的解决方案就是:在所有计算机系统中必然提供的一种设备---定时计数器,并提供一种机制---中断

1.定时计数器

所谓定时计数器实际上就是数字电路中学习过的计数器:每当输入一个脉冲上,计数器中的值就加1(也有是减1的,加1的叫加法计数器,减1的叫减法计数器)。如果输入的脉冲是周期性的信号,也就是说两个信号之间的间隔(时间)是固定的,那么我们只要知道从开始到现在一共有多少个信号接入了计数器,我们就知道了经过了多少时间。其为定时计数器,其本质就是计数器,当然可以计算一个信号输入了多少个脉冲,定时计数器我们最主要的功能还是定时。更确切的说主要用其时钟(过了多少时间)和闹时功能(到一定时间提醒)。

需要知道时间,首先要考虑的就是周期性信号从何而来?也就是时钟源是什么?我们一般考虑从系统的晶振引入的振荡信号,所有的系统一定是有晶振的(?),晶振为系统中所有的设备提供了统一的时间信号,现在的计算机系统的时钟系统越来越复杂,甚至有不止一个时钟源:系统的内核(CPU)希望速度越快越好,但是外设多种多样,速度千差万别,我们都要满足它们的需要。MCU中不但可能有外部时钟源(包括系统晶振,可能有多个),而且可能有内部时钟源;并且为了系统的可靠性,外部晶振的频率fosc可能比较低,为了获得内核等所需的高频信号,系统还可能有PLL(锁相环)将低频时钟信号变为高频信号,还有所谓的分频、倍频等的设备......但是万变不离其宗,不管如何处理,总是要将一个周期性信号送入计数器中(定时功能输入的信号是标准的脉冲信号,而计数外部脉冲时可能还要涉及滤波、整形等,比如将一个“正弦信号”变成标准的方波信号)。

知道了时钟源我们还需要知道如何启动计数。这是一个开关、按钮。具体的设备各有不同,一般是某个寄存器的某位进行设置即可,也可能是某个设备或端口发出了一个信号,启动了计数器工作,这都有可能,具体不详述。

另外我们还要知道定时器到底记录了多少时间。一般的方法我们是查看计数器的值。但是我们要知道计数器记录的脉冲个数是有极限的,比如8位计数器最多记录255个脉冲,16位计数器65535个脉冲,如果超出怎么办?办法很简单:让计数器多计数几次。我们需要知道一旦计数器达到其上限时,其会溢出,并输出一个信号------溢出信号。以8位加法计数器为例。比如我们需要定时100脉冲,我们可以让计数器从155开始计数,然后我们不断查看(查询)溢出信号的值,当其出现时,我们可以知道已经来100个信号了。如果需要定时1000脉冲呢?我们可以将上述过程重复10遍。

在这里强调一下计数器输出的脉冲还可以有很多用处:触发一个中断,改变特定管脚的值、触发一个事件......它可以像推倒了第一块多米乐骨牌一样,实现很多功能,具体要看系统设置,一般来说我们常见的系统一定提供了计数脉冲触发中断的机制,其他的机制没有提供的话,我们也可以采用中断的方式实现,只是不那么方便和高效而已。

2.中断

中断是什么?中断就是打断,interrupt!实际上这个还是没有解释清楚的。举个例子:我的学生时代,学校很远,我是住校的,每周只能回家一次。每周末我的母亲总是很紧张:她要一遍又一遍的到路口看我有没有回来(每次想起这个场景总是心酸),没看到我回来,她总是心神不宁的,事情也做不好,她这样一遍遍地到路口查看我们称之为“查询”。那么现在如果我要回去怎么办呢?我只要打个电话就可以了,告诉她我什么时候回来,这样一来,电话一响,她就知道我要回来,要到家了,这个可以称为“中断”。

学术化的说:中断是一种打断当前系统正常工作的机制。当中断发生时,系统停止当前工作,处理中断事务,当中断事务处理完成后,系统返回原事务继续执行。在这里大家要记住中断是系统用来与外界交互(人或其他设备),处理随机事件的一种机制,是一种交互手段。其实在CPU的内部还是有一个设备,它一直在监测某个信号(中断信号),一般说来CPU每执行一条指令,该设备查询一次,一旦发现中断信号出现其立刻通知CPU执行中断功能。这实际上是将原来我们赋予CPU的查询功能交给了一个设备执行,让CPU从低价值工作中解脱出来。

另外还有几个概念需要掌握:

中断源:发出中断信号的设备。

中断服务(处理):中断发生时,计算机执行的工作。一般计算机一旦发现有中断发生了,其立刻停止当前工作,并做记录(机器自动完成)以便处理返回时接着处理,这叫中断保存,处理完成后,机器返回接着处理被中断的事务,这叫中断恢复。

中断向量:中断发生后机器首先进行中断保存,然后根据预先的设计,CPU会到指定的地点读取指令(或数据),进行跳转,执行中断服务,这个指定的地址就是中断向量。一般说来机器可以实现多个中断,相应的中断向量就放在一起,形成中断向量表。它们的地址一般比较特殊,如MCS51的中断向量表就放在存储器地址的开头。

中断屏蔽、中断优先级、不可屏蔽中断:中断发生了,我就不想处理它---中断屏蔽。几个中断同时发生了,到底执行谁----谁的优先级高执行谁,高优先级中断可以知道低优先级中断,低优先级中断不可以中断高优先级中断。有些中断你是躲不掉的---不可屏蔽中断。

举个例子:你在做作业(正常事务),你的朋友喊你去打篮球(中断发生),你放下笔,夹好书(中断保存),告诉他:有事在忙!(中断处理)。然后打开书,拿起笔,接着刚才的地方继续写(中断恢复)。也可能你抹不开面子去打球了(中断处理,中断服务),打完球再回来做作业。当也有可能你在打球的时候,你的女朋友来找你去逛街(新中断发生),你如果你重友轻色(女朋友的事优先级低),你根本不理她,继续打球,如果重色轻友(女朋友的事优先级高),你就会停止打球,然后陪女朋友逛街。当然也有可能你认为作业太重要,不想被任何人、任何事打扰,你关掉手机,将自己反锁在房间里(中断屏蔽),一心一意做作业。但世间总有意外:你所在的楼着火了(不可屏蔽中断)......

一般来说,中断管理是分层次的,有三层,也有两层。两层是设备层和内核层,设备有一个中断信号线直接与内核(CPU)相连。这种方式设备与内核高度绑定。三层是在设备和内核之间增加一个中断向量管理器(VIC),这个方式比较灵活,设备更多样化。MCS51采用两层管理。

中断信号从设备发出,经中断向量管理器传到内核(或直接传到内核)。我们可以从设备层面关闭中断,也可以从CPU层面关闭中断,也可以从中断向量管理器关闭中断信号,其中CPU的开关相当于总开关,如果CPU关闭中断了,设备不管如何发出中断信号都没用!

3.实例

MCS51中有两个计数器,每个计数器有4种计数方式(选择太多了),下面分别使用精确延时,以及采用中断发生进行定时。

//系统采用12M晶振,故计计时脉冲周期为1us
//定时器0用于延时,采用16位定时方式
//定时器1用于计数,采用8位自动重装方式

//延时范围为1~65535ns
void delay_ns(unsigned int t){
   //将TMOD的最低位设为01,并且不能影响其他位
   TMOD&=~(3<<0);
   TMOD|=1<<0;
   //设置计数起始值
   TH0=(65535-t)>>8;
   TL0=(65535-t)&0x00FF;
   //启动定时器
   TR0=1;
   while(!TF0);
   TF0=0;
   TR0=0;
}
//延时范围为1~65535ms
void delay_ms(unsigned int t){
   //将TMOD的最低位设为01,并且不能影响其他位
   TMOD&=~(3<<0);
   TMOD|=1<<0;
   //设置计数起始值,定时1ms
   _start:
   t--;
   TH0=(65535-1000)>>8;
   TL0=(65535-1000)&0x00FF;
   //启动定时器
   TR0=1;
   //等待计数结束
   while(!TF0);
   while(t){
     TF0=0;
     goto _start;
   }

}
void time1ISR() interrupt 3{
....
}
void initTimer1(u8 t){
 TMOD&=~(3<<4);//定时器1计数方式清零
 TMOD|=2<<4;//定时器1计数方式2;
 TH1=TL1=t;
};

 *需要注意:对于MCS51而言,当其系统晶振为12Mhz时,意味着其每执行一条机器指令约需要1us时间,所以才有上述的delay_us其精度有较大的误差,计时越短,相对误差越大!甚至难以忍受,可能其计时精度还不如采用空循环,可以考虑采用汇编指令实现或使用C51提供的单指令实现!对于现代MCU基本上实现了单指令周期,即1个系统周期处理一条指令,如LT320T采用8Mh经倍频后72Mhz,每条指令执行时间约为1/72us,与MCS51相比优势明显!其延时函数的调用、执行等花费的时间较少,相对精度高得多!但是即使如此也要做适当的时间补偿,实际应用中可以用示波器等测量具体的延时时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值