历史上的今天
返回首页

历史上的今天

今天是:2025年02月06日(星期四)

正在发生

2020年02月06日 | PIC单片机中断程序的设计技巧总结

2020-02-06 来源:eefocus

所有的中档系列PIC单片机,PORTB端口最高的4个引脚(RB7~RB4)在设为输入模式时,当输入电平由高到低或由低到高发生变化时,可以让单片机产生中断。这就是通常所说的引脚状态变化中断。


在设计引脚中断程序时,有三个需要特别注意的地方。一是,在清除P0RTB中断标志位RBIF之前,必须安排一条必不可少的,以PORTB端口数据寄存器PORTB为源寄存器的读操作指令。放置这一指令的目的有时并不只是为了读取有用的数据,而是为了取消状态变化的硬件信号,以便顺利清除RBIF标志位,为下一次中断做好准备。二是,由于端口PORTB是引脚电子变化中断,即无论引脚出现上升沿还是下降沿都会产生中断请求,所以必须处理好不需要的虚假中断。三是,一般都利用PIC单片机的引脚功能来检测按键,所以必须处理好按键消抖的问題。


在主程序里先设置有关的寄存器。

◇设置TRISB寄存器,使RB7~RB4相关的引脚处于输入状态;

◇如果需要弱上拉,通过OPTION_REG的第7位设置;

◇RBIF=O;

◇RBIE=1;

◇GIF=1。


响应状态变化后的中断服务程序。

◇检查RBIF是否为l,为l则是引脚变化引起的中断;

◇调用延时程序,延时20~30 ms,目的是为了按键去抖;

◇判断是引脚出现上升沿还是下降沿引起的中断;

◇调用按键处理程序;

◇读PORTB口的值,取消状态变化的硬件信号;

◇清除RBIF标志。


笔者认为上面程序设计最大的问题是在中断程序里调用延时程序。大家知道,中档PIC单片机只有8层深度的硬件堆栈,在中断里调用于程序出现极易堆栈溢出的情况。另外,PIC单片机中断程序人口只有一个,在响应中断的请求时,PIC单片机就会自动把全局中断的使能位(INTCON的第7位GIF)清除,这样其他中断就暂时不能被响应(此时,如果别的中断发出的中断请求,标志位将一直保留着),直到这个中断程序退出后才会得到响应。这就要求我们设计中断程序的时候必须尽量短,避免调用子程序,更不要在中断里进行复杂的运算。


下面给出笔者设计程序时的思路。


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

else if((RBIE&RBlF)==1){ //如果引脚变化引起中断

if(RB4==0){ //RB4上的按钮接地

key=1; //按键标志位置位

}

RBIF=0; //清除引脚中断标志位

}


其中,if(RB4==0)语句相当于读取了PORTB端口数据寄存器,取消了状态变化的硬件信号。


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


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

unsigned char count;

if((ToIE&TOIF)==1){ //定时器中断

TMRO+=0x09; //每250μs中断一次

if(count==4){

count=0;

SYSlms=l; //系统时间标志

couot++;

}

T0IF=0; //清除时钟中断标志位

}


有了这个时间基准,便可以在主程序里进行按键去抖处理了。为了更好地利用这个时间基准,定义一个消息标志SYSTime,笔者把它称作时间消息。为了让这个消息有自我发布和自我消失的功能.定义了如下一个宏:

bit SYSTime;

#defincTimeEnahle()SYSTime=0,if(SYSlms){SYSTime=l;SYSlms=0;)


可以把TimeEnable()放到主程序死循环的任何地方,每当程序执行这个宏,SYSTime就会清零,这就是标志位的自我消失.如果在定时器时间基准标志位SYSlms已经置位的话,SYSTime就会置1,这样别的程序就可以利用这个时间消息了,这就是消息的自我发布。下面就是利用这个时间消息来进行按键延时去抖的,首先看一下按键扫描子程序;

void seaakey(){

unsigned char KeyTime,KeyTask;//定义任务时间参数、

//任务参数

switch(KeyTask){

case0:if(key){

KeyTime=30; //准备延时30 ms

KeyTask++; //准备好下一个任务

kcy=0;

}

break;

case I:KeyTime--; //延时30 ms

if(KeyTime==0)Key+ask++;

break;

case2;if(RB4==o){

//调按键处理程序

KeyTask=0;

}

else KeyTask=0;//退出任务

break;

}

}


在主程序的死循环中这样用:

