Seltsames Pin-Verhalten mit pic16f88

Ich habe gelernt (zumindest versucht), wie man mit Bildmikrocontrollern arbeitet, und ich habe dieses Verhalten bemerkt, bei dem ich nicht sicher bin, ob es nur meine Schuld ist oder passieren soll. Ich habe das folgende Programm in der Hoffnung geschrieben, eine LED blinken zu lassen. Es blinkt einwandfrei, wenn es an den Pin mit der Bezeichnung RA2 angeschlossen ist, aber wenn ich die LED an Pin 15 (auf dem Datenblatt mit RA6 / OSC2 / CLKO gekennzeichnet) anschließe, bleibt die LED an, als hätte ich sie an Vdd angeschlossen. Wenn ich es dann wieder in RA2 stecke, wo es hingehört, ist es ausgeschaltet. Die einzige Möglichkeit, es wieder einzuschalten, besteht darin, einen 10k-Widerstand zwischen Vdd und MCLR anzuschließen (wie beim Programmieren). Was passiert hier? MCLR wird auch benötigt, wenn es an einige andere Pins angezapft wird. Verursache ich Schaden?
Die Schaltung besteht aus 3 AA-Batterien, die das Bild mit Strom versorgen, mit einem 330-Widerstand und einer 3-mm-LED in Reihe, die von Pin 1 (RA2) zu Pin 5 (Masse) läuft.
pic16f88 Datenblatt
Code:

#include <xc.h>

__CONFIG(MCLRE_ON & CP_OFF & WDTE_OFF);

void main(){

    TRISA = 0x0000;
   // RB6 = 0b000010;
    for(;;){
        RA2 = 1;
        Wait();
        RA2 = 0;
        Wait();
    }
}
int Wait(void) // gives me a delay of 1/3rd a second or so
{
for (int i = 0; i < 50; i++)
 {
 }
}

Antworten (3)

Sie müssen den MCLR-Pin während des normalen Betriebs hoch binden, sonst wird der Chip im Reset gehalten. Beachten Sie den Balken über MCLR, dies bedeutet, dass er aktiv niedrig ist .
Verwenden Sie einen Widerstand zwischen MCLR und Vdd von etwa 10 kΩ (<40 kΩ)
Siehe S. 132/133 des Datenblatts.

Also muss ich diesen 10-kΩ-Widerstand dauerhaft dort halten? Es schien ok zu funktionieren, wenn das nicht da war. Was bewirkt das Halten im Reset? Würde das Einfügen von _MCLRE_OFF in den Konfigurationsteil des Programms dies beheben?
Aufgrund der sehr hohen Impedanz des CMOS-Eingangs funktioniert es zeitweise, wenn es nicht vorhanden ist. Wenn Sie es nur mit der Hand berühren, wird es einen Unterschied machen, wenn es schwebt. Wenn das Teil im Reset gehalten wird (MCLR tatsächlich auf Masse gezogen und nicht schwebend), wird der Hauptoszillator abgeschaltet und das Teil "schläft" (sehr geringer Stromverbrauch). Durch das Ausschalten von MCLR wird der Pin-Status irrelevant, ja.
Was für die MCU besser / sicherer / intelligenter ist, mclr in der Konfiguration ausschalten oder eingeschaltet lassen und den Widerstand dort belassen. Was wird normalerweise gemacht?
Es liegt an Ihnen, wenn Sie nicht in der Lage sein müssen, das Mikro extern zurückzusetzen (z. B. Tastendruck), dann ist es eine Option, es auszuschalten und ein paar Komponenten zu sparen. Mikrochips haben viele App-Notizen zu diesen Themen, ich würde auf ihrer Website suchen und ein bisschen lesen.
Das funktioniert gut, danke. Ich bemerke, dass, wenn ich Pin 9 (RB3/PGM/CCP1) mit meinem Finger berühre, die LED anhält und dann ausgeht. Nach etwa 5 Sekunden schaltet es sich wieder ein. Was passiert da?
Schwer zu sagen, aber es liegt wahrscheinlich daran, dass es schwebt (auf Eingang gesetzt) ​​und die Änderung des Werts ein Problem verursacht. Es könnte sein, dass Sie LVP (Low Voltage Programming) eingestellt haben und es in den Programmiermodus wechselt. Stellen Sie sicher, dass Sie die richtigen Header- und Konfigurationsdeklarationen haben, und setzen Sie alle nicht verwendeten Pins auf Ausgang (hoch oder niedrig), um Probleme im Zusammenhang mit Floating zu vermeiden.
Ich erwähne die korrekten Header- und Konfigurationsbits, da Ihre Wait-Routine wie gezeigt nicht 1/3 Sekunde dauern sollte (eher einige zehn Mikrosekunden). Stellen Sie sicher, dass Sie den Oszillator in den Konfigurationsbits richtig eingestellt haben.
Alles klar, danke. Also sollte ich LVP_OFF ​​an die Konfiguration anhängen, und worauf sollte ich den Oszillator einstellen? Die MCU ist auf 20 MHz ausgelegt, ist das ein akzeptabler Wert?
Wenn Sie einen externen 20-MHz-Quarz haben, können Sie ihn darauf einstellen. Wenn nicht, verwenden Sie den internen 8-MHz-Oszillator. Sie können den LVP ausschalten, wenn Sie ihn nicht verwenden, ja, und er kann stoppen, was Sie sehen (aber der Pin sollte trotzdem auf einen Ausgang gesetzt sein). , Reset, LVP usw.) ist darin enthalten.
Alles funktioniert jetzt richtig, ich glaube, ich weiß, was jetzt passiert ist. Ich habe es so eingestellt, dass es den internen Oszillator mit dem Konfigurationsbit FOSC_INTOSCIO verwendet. Ich habe die Warteschleife auf 500 Schleifen erhöht, und ich bekomme zwischen jedem Blinken etwas mehr als eine Sekunde. Wenn ich es auf fünfzig zurückstelle, blinkt es viel schneller.

