Hallo, ich muss bei einem Projekt einen PIC16LF722 einsetzen und weiß langsam, warum ich bislang immer mit anderen Controllern gearbeitet habe... ;-) Folgendes Problem habe ich mit diesem Code: #include <pic.h> int main (void) { TRISC6 = 0; RC6 = 0; TRISC0 = 0; RC0 = 0; unsigned int i; for (i = 0; i < 1000; i++) { CLRWDT(); RC0 = 1; DelayUs(125); RC0 = 0; DelayUs(125); } for(;;) { CLRWDT(); } } Sobald ich RC0 ein wenig toggle, wechselt RC6 auf high, obwohl das nirgends im Code geschrieben steht. Das ganze kann ich mit dem Simulator nicht nachvollziehen, dort bleibt RC6 konstant low. Der PIC16LF722 wird mit einem 4MHz-Quarz betrieben, VCC ist 3,3V und Abblockkondensatoren sowie Reset-Beschaltung (RC-Glied) sind auch vorhanden. Der Zustand ändert sich nicht immer, sondern scheinbar zufällig. Es ist aber auch nichts EMV-kritisches auf der Platine - alle anderen Komponenten wie beispielsweise ein Display und einige Taster werden noch garnicht benutzt. Vielleicht habe ich etwas im Datenblatt übersehen, aber momentan fällt mir schlichtweg nichts mehr ein. Ich benutze übrigens MPLAB IDE v8.40 mit dem Hi-Tech C-Compiler in der Lite-Version. Danke schonmal im vorraus.
wie kommsdn du zu der Erkenntnis? mit den LAT-"Registern ist das so im C auch richtig, wenn er welche hat?
Maik Werner schrieb: > wie kommsdn du zu der Erkenntnis? Nach dem Toggeln von RC0 liegt an RC6 ein High-Pegel an - auch wenn der Pin niemals auf high gesetzt worden ist. > mit den LAT-"Registern ist das so im C > auch richtig, wenn er welche hat? Die PIC16F haben kein LAT-Register.
Moin Christoph, bei kleinen PICs gibt es immer wieder drei prinzipielle Punkte die vor dem Sourcecode abgehandelt sein sollten: 1) Schalte ALLES (!) an den Pins ab, was Du nicht benötigst (analoge Eingänge, Comparatoren, ...) 2) Definiere alle Interrupts, besonders die mit Pinfunktionen 3) arbeite grundsätzlich mit einem Schattenregister (read-modify-write Problematik, Manual Seite 73), wenn Du DAten an den Pins ausgeben möchtest. Bedeutet soviel wie schreibe immer den ganzen Port, keine einzelnen Pins. Habe viele Projekte mit der PIC Familie verwirklicht. Wenn obige Punkte berücksichtigt werden, laufen die kleinen bestens. Gruß kokisan
Hallo Dierck, leider komme ich noch nicht ganz weiter: > 1) Schalte ALLES (!) an den Pins ab, was Du nicht benötigst (analoge > Eingänge, Comparatoren, ...) > 2) Definiere alle Interrupts, besonders die mit Pinfunktionen Das habe ich gemacht, auch wenn es oben noch nicht explizit stand. > 3) arbeite grundsätzlich mit einem Schattenregister (read-modify-write > Problematik, Manual Seite 73), wenn Du DAten an den Pins ausgeben > möchtest. Bedeutet soviel wie schreibe immer den ganzen Port, keine > einzelnen Pins. Auch das habe ich gemacht, aber weder Konstrukte wie unsigned char port; port = PORTC | (1<<4); PORTC = port; noch so simple Sachen wie PORTC |= (1<<4); funktionieren richtig - es ändern sich immer andere Pins noch mit. Liegt das eventuell am Compiler? Der generierte Assembler-Code sieht eigentlich in Ordnung aus.
Der Bitzugriff auf einzelne Portbits ist eigentlich gerade eine Stärke des PICs. Ich vermute, dass man dem Compiler das explizit sagen muss. So nach deiner Beschreibung macht er daraus einen read-modify-write für den ganzen Port.
Harald schrieb:
> Poste bitte mal das generierte Assembler-File.
Voilà:
--
23: int main (void)
24: {
25: // Ausgänge
26: TRISC = 0b01101111;
001 306F MOVLW 0x6f
002 1683 BSF 0x3, 0x5
003 1303 BCF 0x3, 0x6
004 0087 MOVWF 0x7
27: PORTC = 0;
005 1003 BCF 0x3, 0
006 1283 BCF 0x3, 0x5
007 1303 BCF 0x3, 0x6
008 3000 MOVLW 0
009 1803 BTFSC 0x3, 0
00A 3001 MOVLW 0x1
00B 0087 MOVWF 0x7
28:
29: // Eingang
30: ANSELB = 0;
00C 1003 BCF 0x3, 0
00D 1683 BSF 0x3, 0x5
00E 1703 BSF 0x3, 0x6
00F 3000 MOVLW 0
010 1803 BTFSC 0x3, 0
011 3001 MOVLW 0x1
012 0086 MOVWF 0x6
31: TRISB = 0b00000001;
013 3001 MOVLW 0x1
014 1683 BSF 0x3, 0x5
015 1303 BCF 0x3, 0x6
016 0086 MOVWF 0x6
32:
33: for(;;)
34: {
35: CLRWDT();
36:
017 0064 CLRWDT
37: PORTC |= (1<<4);
018 1283 BCF 0x3, 0x5
019 1303 BCF 0x3, 0x6
01A 1607 BSF 0x7, 0x4
38: DelayMs(100);
01B 3064 MOVLW 0x64
01C 27E8 CALL 0x7e8
39: PORTC &= ~(1<<4);
01D 30EF MOVLW 0xef
01E 00F5 MOVWF 0x75
01F 1283 BCF 0x3, 0x5
020 1303 BCF 0x3, 0x6
021 0875 MOVF 0x75, W
022 0587 ANDWF 0x7, F
40: DelayMs(100);
023 3064 MOVLW 0x64
024 27E8 CALL 0x7e8
41: }
025 2817 GOTO 0x17
--
Vor der Zeile 23 steht nur die Delay-Routine, die aber keinen Einfluss
auf die Port-Pins nimmt. In diesem Beispiel sollen die Ausgänge RC7 und
RC4 als Ausgänge benutzt werden, RB0 als Eingang. Immer wenn ich RC4
toggel, ändert sich der Zustand an RB0. Am Eingang hängt ein
DCF77-Modul. Es machen auch andere Pins Probleme und die Hardware ist
soweit in Ordnung.
Harald schrieb: > Der Bitzugriff auf einzelne Portbits ist eigentlich gerade eine Stärke > des PICs. Ich vermute, dass man dem Compiler das explizit sagen muss. So > nach deiner Beschreibung macht er daraus einen read-modify-write für den > ganzen Port. Weißt du wo? Ich arbeite zum ersten Mal mit dem Hi-Tech-C-Compiler und habe bislang noch nichts gefunden.
Das war nur eine Vermutung mit der Einstellbarkeit. Die Zeile PORTC &= ~(1<<4); wird ja tatsächlich in einen r-m-w übersetzt. Erstmal wird 0xEF ins Scratch-RAM geschrieben (Adresse 0x75). Dann erfolgt das leidige wählen der richtigen Page. Anschliessend wird das W-Register (Akku) mit dem Inhalt von 0x75 geladen (also dem Wert 0xEF). In Zeile 022 passiert es dann. Das Register 0x07 (Port C) wird mit W verundet und nach 0x07 zurückgeschrieben. 01D 30EF MOVLW 0xef 01E 00F5 MOVWF 0x75 01F 1283 BCF 0x3, 0x5 020 1303 BCF 0x3, 0x6 021 0875 MOVF 0x75, W 022 0587 ANDWF 0x7, F Erstmal ist das ein Wahnsinnsaufwand, denn es gibt auch eine Direktzuweisung für den Akku W --> MOVLW 0xEF hätte es auch getan, ganz ohne Scratch-RAM. In korrekter Bitzuweisung müsste es wie folgt aussehen: BCF 0x3, 0x5 BCF 0x3, 0x6 BCF 0x7, 0x4 Witzig, beim Setzen des Bits hat der Compiler das hinbekommen: 37: PORTC |= (1<<4); 018 1283 BCF 0x3, 0x5 019 1303 BCF 0x3, 0x6 01A 1607 BSF 0x7, 0x4 Die von dir verwendete Schreibweise zum Setzen und Löschen von Portbits ist sehr AVR-typisch, da keine Bitunterstützung. Bei jedem Compiler, der für bitoptimierte Maschinen geschrieben ist (eben auch PIC) gibt es meist spezielle "language extensions" oder Makros, die dann bei der Übersetzung zum gewünschten Resultat führen. Beim Keil C51 oder bei den C167-Compilern (Tasking/Keil) gibt es so etwas auch. Leider kenne ich mich bei dem von dir genutzten Compiler nicht aus. Gibt es ein Handbuch oder mindestens ein paar Demo-Codes?
Ach so, ja beim PIC ist die Adresse für Port-Input und -Output identisch. Beim AVR warst (bzw. bist) Du es ja gewohnt, die Register PORTx und PINx zu benutzen. Normalerweise ist das in den meisten Fällen unproblematisch, vorausgesetzt der Compiler baut keinen Mist. Beim AVR indes ist das auch nicht ohne Probleme, da hat man auf anderer Ebene die r-m-w Problematik.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.