Verwenden mehrerer externer Interrupts in PIC

9

Ich habe PIC16F877( Datenblatt ) für mehrere Projekte verwendet. Für einen einzelnen externen Pinwechsel-Interrupt können Sie PORTB0Interrupt verwenden. Aber jetzt muss ich 8 unabhängige externe Pinwechsel-Interrupts in einem einzigen Schaltkreis unterstützen.

Im Datenblatt steht, dass es 15 Interrupts gibt PIC16F877, aber ich denke, diese werden gezählt, einschließlich Timer-Überlauf-Interrupts usw., die in diesem Fall unbrauchbar sind.

Dies ist, was Datenblatt über INTCONRegister sagen .

Geben Sie hier die Bildbeschreibung ein

Kann ich mit Bit0 4 unabhängige Interrupts haben RBIF? Es repräsentiert eine Veränderung in PB7:PB4. Wie kann ich feststellen, welcher Pin geändert wurde, indem ich den Portwert in der Interruptroutine lese?

Auch wenn ich oben positive Antworten bekomme, brauche ich 8 Interrupts? Natürlich kann ich noch INTEfür PORTB0Veränderung verwenden. Dann 4 + 1 = 5, aber was ist mit anderen 3? (Da jedoch alle 8 Interrupt-Ereignisse vom gleichen Typ sind, 4 + 1 + 3 = 8scheint das Ding hässlich, nicht wahr?)

Vom Mikrocontroller werden keine anderen schweren Aufgaben erwartet als die Überwachung von 8 Pins. (Wenn wir über die anderen Aufgaben sprechen, müssen wir einen Satz separater Zählervariablen verwalten und häufig etwa 4 Bytes seriell an den PC übertragen.)

Anregungen sind willkommen. Auch wenn es darum geht, den Mikrocontroller gegen einen geeigneteren auszutauschen (aber äh ... sag mir nicht, ich soll von PICs weggehen ).

Codename SC
quelle
2
Ohne Interrupts können Sie möglicherweise die Pins im Hauptprogramm überwachen. Das ist aber nicht perfekt. Alternativ können Sie sich für Arduino entscheiden. Obwohl es kein PIC ist, ist es ziemlich einfach, Sie werden es leicht verstehen, da Sie bereits mit PICs vertraut sind.
Anubis
1
Wenn Sie den RBIE-Interrupt verwenden, können Sie jedes Mal den vorherigen Wert und ein XOR puffern, um herauszufinden, was geändert wurde. Sollte ziemlich schnell ausgeführt werden.
PeterJ
@ PeterJ das habe ich nicht ganz verstanden. Welchen Wert puffern?
Codename SC
@ PeterJ toll! Warten ...
Codename SC
1
Eine Möglichkeit besteht darin, ein externes Gate mit 8 Eingängen (wie früher der 74LS30) zu verwenden, um die externen Signale auf einem Interrupt-Pin zu kombinieren. Da der 74 (HC) 30 ein NAND-Gatter ist, müssten alle Eingänge im Ruhezustand hoch sein. Sie müssten auch mit Port-Pins verbunden werden, damit Sie durch Lesen des Ports erkennen können, welche Interrupts aktiv sind.
Brian Drummond

Antworten:

3

Dies ist C-Pseudocode, um eine Idee zu erklären. Es verwendet ein exklusives ODER, um herauszufinden, welche Pins sich geändert haben, und ruft Ihre verschiedenen Handler innerhalb eines RBIE-Interrupts auf. Abhängig davon, wie kritisch die Anwendung ist, möchten Sie möglicherweise überprüfen, wie der PIC mit Situationen wie einem Portwechsel während der Ausführung des Interrupts umgeht, um sicherzustellen, dass Sie keine Ereignisse verpassen.

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();
}
PeterJ
quelle
Ich verstehe, danke! aber das ist nicht die genaue Antwort, die ich suche. Auf diese Weise können Sie RB7:RB4nur 4 Pins überwachen . Aber ich frage nach einer Möglichkeit, 8 Pins zu überwachen. irgendein Vorschlag?
Codename SC
Ich denke, es gibt einen Grund, warum Sie RB0 - RB7 nicht verwenden können. Ansonsten kann ich mir keinen Weg vorstellen. Wenn es nicht wichtig ist, den Code schnell zu ändern, können Sie den obigen Codestil in einem Timer-Interrupt (oder nur in der Hauptschleife) verwenden.
PeterJ
Wenn Sie für diesen PIC Interrupts verwenden müssen, ist der XOR-Trick für RB4: RB7 und vier Interrupts für RB0: RB3 der richtige Weg. Wenn Sie den Interrupt nicht benötigen, rufen Sie einfach den gesamten Port in Ihrem Code ab oder verwenden Sie einen Timer-Interrupt, um den Abruf durchzuführen, wenn Sie eine harte Abtastrate benötigen
Scott Seidman,
and four interrupts for the RB0:RB3? PIC16F877 unterstützt keine Interrupts für RB1:RB3, oder?
Codename SC
Ich hatte das im Datenblatt übersehen, ich nahm an, dass es den gesamten Port abdeckte. Aber ich habe Ihren anderen Kommentar ungefähr einmal pro Sekunde gesehen, daher denke ich, dass Sie dies besser einfach in Ihrer Hauptschleife ausführen sollten. Bei Interrupts müssen Sie darauf achten, dass die Variablen zu jedem Zeitpunkt während der Ausführung aktualisiert werden und wie Pin-Änderungen behandelt werden, während der Interrupt ausgeführt wird. Es klingt wirklich so, als würde es es nur erschweren, ohne wirklich zu gewinnen. Die einzige Ausnahme, an die ich denken könnte, ist, wenn Sie Wake-from-Sleep bei Interrupt verwenden möchten. In diesem Fall müssten Sie sie per Hardware-MUX verwenden.
PeterJ
1

