原创 与张工探讨“完善的中断源查询方法”的判别次序及效率问题

2007-1-16 00:33 4763 7 7 分类: MCU/ 嵌入式
与张工探讨“完善的中断源查询方法”的判别次序及效率问题
mood25.gif hotpower 发表于 2004-9-25 01:31 PIC 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴


在<入门与实战>的例6-8中,张工祥述了"不完善的中断源查询方法"的误触发问题. 这是习惯51中断体系的编程者最容易"误伤友军"的一大隐患.

非常实用,但我个人认为次序应该倒一下,这样可以提高程序的效率.

人们的习惯为先判使能后判触发,但中断使能后一般永远不会"自毁",即为"常数".

而中断触发却是随机的.故还是先判触发后判使能较好些.

即:
if (T0IF && T0IE) {
  T0IF = 0;
  Int_TMR0();
}
else if (INTF && INTE) {
  INTF = 0;
  Int_RB0();
}

又因为PIC中档机中断优先级本就是用户的判别次序,故同级时,可改为
if (T0IF && T0IE) {
  T0IF = 0;
  Int_TMR0();
}
if (INTF && INTE) {
  INTF = 0;
  Int_RB0();
}

if (INTF && INTE) {
  INTF = 0;
  Int_RB0();
}
if (T0IF && T0IE) {
  T0IF = 0;
  Int_TMR0();
}

个人意见,不知张工意下如何???

http://www.21icbbs.com/club/bbs/ShowAnnounce.asp?v=&ID=1377695

再聊中断响应频率及中断服务程序时间和判别次序的关系
mood25.gif hotpower 发表于 2004-9-25 08:10 PIC 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴


还以上2个示例来"聊天".

例:
if (T0IF && T0IE) {
  T0IF = 0;
  TMR0 = NewTimeVal;
  Int_TMR0();
}
else if (INTF && INTE) {
  INTF = 0;
  Int_RB0();
}

可以看出,TMR0比RB0中断优先.看似程序没问题,Int_RB0()函数应该得到"服务".
但当TMR0定时间隔(-NewTimeVal)低于或接近Int_TMR0()函数运行时间时,Int_RB0();函数将会"长眠地下","永不超生"...

同理,将其顺序颠倒,即
if (INTF && INTE) {
  INTF = 0;
  Int_RB0();
}
else if (T0IF && T0IE) {
  T0IF = 0;
  TMR0 = NewTimeVal;
  Int_TMR0();
}

若RB0老发"密电码",Int_TMR0()函数也同样"喝西北风"!!!
所以,中断服务程序中的else及xxIF,xxIE之间的关系很微妙,不能马虎!!!


中断服务程序的分割运行问题
mood25.gif hotpower 发表于 2004-9-25 09:08 PIC 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴


以键扫描及动态显示刷新为例:

如果将KeyScan()及Dispay()按顺序植入到TMR0中,对于其他中断服务程序是"非人道"的一件事情.
所以,一般与张工的11.4 C框架基本雷同.

但对于我们这些"中断追星族"来说看来是件"难事".(至少不想改掉此恶习)

以8键8LED为例:
动态显示刷新频率一般定在50Hz即20mS较好,而键抖动的消抖时间恰好也在20mS左右.这样想来,KeyScan()及Dispay()真是天公做媒的一对"新人"...

如果将TMR0的定时时间设为20mS/键盘个数,即20/8=2.5mS中断一次.
每次TMR0中断时,其进入次数计数器CNT_TMR0都+1.(CNT_TMR0只取低3位)

那么,一个"美妙的事情"发生了--键盘消抖时间被蒸发了...

原来,由于采用20mS/键盘个数,每次中断只依次扫描一个键,等全部扫描完时及某键20mS到时,某次键2次的扫描间隔恰好就是20mS.
这样原本需要键盘消抖等待的20mS就让个了其他的7个键用于扫描.

那么,其键盘号即为TMR0的计数值CNT_TMR0.也省去了键值寄存器.
若每键再设一个压键次数计数器KeyCnt[n].
若KeyCnt[CNT_TMR0]=0表示某键没压下或键释放,KeyCnt[CNT_TMR0]=2时表示键刚发生压键事件,当KeyCnt[CNT_TMR0]>=长压键时间/2.5mS时,表示有长压键事件发生.

用这种方式做出来的键手感很好,没有误动作...
而且键扫描时间基本上是原来KeyScan()函数的1/n.

再论动态显示刷新问题.
同理,动态显示刷新时间为20mS/动态显示刷新位.
故动态显示刷新位也就是TMR0的计数值CNT_TMR0.
这样显示缓冲区LedBuff[]显示某位时,显示值即为LedBuff[CNT_TMR0].



就到这里,让张工见笑了...

中断服务程序的分割运行问题
mood25.gif hotpower 发表于 2004-9-25 09:08 PIC 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴


以键扫描及动态显示刷新为例:

如果将KeyScan()及Dispay()按顺序植入到TMR0中,对于其他中断服务程序是"非人道"的一件事情.
所以,一般与张工的11.4 C框架基本雷同.

但对于我们这些"中断追星族"来说看来是件"难事".(至少不想改掉此恶习)

以8键8LED为例:
动态显示刷新频率一般定在50Hz即20mS较好,而键抖动的消抖时间恰好也在20mS左右.这样想来,KeyScan()及Dispay()真是天公做媒的一对"新人"...

如果将TMR0的定时时间设为20mS/键盘个数,即20/8=2.5mS中断一次.
每次TMR0中断时,其进入次数计数器CNT_TMR0都+1.(CNT_TMR0只取低3位)

那么,一个"美妙的事情"发生了--键盘消抖时间被蒸发了...

原来,由于采用20mS/键盘个数,每次中断只依次扫描一个键,等全部扫描完时及某键20mS到时,某次键2次的扫描间隔恰好就是20mS.
这样原本需要键盘消抖等待的20mS就让个了其他的7个键用于扫描.

那么,其键盘号即为TMR0的计数值CNT_TMR0.也省去了键值寄存器.
若每键再设一个压键次数计数器KeyCnt[n].
若KeyCnt[CNT_TMR0]=0表示某键没压下或键释放,KeyCnt[CNT_TMR0]=2时表示键刚发生压键事件,当KeyCnt[CNT_TMR0]>=长压键时间/2.5mS时,表示有长压键事件发生.

用这种方式做出来的键手感很好,没有误动作...
而且键扫描时间基本上是原来KeyScan()函数的1/n.

再论动态显示刷新问题.
同理,动态显示刷新时间为20mS/动态显示刷新位.
故动态显示刷新位也就是TMR0的计数值CNT_TMR0.
这样显示缓冲区LedBuff[]显示某位时,显示值即为LedBuff[CNT_TMR0].



就到这里,让张工见笑了...

"中断处理的精干和快速"是可以通融一些的
mood25.gif hotpower 发表于 2004-9-25 11:11 PIC 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴


对于现代MCU来说,定时中断服务可谓是"MCU之魂魄",合理利用及适当分割是可以"还魂"的...

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条