在PIC中使用多个外部中断


9

我已经将PIC16F877datasheet)用于多个项目。对于单个外部引脚更改中断,可以使用PORTB0中断。但是现在我需要在一个电路中支持8个独立的外部引脚更改中断。

在数据表中,它说有15个中断PIC16F877,但是我想这些都算在内,包括定时器溢出中断等...在这种情况下没有用。

这是数据表关于INTCON寄存器的内容。

在此处输入图片说明

我可以使用bit0进行4个独立的中断RBIF吗?它代表的变化PB7:PB4。如何通过读取中断程序中的端口值来识别哪个引脚发生了变化?

即使我得到以上肯定的答案,我也需要8次中断?当然,我仍然可以使用INTE进行PORTB0更改。然后4 + 1 = 5,其他3个呢?(但是,尽管这8个中断事件都是同一类型,但4 + 1 + 3 = 8事情看起来很难看,不是吗?)

除了监视8个引脚之外,微控制器没有其他繁重的任务。(谈论其他任务时,它必须维护一组单独的计数器变量,并经常向PC串行传输约4个字节)

欢迎任何建议。即使是为了将微控制器更改为更合适的一个(但...不要告诉我不要使用PICs)。


2
在不使用中断的情况下,您可以监控主程序中的引脚。但这并不是完美的。或者,您可以选择Arduino。尽管它不是PIC,但它非常简单,因为您已经很熟悉PIC,因此您会很容易理解。
阿努比斯

1
如果使用RBIE中断,则每次只需缓冲先前的值,然后进行XOR运算以查找更改。应该很快执行。
PeterJ 2013年

@PeterJ我不太明白。缓冲区哪个值?
代号SC

@PeterJ太好了!等待中……
代号SC

1
一种方法是使用外部8输入门(例如老式的74LS30)将外部信号组合到一个中断引脚上。由于74(HC)30是NAND门,您需要在静态时将所有输入都设为高电平-它们还需要连接至端口引脚,以便您可以通过读取端口来识别哪些中断处于活动状态。
Brian Drummond

Answers:


3

这是用C伪代码解释的一个想法。它使用异或运算来确定哪些引脚已更改,并将在一个RBIE中断中调用您的不同处理程序。根据应用程序的关键程度,您可能需要检查PIC在中断执行期间如何处理端口更改等情况,以确保您不会错过任何事件。

int old_port_b;

void isr_handler()
{
    int new_port_b, changed_pins;
    new_port_b = read_port_b();
    changed_pins = new_port_b ^ old_port_b;
    if (changed_pins | 1)
        rb0_hander();
    if (changed_pins | 2)
        rb1_hander();
        // ... etc
    old_port_b = new_port_b;
}

int main()
{
    old_port_b = read_port_b();
    enable_interrupt();
}

我明白了,谢谢!但这不是我要找的确切答案。这样,您只能监视RB7:RB44个引脚。但我正在寻求一种监控8个引脚的方法。有什么建议吗?
代号SC

我想这是您不能使用RB0-RB7的原因吗?否则,我真的想不出办法,如果快速触发代码不是很重要,则可以在计时器中断(或仅在主循环中)中使用上述样式的代码。
PeterJ

对于该PIC,如果您需要使用中断来执行此操作,则可以使用RB4:RB7的XOR技巧和RB0:RB3的四个中断。如果不需要中断,只需轮询代码中的整个端口,或者如果需要硬采样率,则使用计时器中断来处理轮询
Scott Seidman 2013年

and four interrupts for the RB0:RB3?PIC16F877不支持的任何中断RB1:RB3,是吗?
代号SC

我错过了数据表中的内容,我以为它涵盖了整个端口。但是我看到您的其他评论大约每秒一次,因此我认为最好在主循环中运行它。对于中断,您将需要在执行过程中随时进行变量更新,以及如何在中断运行时处理引脚变化。听起来好像真的会使它复杂化,但没有任何实际收益。我唯一想到的例外是,如果您想使用中断时从睡眠中唤醒,在这种情况下,您需要对它们进行硬件MUX。
PeterJ

1

该部分只有4个引脚更改中断,您可以在选定的边沿上设置一些其他中断。一种策略是从外部检测8位值的变化,然后在不匹配时中断。这在硬件上变得凌乱,但恰好满足您的需求。

您尚未说明的重要参数是您需要多快的时间来响应引脚更改,以及引脚更改将保持有效的最短时间是多少。根据答案,您可以根据固件中的常规中断进行轮询。16F877可以以5 MHz的指令速率运行,并且检查更改仅需要执行少量指令。假设您每50条指令设置一次中断。这将把处理器时间的很大一部分留给前台代码。中断速率为100 kHz,周期为10 µs。当然,前台代码仍然需要查看更改标志并对其进行处理,因此响应时间将超过10 µs,但是您没有说出检测到更改时需要执行的操作。如果这只是需要在人类时代做出回应,


抱歉,缺少详细信息。由于预期的响应率once per second将足够。当检测到引脚变化(仅一个边沿,例如上升)时,计数器(变量)必须增加。在主循环中,它必须监视计数器的值,当一个计数器的值大于某个特定值时,必须将四个字节传输USART到PC。然后将相关的计数器值重置为零。就那么简单。我想轮询选项会很好吧?
代号SC

2
每秒一次!那么,所有困扰中断的原因是什么?定期轮询很容易做到这一点。那是什么问题呢?
Olin Lathrop 2013年

um ... i虽然最好,因为其中有8个,而且无法预测响应(但可以认为该值是最小值)。嘿!人们可以犯错,对.. :(
代号SC

1

您可以使用@Brian Drummond提到的8输入门NAND在INT引脚上产生中断,并将中断源连接到8位并行输入/串行输出移位寄存器,例如“ 74HC165N”,因此您将需要在中断发生后仅从该移位寄存器读取数据,这将为您提供有关实际中断源的信息...这可能不是最快的方法,但易于扩展,将使用不超过5个引脚,并且如果添加地址控制系统(MUX,LATCH等),则只需要一个松树即可进行中断通知,而其他引脚可能会在不同时间重用于不同的资源;)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.