[经验] 【我是电子发烧友】PIC单片机引脚中断程序设计技巧

[复制链接]
发表于 2017-5-10 14:52:40   1189 查看 16 回复 显示全部楼层 倒序浏览
分享
所有的中档系列PIC单片机,PORTB端口最高的4个引脚(RB7~RB4)在设为输入模式时,当输入电平由高到低或由低到高发生变化时,可以让单片机产生中断。这就是通常所说的引脚状态变化中断。

在设计引脚中断程序时,有三个需要特别注意的地方:


一是,在清除P0RTB中断标志位RBIF之前,必须安排一条必不可少的,以PORTB端口数据寄存器PORTB为源寄存器的读操作指令。放置这一指令的目的有时并不只是为了读取有用的数据,而是为了取消状态变化的硬件信号,以便顺利清除RBIF标志位,为下一次中断做好准备。

二是,由于端口PORTB是引脚电子变化中断,即无论引脚出现上升沿还是下降沿都会产生中断请求,所以必须处理好不需要的虚假中断。

三是,一般都利用PIC单片机的引脚功能来检测按键,所以必须处理好按键消抖的问题。

引脚中断程序设计
  1. <font size="4">在主程序里先设置有关的寄存器:
  2. 设置TRISB寄存器,使RB7~RB4相关的引脚处于输入状态;
  3. 如果需要弱上拉,通过OPTION_REG的第7位设置;
  4. RBIF=O;
  5. RBIE=1;
  6. GIF=1。</font>
复制代码

  1. <font size="4">响应状态变化后的中断服务程序:
  2. 检查RBIF是否为l,为l则是引脚变化引起的中断;
  3. 调用延时程序,延时20~30 ms,目的是为了按键去抖;
  4. 判断是引脚出现上升沿还是下降沿引起的中断;
  5. 调用按键处理程序;
  6. 读PORTB口的值,取消状态变化的硬件信号;
  7. 清除RBIF标志。</font>
复制代码

上面程序设计最大的问题是在中断程序里调用延时程序。大家知道,中档PIC单片机只有8层深度的硬件堆栈,在中断里调用于程序出现极易堆栈溢出的情况。


另外,PIC单片机中断程序入口只有一个,在响应中断的请求时,PIC单片机就会自动把全局中断的使能位(INTCON的第7位GIF)清除,这样其他中断就暂时不能被响应(此时,如果别的中断发出的中断请求,标志位将一直保留着),直到这个中断程序退出后才会得到响应。这就要求我们设计中断程序的时候必须尽量短,避免调用子程序,更不要在中断里进行复杂的运算。

下边开始说重点

当引脚状态变化引起中断时,在中断子程序里首先判断引起中断的原因是不是我们需要的变化引起的中断。如果是,不要在这里延时,而是设置一个标志位,接着清除中断标志,退出中断。中断程序如下:

  1. <font size="4">else if((RBIE&RBlF)==1){ //如果引脚变化引起中断
  2.     if(RB4==0){ //RB4上的按钮接地
  3.     key=1; //按键标志位置位
  4.     }
  5.     RBIF=0; //清除引脚中断标志位
  6.     }</font>
复制代码
其中,if(RB4==0)语句相当于读取了PORTB端口数据寄存器,取消了状态变化的硬件信号。

下面详细介绍怎么样进行按键去抖。

首先,在定时器中断里设置一个lms的时间基准标志位“SYSlms”,每到lms,“SYSlms”便置位。程序如下:

  1. <font size="4">unsigned char count;
  2.     if((ToIE&TOIF)==1){ //定时器中断
  3.     TMRO+=0x09; //每250μs中断一次
  4.     if(count==4){
  5.     count=0;
  6.     SYSlms=l; //系统时间标志
  7.     couot++;
  8.     }   
  9.     T0IF=0; //清除时钟中断标志位
  10.     }</font>
复制代码
有了这个时间基准,便可以在主程序里进行按键去抖处理了。为了更好地利用这个时间基准,定义一个消息标志SYSTime,笔者把它称作时间消息。为了让这个消息有自我发布和自我消失的功能.定义了如下一个宏:
  1. <font size="4">bit SYSTime;
  2.     #defincTimeEnahle()SYSTime=0,if(SYSlms){SYSTime=l;SYSlms=0;)</font>