Dieser Teil hat nur 4 Pin-Change-Interrupts und einige andere, die Sie an ausgewählten Kanten einrichten können. Eine Strategie wäre, eine Änderung des 8-Bit-Werts extern zu erkennen und dann die Nichtübereinstimmung zu unterbrechen. Das wird in der Hardware chaotisch, wird aber so genau das, was Sie wollen.

Die wichtigen Parameter, die Sie nicht angegeben haben, sind, wie schnell Sie auf einen Pinwechsel reagieren müssen und wie lange ein Pinwechsel mindestens so lange dauert, bis er gültig ist. Abhängig von den Antworten können Sie basierend auf einem regelmäßigen Interrupt in der Firmware abfragen. Der 16F877 kann mit einer Befehlsrate von 5 MHz betrieben werden, und die Überprüfung auf eine Änderung würde nur wenige Befehle erfordern. Angenommen, Sie richten den Interrupt alle 50 Anweisungen ein. Das würde einen guten Teil der Prozessorzeit dem Vordergrundcode überlassen. Die Unterbrechungsrate wäre 100 kHz und die Periode 10 us. Natürlich muss der Vordergrundcode dann noch das Änderungsflag sehen und etwas dagegen tun, sodass die Antwortzeit mehr als 10 µs beträgt, aber Sie haben nichts darüber gesagt, was Sie tun müssen, wenn eine Änderung erkannt wird. Wenn dies nur in menschlicher Zeit reagieren muss,

Olin Lathrop
quelle
Entschuldigung für die fehlenden Details. Da wird die erwartete Rücklaufquote once per secondausreichen. Wenn ein Pinwechsel (nur eine Flanke, z. B. steigend) erkannt wird, muss ein Zähler (variabel) inkrementiert werden. In der Hauptschleife müssen die Zählerwerte überwacht werden, und wenn einer einen bestimmten Wert überschreitet, müssen vier Bytes über USARTden PC übertragen werden . Setzen Sie dann den entsprechenden Zählerwert auf Null zurück. So einfach ist das. Ich denke, die Polling-Option wird gut gehen, oder?
Codename SC
2
Einmal pro Sekunde ! Also, wofür ist all die Qual über Interrupts? Dies ist bei regelmäßigen Abfragen problemlos möglich. Was ist dann das Problem?
Olin Lathrop
ähm ... ich denke, es ist am besten, da es 8 davon gibt und außerdem kann die Antwort nicht vorhergesagt werden (aber dieser Wert kann als Minimum angenommen werden). Hallo! Leute können Fehler machen, richtig .. :(
Codename SC
1

Sie können das von @Brian Drummond erwähnte 8-Eingangs-Gate-NAND verwenden, um einen Interrupt über den INT-Pin auszulösen und Ihre Interrupt-Quellen auch mit dem 8-Bit-Parallel-In / Serial-Out-Schieberegister wie "74HC165N" zu verbinden Um nur die Daten aus diesem Schieberegister zu lesen, nachdem der Interrupt ausgelöst wurde, erhalten Sie Informationen über Ihre tatsächliche Interruptquelle. Dies ist möglicherweise nicht der schnellste Weg, aber einfach zu erweitern und verwendet nicht mehr als 5 Pins Wenn Sie ein Adresssteuerungssystem (MUX, LATCH, ...) hinzufügen, benötigen Sie nur eine Kiefer für die Interrupt-Benachrichtigung, und andere Pins können zu unterschiedlichen Zeiten für unterschiedliche Ressourcen wiederverwendet werden.

Eli Oulman
quelle