从单片机基础到程序框架(全集 2019pdf版).pdf - 第360页

第八十四节: 中断与中断函数。 【84.1 中断。 】 单片机的 “中断 ” 跟日常生活的 “中断” 差不 多, 我正在做 “常事” 的时候, 突然 遇到优先级更 高的 “急 事” ,这 时我必 须先 暂停手 上的 “常 事” ,马上去 处理 突如 其来 的“急 事” , 处理完 “急 事” 再返 回来继 续做 “常事” 。要理解单片机的“中断” ,有六个关键点,第一点是“配置中断” ,第二点是“做常事” ,第三点是 “中断请求” ,第…

100%1 / 836
void main()
{
while(1)
{
switch(Gu8CycleStep)
{
case 0:
Gu32CycleCnt++; //这里就是累 main 函数内部的主循环 while(1)的次
if(Gu32CycleCnt>=CYCLE_SUM) //累计的次数达到设定值 CYCLE_SUM 就跳到下一步骤
{
Gu32CycleCnt=0; //及时清零计数器,为下一步骤的新一轮计数准
P0_0=0; //LED 灯亮。
Gu8CycleStep=1; //跳到下一步骤
}
break;
case 1:
Gu32CycleCnt++; //这里就是累 main 函数内部的主循环 while(1)的次
if(Gu32CycleCnt>=CYCLE_SUM) //累计的次数达到设定值 CYCLE_SUM 就返回上一步骤
{
Gu32CycleCnt=0; //及时清零计数器,为返回上一步骤的新一轮计数准备
P0_0=1; //LED 灯灭。
Gu8CycleStep=0; //返回到上一个步骤
}
break;
}
}
}
【83.3 累计主循环的不足。
上述 83.2 例子中,“累计主循环次数”实现时间延时是一个不错的选择。这种方法能胜任多任务处理的
程序框架,但是本身也有一个小小的不足,比如“阀值 CYCLE_SUM 到底应该取多少才能产生多长的时间”
没有标准的,只能依靠不断上机实验来拿到一个你所需要的数值,这种“不规范”当程序要移植到其它单
片机平台上的时候就特别麻烦,需要重新修正阀值 CYCLE_SUM。除此之外,哪怕在同样的一个单片机里,随
着主函数里任务量的增加,累计一次主循环所消耗的时间长度也会发生变化,意味着靠“累计主循环次数”
所获得的时间也会发生变化而导致不准确,此时,为了保证延时时间的准确性,必须要做的就是再一次修正
“设定累计主循环次数”的阀 CYCLE_SUM,这样显然给我们带来了一丝不便,怎么办?假设单片机没“定
时中断”这个资源,那么这种“累计主循环次数”在多任务处理中确实是不二之选,但是,因为现在几乎所
有的单片机内部都有“定时中断”这个资源,所以,大家不用为这个“不足”而烦恼,我们只要用上本节的
switch 思路,再外加一个“定时中断”,就可以轻松解决此问题,下一节就跟大家讲“定时中断”的内容。
第八十四节: 中断与中断函数。
【84.1 中断。
单片机的“中断跟日常生活的“中断”差不多,我正在做“常事”的时候,突然遇到优先级更高的“急
事”,这时我必须先暂停手上的“常事”,马上去处理突如其来的“急事”处理完“急事”再返回来继续做
“常事”。要理解单片机的“中断”,有六个关键点,第一点是“配置中断”,第二点是“做常事”,第三点是
“中断请求”,第四点是“保护中断现场”第五点是“处理急事,第六点是“返回中断现场”举一个我生
活的例子如下:
第一点:我老婆随时都会打电话给我,所以我的手机 24 小时都打开处于待机的状态。(配置中断
第二点:我正在读一本书《道德经》(做常事)
第三点:当我读到第 18 页的时候,老婆突然给我打电话,让我去幼儿园帮接一下小孩(中断请求
第四点:我在第 18 页里夹了一张书签做标记(保护中断现场)
第五点:我放下手上的书去幼儿园接小孩(处理急事)
第六点:接了小孩,我回来继续打开《道德经》找到书签标记的第 18 (返回中断现场),继续阅读。
上述六点在单片机的 C 语言里,“配置中断”放在主函数的初始化那里,“做常事”放在主函数的主
环里(main 函数内部的 while(1)循环)“中断请求”单片机内部硬件检测到符合发生中断的条件“保护中
断现场”是单片机内部硬件电路自动处理的(不需要我们软件干涉)“处理急事是单片机自动跳转到另
开辟的一个特殊中断函数处理(自动跳转是单片机的硬件自动完成不需要我们软件干涉),执行完一次中断
函数后单片机再自动跳转到主函数的主循环的现场点继续从现场点开始继续做常事(返回中断现场)。在这
六点中,其中第四点的“保护中断现场”与第六点的“返回中断现场”是要特别强调的,单片机从 main
数的主循环 while(1)准备跳转到中断函数之前,它会自动记录当前的位置(做好路标,以便处理完中断函
数后再返回 main 函数的主循 while(1)时,能找到之前的被中断跳转前的位置,这样就可以接上原来的步
骤去处理原来的“常事,在步骤上既不提前也不滞后恰到好处,中断就不会影响到常事的完整性。代码
布图的模板描述如下:
void main()
{
配置中断;
while(1)
{
处理常事;
}
}
void 中断函数() interrupt 序号 //中断函数后缀带“interrupt 序号”特别修饰
{
急事;
}
奇怪!上述代码,为什么“main 函数”与“中断函数”在软件上看不到任何关联,既不存在“main
数”调用“中断函数”也不存在“中断函数”调用“main 函数”的情况,在观感上“main 函数”与“中
断函数”仿佛是隔离的毫无“物理连接”的,为什么单片机还能在“main 函数”“中断函数”两者中切换
自如?没错,确实,“main 函数”与“中断函数”在书写上是隔离的毫无关联的,但是它们之间之所以能相
互切换,是因为背后有一只无形的手在自动操控这一切,这只手就是单片机硬件自身,这是一种特殊机制,
也可以理解成一种特殊的游戏规则,我们只要遵守就好了,除了普通函数,其它凡是中断函数的,都不用
main 函数发生软件上的关联调用,它们之间的切换都是硬件自动完成的,这就是 main 函数与中断函数的
殊跳转机制(或者称为游戏规则也可以
【84.2 常用的中断函数有哪三类?】
单片机的中断有很多,但常用在项目上的有三类:
第一类是定时中断。配置中断后,使其每隔一段时间就产生一次中断,比如“1ms 一次的定时中断”几
乎是所有的系统里的标配,因为它对程序框架起到一个时间节拍的作用。
第二类是通讯中断。比如串口每接收完一个字节就会产生一个中断通知我们去处理。
第三类是电平变化的中断。下降沿或者上升沿的中断,常常用在采集高速的脉冲信号。
【84.3 我们如何操控中断?】
刚才 84.1 提到“单片机硬件自动”这个概念,但是说它“硬件自动”并不意味着它不可控。单片机
身出厂的时候内部就携带了很多种类的中断,这些中断是否开启取决于你的“配置中断”代码,你要开启或
者关闭某类中断,只需编写对应的“配置中断”代码就可以,而“配置中断”的代码本质就是填写某些寄存
器数值。