while(1){

TimeEnable();

If(SYSTime==1){scankey();)

//在此可以添加其他程序


只有有时问消息的时候才执行按键扫描程序。可以看到,进入扫描程序执行第一次的时候,程序首先判断按键标志位有没有置位,置位的话(也就是有按键按下的话),任务时间参数(KeyTime)赋值为30,这是延时30ms,去抖,当然你也可以设置为其他的时间值;同时任务参数 (KeyTask)加1。1ms后,再进入扫描程序,这个时候扫描程序执行casel的语句,这样30次后(延时了30ms),任务参数(KeyTask)加1,值为2。lms后,再进入扫描程序,将执行case 2的语句,首先在这里再次判断是不是按键还在按下,如果是就调按键的处理程序,如果不是。就退出按键扫描程序。在这里,还可以加入按键是否抬起的判断程序。


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

推荐阅读

史海拾趣

Feller US公司的发展小趣事

在电动汽车领域,技术创新是企业生存和发展的关键。菲斯克一直致力于研发更加先进、更加环保的电动汽车技术。经过多年的努力,公司终于在某项关键技术上取得了重大突破。这一突破不仅提升了电动汽车的性能和续航里程,还为公司赢得了市场的广泛认可。菲斯克凭借这一技术优势,成功推出了一系列备受好评的电动汽车产品,进一步巩固了其在市场中的地位。

安谱隆(Ampleon)公司的发展小趣事

在安谱隆的发展历程中,资本市场对其一直保持着高度的关注。然而,其“安家”之路却并不平坦。2017年,奥瑞德曾有意收购安谱隆,但由于资金问题,这桩收购最终未能成行。2018年,旋极信息也计划收购安谱隆,但同样未能成功。这些波折反映了资本市场对安谱隆价值的认可,但也暴露出安谱隆在寻找合适买家方面所面临的挑战。

Engineered Components Co公司的发展小趣事

在稳固了国内市场后,ECC开始积极拓展国际市场。他们参加了多个国际电子展会,展示了公司的技术和产品。通过与国际客户的交流与合作,ECC逐渐打开了国际市场的大门。同时,ECC还与国际知名电子企业建立了长期合作关系,共同研发新产品、开拓市场。这些举措使得ECC在国际市场上的知名度不断提升。

ARBOR公司的发展小趣事

ARBOR公司深知合作的重要性,积极与上下游企业建立紧密的合作关系。公司通过与供应商和客户建立长期稳定的战略合作关系,实现了资源共享和优势互补。这种合作模式不仅降低了公司的运营成本,也提高了产品的竞争力。同时,ARBOR公司还积极参与行业交流活动,推动整个电子产业的健康发展。

Aplus Flash Technology Inc公司的发展小趣事

Aplus Flash Technology Inc公司自成立以来,一直致力于闪存技术的研发与生产。在电子行业的激烈竞争中,公司凭借对技术的深入理解和持续创新,成功研发出了一款高性能、低成本的闪存芯片,迅速占据了市场份额。这款芯片不仅满足了消费者对电子设备存储容量和速度的需求,还因其出色的稳定性和耐用性赢得了客户的广泛好评。Aplus Flash Technology Inc公司因此成为了闪存市场的佼佼者,为公司的进一步发展奠定了坚实基础。

依必安派特(ebmpapst)公司的发展小趣事

在快速发展的过程中,依必安派特也面临着一些挑战。其中之一就是仿冒产品的泛滥。为了维护品牌形象和客户利益,依必安派特积极打击仿冒产品。例如,在2023年,依必安派特和地方政府联手突击了一家位于广东的仿冒产品工厂,揭示了其造假行为。这一行动不仅保护了依必安派特的品牌声誉和客户信任,也为中国市场的公平竞争环境做出了贡献。

问答坊 | AI 解惑

清华大学嵌入式教程word版,亲自排版 可直接打印

整理了一天,打印时记得用双面A4,因为是按照双面排版的!     下载了记得顶一下,本人刚注册的号,积分不多,帮忙挣点积分了好下载资料,在此谢过了!!…

查看全部问答>

谷歌微软退出自有品牌手机市场

本帖最后由 jameswangsynnex 于 2015-3-3 19:57 编辑 对于有钱有势的谷歌和微软来说,今年的6月过得不大舒坦。 6月底,谷歌和微软不约而同地宣布不再推出新的自有品牌手机。其实,谷歌试水手机市场只有5个多月,而微软则只有两个多月。这对已经习 ...…

查看全部问答>

在WinCE6.0 的用户态驱动中如何映射物理地址

请教各位大虾:   在WinCE6.0 的用户态驱动中如何映射物理地址? 对于下面的这样一段代码, 如果这个驱动是被运行在用户态, 输出的vpReg为0. 哪位知道该如何映射物理地址, 请不吝赐教. DWORD HDR_Init(LPCTSTR pContext, LPCVOID lpvBus ...…

查看全部问答>

WindML开发问题

最近想学用WINDML,哪有这方面的资料啊? 高手讲讲基本的开发步骤吧 谢啦…

查看全部问答>

怎样找到USB设备的EndPoint?

{c12127c7-8258-4929-8574-4278b946cd69}…

查看全部问答>

求助!!!CC2430芯片烧不进程序,请问电路设计哪出了问题!!!

向CC2430芯片烧程序的时候,程序烧不进去,经测试发现CC2430烧程序的数据线(DD引脚,46脚)为3.3V高电平,CC2430的电源3.3V。而正常情况下这个引脚的电压应该几乎等于0V,为低电平。烧写器没有问题,接线没有错。 现在已经确定是CC2430芯片和周围 ...…

查看全部问答>

S3C2410/2440如何接市面上买来的液晶屏?我研究了好多天,还是一头雾水,请高手帮帮我

现在市面上买来的液晶屏一般有以下信号 HSYNC    //2410有相应引脚 VSYNC    //2410有相应引脚 DOTCLK   //2410有相应引脚 DEN      //2410有相应引脚 AVDD     //模 ...…

查看全部问答>

知道Marvell PXA310 的请进

买了一个掌上电脑HP iPAQ 212,他的cpu类型是Marvell PXA310,请问这是个啥cpu,基于什么架构平台的,原来ARM的程序不用改动可以移植到这上面吗?x86下的程序呢…

查看全部问答>

pxa270wince下大页面nandflash驱动的问题?

我最近在做pxa270wince下大页面nandflash的驱动,更改了read,write函数后,在控制面板里可以看到这个设备,容量显示也是正确的,可是一格式化,就在FMD_SetBlockStatus中把每一个block立刻mark成bad,不知道该如何解决,有做过这个的大大给我讲一下 ...…

查看全部问答>

如何进入IDLE中断

USART的配置如下USART_InitStructure.USART_BaudRate = 4800;  USART_InitStructure.USART_WordLength = USART_WordLength_8b;  USART_InitStructure.USART_StopBits = USART_StopBits_1;& ...…

查看全部问答>