Forum: Mikrocontroller und Digitale Elektronik Registerzuweisung bei PIC16F887


von Oliver S. (os252)


Lesenswert?

Hallo,

ich komme aus der AVR Welt und möchte nun auch PIC Controller 
programmieren.
Nun wollte ich in dem PORTC Register eines PIC16F887 2 Bits mit dem Wert 
0 beschreiben.
Ich habe es folgendermaßen versucht:

PORTCbits.RC3 = 0;
PORTCbits.RC4 = 0;

oder ich habe versucht direkt zu adressieren:

RC3 = 0;
RC4 = 0;

Allerdings funktioniert dieses nicht. Einer der beiden Werte wird immer 
nicht übernommen.
Wenn ich die Zuweisung allerdings über das komplette Register durchführe 
funktioniert es problemlos.

PORTC = 0b11100111;

Was mache ich wohl falsch? Ich hatte gedacht, dass man beim PIC die Bits 
einzeln ansprechen kann und nicht wie beim AVR maskieren muss?!

Ich hoffe, de Informationen reichen aus um mir weiter zu helfen.
Vielen Dank schonmal!

MfG
Olli

von tt4u (Gast)


Lesenswert?

PORTC,2 = 0

von Kein Name (Gast)


Lesenswert?

Könnte eine Variante der IO Speed Falle sein.

http://www.sprut.de/electronic/pic/fallen/fallen.html#iospeed

Dummerweise lesen die PIC 16 Bit-Befehle nicht das Latch sondern die 8 
Pins.

von Klaus (Gast)


Lesenswert?

Ich benutze zwar die PIC24xx aber

Oliver S. schrieb:
> PORTCbits.RC3 = 0;
> PORTCbits.RC4 = 0;
>
> oder ich habe versucht direkt zu adressieren:
>
> RC3 = 0;
> RC4 = 0;

Das ist das gleiche. In einem Headerfile wirst du sowas finden wie

#define RC3 PORTCbits.RC3

Oliver S. schrieb:
> Allerdings funktioniert dieses nicht. Einer der beiden Werte wird immer
> nicht übernommen.
> Wenn ich die Zuweisung allerdings über das komplette Register durchführe
> funktioniert es problemlos.

Das ändern von Bits in einem Port sollte man nicht hintereinander 
machen. Immer etwas anderes dazwischen, zur Not ein NOP. Ich weiß jetzt 
nicht, wie die Funktion für einen NOP beim Compiler für die die PIC16 
aussieht, mußt du mal nachsehen (nop() ?, _nop() ?, oder irgenwas mit 
__builtin ??).

MfG Klaus

von Oliver S. (os252)


Lesenswert?

Hallo,

vielen Dank für die Antworten.
Leider habe ich es bislang noch nicht so hinbekommen wie ich es mir 
vorgestellt hatte.
Nun habe ich versucht die Bits im PORTC umzudrehen. Also:
1
PORTC &= ~(RC3);
2
PORTC &= ~(RC4);

Damit funktioniert das nun auch wohl, da die Register zu Beginn wohl mit 
1 initilaisiert werden.

Allerdings möchte ich gerne wissen warum das mit der Methode nicht 
funktioniert, die ich bereits gepostet habe.

Bisher versucht habe ich nun auch:
1
PORTCbits.RC3 = 0;
2
_nop();
3
_nop();
4
_nop();
5
_nop();
6
PORTCbits.RC4 = 0;

Allerdings funktioniert dieses aber nicht.
Eventuell hat jemand noch eine Idee wie man das richtig macht oder warum 
das bei mir nicht funktioniert.

MfG
Olli

von Oliver S. (os252)


Lesenswert?

Hallo,

ich habe das Problem gefunden.
Die Ports sollten auf low geschaltet werden, obwohl die TRIS Bits dieser 
Ports auf 1 (also Eingänge) waren.
Dies ist nötig, da die Pins zuerst einmal Hochohmig sein sollen und 
später die externe Schaltung auf low ziehen.
Diese Vorgehensweise wollte wohl der Compiler (oder was auch immer) 
nicht so ganz unterstützen.
Nun habe ich die Pins zuerst als Ausgänge konfiguriert, sie dann auf low 
gezogen und danach die Pins wieder als Eingänge (hochohmig).
Zur Info: Ich verwende den Hi-Tech Compiler PICC.

Ich habe es nun folgendermaßen realisiert:
1
TRISCbits.TRISC3 = 0; //als Ausgänge setzen
2
TRISCbits.TRISC4 = 0;
3
  
4
PORTCbits.RC3 = 0; //Ausgänge auf Low
5
PORTCbits.RC4 = 0;
6
  
7
TRISCbits.TRISC3 = 1; //als Eingänge setzen
8
TRISCbits.TRISC4 = 1;

Eventuell hilft es irgendjemanden mal bei der Fehlersuche.

MfG
Olli

von Chris (Gast)


Lesenswert?

Das bringt dich auch nicht wirklich weiter, ein Write auf irgendein Bit 
im selben Port ändert es wieder auf high, mit hoher Sicherheit.

Beschreib das LATx Register, LATCbits.RC4 = 0; als Beispiel, wobei
auch hier dasselbe gilt, ein Write auf PortB ändert dir die Bits.
PORTx solltest du nur als readonly benutzen, zum write solltest du
ausschließlich LATx benutzen, das erspart dir viel Arger.
Aussnahmen gibt es immer, das ist jedoch die Regel.
Beim PORTx stimmt das sehr wohl wegen man sollte den Port nicht gleich 
hintereinander ändern, beim LATx besteht diese Limitierung nicht, für
das Lesen des Ports, also btfsx und Konsorten ist es egal.

von Stefan (Gast)


Lesenswert?

Der Controller hat kein LAT Register.

von Chris (Gast)


Lesenswert?

sorry, hatte was von pic24 gelesen.
Es ist ein PIC16F887

Ja, entweder ein shadow register benutzen, welches dann auf PortC 
geschrieben
wird, oder die Pinzuordnung und Programmierung durchdacht machen.

Shadow register ist die manuelle Implementation eines LATx Registers.

http://www.piclist.com/techref/readmodwrite.htm

von Michael L. (michaelx)


Lesenswert?

Hallo Oliver,

bei den "einfachen" PICs (so wie deinem)ohne LAT-Register für die 
I/O-Ports stolpern wohl die Meisten zu Anfang über dieses Problem.

Die gängigste Variante, die ich kenne und in diversen Programmen gesehen 
habe, ist, das Bitmuster für die Ausgänge eines Ports in einem anderen 
Register vorzuhalten. Alle Bitmanipulationen werden nur dort 
vorgenommen, und das gesamte Byte danach auf das Port-Register 
geschrieben. Damit umgeht man die Fallen (I/O-Speed, Read-Modify-Write).

HTH
Michael

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.