Was bewirkt, dass das Einschalten eines einzelnen Ausgangspins am Microchip PIC16F690 spontan einen anderen Pin am selben Port ausschaltet?

7

Was bewirkt, dass das Einschalten eines einzelnen Ausgangspins am Microchip PIC16F690 spontan einen anderen Pin am selben Port ausschaltet? Ich kann dieses Problem umgehen, indem ich ein Byte in den gesamten Port schreibe und alle Pins gleichzeitig steuere, anstatt nur ein bisschen, um den Pin-Status zu steuern. Ich verwende hier den Hi-Tech C-Compiler. Ich bestimme den Zustand des Pins mit 9 LEDs, die jeweils 3 mA verbrauchen. Dies liegt weit unter den maximalen Leistungsspezifikationen.

In der mplab-Headerdatei ist der 0-Pin an Port A als solcher deklariert:

volatile       bit RA0  @ ((unsigned)&PORTA*8)+0;

Ich schalte den Stift ein, indem ich einen hohen Wert darauf schreibe.

RA0 = 1;

Ist das Problem, dass der Complier die "1" als Byte behandelt und in den gesamten Port schreibt? Muss ich es besetzen? Wenn ja, hätte der Complier mir keinen Fehler geben sollen?

RA0 = (bit) 1;

Wenn ich an den gesamten Port schreibe, funktioniert alles wie erwartet:

PORTA = 0b00000001;
Dave.Mech.Eng
quelle

Antworten:

16

Es ist das bekannte Lese-, Änderungs- und Schreibproblem. Details finden Sie im Datenblatt. Sie müssen in das gesamte Register schreiben, wie Sie gefunden haben. Die 18F- und 16-Bit-Geräte haben kein Problem. Auf Seite 2 dieses Dokuments finden Sie eine gute Beschreibung . Das Ändern von Bits in einem "Schatten" -Register und das anschließende Schreiben des Registers in den Ausgangsport wird häufig verwendet, um das Problem zu umgehen.

Leon Heller
quelle
Sind Sie sicher, dass dies das Problem ist? Ich würde mir vorstellen, dass RA0 = 1 ASM generieren sollte, das BSF verwendet, was die Bits 1-7 nicht beeinflussen sollte. Sie sollten die Assembly-Listendatei überprüfen. Ich denke, Hi-Tech C generiert es automatisch als .lst-Datei.
Ajs410
2
BSF wirkt sich tatsächlich auf alle Bits 0-7 aus, obwohl wir uns alle wünschen, dass dies nicht der Fall ist . Siehe techref.massmind.org/techref/readmodwrite.htm .
Davidcary
1

Stellen Sie sicher, dass der von Ihnen verwendete Port als digital definiert ist. ANSEL = 0;

Wenn ein Port als analog definiert ist und Sie einen digitalen Lesevorgang ausführen, wird 0 zurückgegeben. Wenn der PIC F16xxx die Lese-, Änderungs- und Schreiboperation ausführt, wird an allen analogen Pins 0 angezeigt. Dann wird 0 zurück in alle diese Pins geschrieben.

Wenn Sie ANSEL für PORT B ​​auf 1 gesetzt haben, schaltet der folgende Code PORT B ​​für 500 ms ein. Lesen Sie dann PORTB als 0b00000000 (da es analog ist). Schalten Sie dann PORTB aus, weil es dachte, es sei ausgeschaltet.

    ANSEL = 0b11111111;
    TRISB = 0;
    PORTB = 0b11111111;
    __delay_ms(500);
    current = PORTB;
    PORTB = current;
    __delay_ms(500);

Stellen Sie sicher, dass Sie das entsprechende ANSEL-Bit für jeden Pin, den Sie als digital verwenden möchten, auf 0 setzen!

Reich
quelle
0

Ich benutze den Compiler von Microchip. Es hat eine Header-Datei, in der alle Register eine Vereinigung mit den definierten Bits haben. Also schreibe ich in meinen Code:

LATAbits.LATA0 = 1;

Außerdem würde ich das Latch-Register anstelle des PORT-Registers verwenden, um die Ausgabe einzustellen. Ich denke, einige Chips kümmern sich nicht darum, andere jedoch.

Robert
quelle
2
Die 16F-PICs haben keine LAT-Register, daher das Problem.
Leon Heller
2
@Leon Heller: Die separaten Latch-Register waren ein Merkmal späterer PIC-Teile von General Instruments, die leider erst in der 18F-Serie in die PIC-Teile von Microchip integriert wurden. Seltsam, dass GI das Problem mit Lese- / Schreib-PORTx-Registern in den 1980er Jahren bemerkte, aber Microchip hat sich jahrzehntelang nicht damit befasst.
Supercat
0

Ich bin mir zu 99% sicher, dass der Compiler dies tut. Unabhängig davon, welche Struktur für den Zugriff auf den Pin definiert ist, besteht eine Mehrdeutigkeit, die der Compiler auflöst, um dieses Verhalten zu erstellen. Das Bit-Casting könnte helfen, aber ich weiß nicht, wie (Bit) definiert ist, daher kann ich nicht sicher sein. Der Compiler gibt Ihnen nicht unbedingt einen Fehler, wenn der Wert, der in den Pin geschrieben wird, vom richtigen Typ ist. Ich vermute, dass die (Bit-) Maske möglicherweise eine Logik auslöst, um den Status der anderen Pins beizubehalten, aber dennoch denselben zurückzugeben Geben Sie als Ihre Konstante ein.

Es ist nicht überraschend, dass das Schreiben in den Port selbst funktioniert - aber das Arbeiten mit einzelnen Pins ist viel komplizierter. Entweder enthält der bereitgestellte Code einen Fehler, er sollte nicht mit diesem Compiler verwendet werden, oder Sie verwenden ihn einfach nicht richtig.

AngryEE
quelle
3
Das hat nichts damit zu tun!
Leon Heller
Nun, tatsächlich können C-Compiler der Grund für viele der Probleme sein. Dieses Problem wird vom Compiler verursacht, da er wahrscheinlich etwas wie XORWF verwendet, es ist jedoch nicht die Schuld des Compilers. Der Programmierer sollte ein Schattenregister verwenden. Am Ende haben Sie also Recht, @LeonHeller. Ich fange an, C-Compiler zu hassen, besonders XC8 heutzutage.
Abdullah Kahraman
-2

Wenn Sie den gesamten Port auf 1 schreiben, sehen Sie das Problem. In der Binärdatei ist das 0b00000001, also setzen Sie tatsächlich die ersten sieben Bits aus und das letzte Bit ein.

Sie müssen binäre Operatoren verwenden, um sicherzustellen, dass Sie nur die Änderung an diesem bestimmten Bit vornehmen. Mach das:

PORTA = PORTA | 1;
// Equivalently:
current = PORTA;
new = current | 1;
PORTA = new;

Wenn die Pins 2-8 derzeit hoch sind, gibt die ODER-Verknüpfung true zurück und das Bit bleibt gesetzt.

Verwenden Sie eine binäre UND-Verknüpfung, um ein wenig zu niedrig zu machen:

PORTA &= 1;

Beachten Sie, dass einige Compiler bestimmte Makros haben, um dies zu tun (dh _BV () auf avr-gcc), und einige Mikros spezifische Adressen haben, die auf jedes Peripheriebit ausgerichtet sind, so dass Sie diesen Lese-, Änderungs- und Schreibzyklus nicht ausführen müssen ( Bitband-Speicher auf Cortex-M3)

Kevin Vermeer
quelle