复制代码
可以把TimeEnable()放到主程序死循环的任何地方,每当程序执行这个宏,SYSTime就会清零,这就是标志位的自我消失.如果在定时器时间基准标志位SYSlms已经置位的话,SYSTime就会置1,这样别的程序就可以利用这个时间消息了,这就是消息的自我发布。下面就是利用这个时间消息来进行按键延时去抖的,首先看一下按键扫描子程序;
  1. <font size="4">  void seaakey(){
  2.     unsigned char KeyTime,KeyTask;//定义任务时间参数、
  3.     //任务参数
  4.     switch(KeyTask){
  5.     case0:if(key){
  6.     KeyTime=30; //准备延时30 ms
  7.     KeyTask++; //准备好下一个任务
  8.     kcy=0;
  9.     }
  10.     break;
  11.     case I:KeyTime--; //延时30 ms
  12.     if(KeyTime==0)Key+ask++;
  13.     break;
  14.     case2;if(RB4==o){
  15.     //调按键处理程序
  16.     KeyTask=0;
  17.     }
  18.     else KeyTask=0;//退出任务
  19.     break;
  20.     }
  21. }</font>
复制代码
在主程序的死循环中这样用:
  1. <font size="4"> while(1){
  2.     TimeEnable();
  3.     If(SYSTime==1){scankey();)
  4.     //在此可以添加其他程序</font>
复制代码
只有有时问消息的时候才执行按键扫描程序。可以看到,进入扫描程序执行第一次的时候,程序首先判断按键标志位有没有置位,置位的话(也就是有按键按下的话),任务时间参数(KeyTime)赋值为30,这是延时30ms,去抖,当然你也可以设置为其他的时间值,同时任务参数 (KeyTask)加1。1ms后,再进入扫描程序,这个时候扫描程序执行case l的语句,这样30次后(延时了30ms),任务参数(KeyTask)加1,值为2。lms后,再进入扫描程序,将执行case 2的语句,首先在这里再次判断是不是按键还在按下,如果是就调按键的处理程序,如果不是。就退出按键扫描程序。在这里,还可以加入按键是否抬起的判断程序。

这样设计的引脚变化程序,CPU开销小,效率高,不会出现堆浅溢出的问题,提高了系统的实时性。



标签:单片机 发烧友

版主

发表于 2017-5-10 15:06:09  

回帖奖励 +1 分积分

  中断讲解的很好
回复

点赞 举报

发表于 2017-5-10 16:29:34    楼主|

PCB在线计价下单

板子大小:

cm
X
cm

层数:

2

板子数量:

10

厚度:

1.6

感谢版主支持
回复

点赞 举报

发表于 2017-5-10 18:52:02  

回帖奖励 +1 分积分

感谢版主
回复

举报

技术员

发表于 2017-5-10 21:14:52  

回帖奖励 +1 分积分

不错不错,点赞点赞。
回复

点赞 举报

总工程师

发表于 2017-5-10 21:54:31  

回帖奖励 +1 分积分

不了解     不过不妨碍学习了解一下
回复

点赞 举报

发表于 2017-5-10 22:02:08    楼主|
王栋春 发表于 2017-5-10 21:54
不了解     不过不妨碍学习了解一下

单片机里最重要的环节之一
回复

点赞 举报

高级工程师

发表于 2017-5-10 22:15:22  

回帖奖励 +1 分积分

加强学习中。。。。。
回复

点赞 举报

总工程师

发表于 2017-5-11 03:53:30  
24不可说 发表于 2017-5-10 22:02
单片机里最重要的环节之一

这个是知道的    慢慢学吧
回复

点赞 举报

工程师

发表于 2017-5-11 10:13:15  

回帖奖励 +1 分积分

了解了,挺好的!!!!!!!!
回复

点赞 举报

发表于 2017-5-11 14:58:48  

回帖奖励 +1 分积分

学习学习
回复

举报

高级工程师

发表于 2017-5-11 22:49:30  
不错,学习一下。。。。。
回复

点赞 举报

发表于 2017-5-12 17:48:30  

回帖奖励 +1 分积分

很实用,收藏了。
回复

点赞 举报

实习生

发表于 2017-5-13 16:41:12  

回帖奖励 +1 分积分

很实用!
回复

举报

助理工程师

发表于 2017-5-13 16:53:19  

回帖奖励 +1 分积分

写的非常不错,很好
回复

点赞 举报

技术员

发表于 2017-5-16 08:34:07  
受益匪浅,感谢版主分享!
回复

点赞 举报

资深工程师

发表于 2017-6-9 11:54:04  
我们不会创造,而会仿照
回复

点赞 举报

高级模式
您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐 上一条 /9 下一条

快速回复 返回顶部 返回列表
-

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

我的提问

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

ARM技术论坛

Android论坛

Linux论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

无线充电技术

-

硬件设计论坛

PCB设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PADS技术论坛

Protel|AD|DXP论坛

Allegro论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

Orcad论坛

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

厂商专区

TI论坛

TI Deyisupport社区

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区