Ihr Problem liegt am !MCLR-Pin. Wenn Sie den PIC programmieren, verwenden Sie die VPP-Funktion, aber derselbe Pin hat die !MCLR-Funktion (Master Clear), und da diese Funktion aktiv niedrig ist, müssen Sie sicherstellen, dass dieser Pin hoch bleibt, damit der PIC Ihren Code ausführen kann. Wie Oli sagte, können Sie dies erreichen, indem Sie einen Pull-up-Widerstand für an den !MCLR-Pin anschließen.

Alternativ können Sie die MCLR-Funktion deaktivieren, indem Sie das MCLRE-Bit im CONFIG1-Register zurücksetzen (eine 0 schreiben).

__CONFIG(MCLRE_OFF & CP_OFF & WDTE_OFF);

Detail des MCLRE-Bits von Seite 130 des Datenblatts:

MCLRE: RA5/MCLR/VPP-Pin-Funktionsauswahlbit
1 = RA5/MCLR/VPP-Pin-Funktion ist MCLR
0 = RA5/MCLR/VPP-Pin-Funktion ist digitale E/A, MCLR intern mit VDD verbunden


Hinzugefügt

In Bezug auf das Read-Modify-Write-Problem tritt dies aufgrund der Funktionsweise des PIC auf. 8-Bit-PICs benötigen vier Taktzyklen für jeden Befehlszyklus. Schreibvorgänge werden im letzten Taktzyklus durchgeführt, während Lesevorgänge im ersten Taktzyklus durchgeführt werden. Dies kann zu Problemen führen, wenn Sie mit verschiedenen Bits desselben Ports arbeiten.

Angenommen, Sie haben den folgenden Code:

RA0 = 1;
RA1 = 1;

Sie würden erwarten, dass sowohl RA0 als auch RA1 hoch sind, nachdem Sie diesen Code ausgeführt haben. Dies kann nicht der Fall sein. Wenn Sie alle Bits auf 0 gesetzt haben , liest der PIC PORTAbei der Ausführung den Wert auf PORTA im ersten Taktzyklus, setzt das Bit 0 und schreibt das Ergebnis zurück auf . Bisher kein Problem, aber wenn Sie die zweite Anweisung ausführen (RA1 = 1), liest der PIC zuerst den Wert von PORTA, und höchstwahrscheinlich hatte der RA0-Pin keine Zeit, auf 1 zu steigen, dann wird der Wert für diesen Pin gelesen 0 statt 1, dann wird das Bit 1 gesetzt, dann wird das Ergebnis nach PORTA zurückgeschrieben, aber nur das Bit 1 gesetzt.RA0 = 1PORTA

Um dies zu vermeiden, können Sie Verzögerungen zwischen den Anweisungen wie folgt hinzufügen:

RA0 = 1;
asm("nop");  // No operation
RA1 = 1;

Eine nopAnweisung sollte ausreichen.

In Ihrem Code sollten Sie dieses Problem aus zwei Gründen nicht haben:

  1. Sie ändern nicht verschiedene Bits auf PORTA
  2. Sie haben eine Warteanweisung zwischen den Schreibvorgängen der Bits von PORTA

Das Schattenregister, von dem Leon sprach, besteht aus einem Register, in dem die einzelnen Bits modifiziert werden, bevor das gesamte Register in den PORT geschrieben wird.

Möglicherweise möchten Sie sicherstellen, dass Ihre Konfigurationssicherungen so eingestellt sind, dass RA6 ein GPIO-Pin ist und nicht die CLKO-Funktion, die der Pin auch übernehmen kann. Ich bin auf dieses Problem mit einem einfachen Programm und dem Compiler von CCS gestoßen. Der Compiler hat eine so schlechte Dokumentation, dass es unmöglich ist, genau zu wissen, was passiert, ohne sich die Fuse-Bits selbst anzusehen.

Ich hätte erwartet, dass Sie, unabhängig davon, ob die LED auf RA2 oder RA6 steht, ein unberechenbares Verhalten haben würden, wenn MCLR # nicht hochgezogen wird. Vielleicht ist RA6 näher an MCLR# und das Problem wird verschärft; nicht sicher.