PIN-Abfrage bei PICs

Hallo Freunde,

Habe das hier schon letztens gefragt, aber keine Antwort bekommen. Jetzt, da alle aus dem Urlaub wieder da sind, probiere ich es einfach nochmal. Bitte entschuldigt dies.

Ich benutze einen PIC 18F242 und den Compiler C18 von Microchip (also Sprache C).

Meine Frage ist nun, wie ich den Zustand eines PINs abfrage. Mit

if(PORTAbits.RA0==1)

oder

if(PORTAbits.RA0)

geht es nicht, er reagiert einfach nicht auf andere Zustände am Eingang A0. Natürlich frage ich den Eingang zyklische ab, ist ja klar.

Dummerweise liegt an diesem PIN auch der ADU-Eingang. Muss man den vorher abschalten? Wenn ja, wie?

Danke für eure Hilfe

der Günther

Hallo Günther,

ich hatte gedacht, es interessiert dich nicht. Aus diesem Grund hatte ich meine Antwort wieder gelöscht.

Also:

Laut Datenblatt
http://ww1.microchip.com/downloads/en/DeviceDoc/3963…
Seite 107
musst du den Port erst als digital I/O initialisieren. Beachte dazu das graue Feld:
„On a Power-on Reset, RA5 and RA3:RA0
are configured as analog inputs and read
as ‘0’. RA4 is configured as a digital input.“

D.h., sie sind im Inital State als Analoge Eingänge konfiguriert.
Im Example 10-1 steht, wie man die Ports als DIO initialisiert.
Beachte auch die nachfolgende Tabelle 10-1.

Falls es noch Probleme gibt, melde dich einfach noch mal.

Steven

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Korrektur
Das Datenblatt war für den neueren Typ 18F2420, gilt aber auch.

Hier ist das ältere für den 18Fxx2
http://ww1.microchip.com/downloads/en/DeviceDoc/3956…

Dort steht das Gleiche auf Seite 89.

Steven

1 „Gefällt mir“

RE2: PIN-Abfrage bei PICs
Hallo Steven,

Danke, nett von dir zu hören. Ich werde das mal probieren und mich morgen nochmal melden.

Gibt es noch etwas, das ich abschalten muss? Ich brauche nämlich nur die digitalen I/O. Was ist denn sonst noch so standardmäßig eingeschaltet?

Gibt es außer der Konfiguration noch mehr zu beachten bei der Initialisierung?

Bin Dankbar für deine Hilfe.

Hallo Günther,

Gibt es noch etwas, das ich abschalten muss? Ich brauche
nämlich nur die digitalen I/O. Was ist denn sonst noch so
standardmäßig eingeschaltet?

Gibt es außer der Konfiguration noch mehr zu beachten bei der
Initialisierung?

Bin Dankbar für deine Hilfe.

Ehrlich gesagt, ich weiß es nicht. Ich habe es noch nicht ausprobiert. ich sage immer „Datenblatt lesen, da steht alles.“ Und jetzt, wo du deine Probleme schilderst, wundert mich gar nichts mehr, dass ich bei meinem 16F872 das LCD nicht ansteuern konnte. Ich hätte wohl mal ins Datenblatt sehen sollen. Ich bin auch zu faul dafür.

Hallo Günther, hallo Steven,

Gibt es noch etwas, das ich abschalten muss? Ich brauche
nämlich nur die digitalen I/O. Was ist denn sonst noch so
standardmäßig eingeschaltet?

Bei manchen Pics (z.B. 18Fxx20) muß für einige Ports auch ein Comparator-Modul richtig gesetzt sein.

Ehrlich gesagt, ich weiß es nicht. Ich habe es noch nicht
ausprobiert. ich sage immer „Datenblatt lesen, da steht
alles.“

Das ist leider der einzige Tip. Am einfachsten bei den PICS ist es, nur genau das Kapitel I/O-Ports zu lesen. Da ist für jeden Port (A,B,…H) zum einen ein Blockschaltbild, woraus man erkennen kann, was möglich ist, was möglicherweise stört, und in der Pic-Manier sind die relevanten Register aufgeführt, mit den unrelevanten Bits in grau.

Gruß
achim

Hallo Freunde,

vielen Dank für eure Hilfe. Aber es nutzt alles nichts, es geht nicht.

Also: Ich habe nun versucht, das Pin abzufragen und als das nach mehrmaliger Zuhilfenahme des Datenblattes nicht ging, habe ich mal geschaut, ob der überhaupt in diese Schleife reingeht. Und irgendwie geht schon das nicht so ganz.

Habe dazu folgendes Testprogramm geschrieben:

#include 
#include 


#pragma romdata CONFIG
\_CONFIG\_DECL (
0b00100101, \
0b00000000, \
0b00001110, \
0b00000001, \
0b10000000, \
0b00001111, \
0b11000000, \
0b00001111, \
0b11100000, \
0b00001111, \
0b01000000 \
);
#pragma romdata
/\*
Config:
1H: !OSCEN=1, FOSC[2..0]=001; OSC switch disable, EC oscillator
2L: BOR disabled; !PWRTEN enabled (=0)
2H: WDT disabled
3H: standard
4L: Debugger diabled, ICSP disabled, stack full reset disabled
5L: no code protection
5H: no code protection
6L: no code protection
6H: no code protection
7L: no code protection
7H: no code protection
\*/
void main (void){
 int cnt, zaehler; 
 PORTA=0x00; //Latches löschen (zur Sicherheit)
 PORTB=0x00;
 PORTC=0x00;
 ADCON1=0x07;
 TRISB=0b00000000; //Ports auf Ausgang
 TRISC=0b00000000;
 TRISA=0b00000000;
 cnt=0; //Zählvariable initialisieren
 while (1){
 cnt=cnt+1; 
 PORTBbits.RB4 = 1; //eine LED an, zum Test ob in Schleife eingetreten
 if(cnt\>0x3E8){
 PORTBbits.RB5 = 1; //andere LED an
 }else{
 PORTBbits.RB5 = 0; //andere LED aus
 }
 if(cnt\>0x7D0){
 cnt=0;
 }
 for(zaehler=0; zaehler

Soweit. Er sollte also die LED an RB4 anmachen und die an RB5 blinken lassen. Die an RB4 geht auch an, die an RB5 nicht bestimmungsgemäß. Manchmal nach dem Einschalten oder Reset ist sie aus, manchmal an. Blinken tut sie gar nicht. Sehr Mysteriös.

Ich benutze einen 10MHz Externen Oszillator, die Versorgungsspannung ist 5V.
Bin etwas ratlos. Das sollte doch eigentlich kein Problem sein, oder?

Bin dankbar für jede Hilfe. 
der Günther

Hi!

Ich weiß ja nicht, wie gut dein Compiler ist, den du benutzt, aber kann es sein, daß du unter Umständen mit deinen Zählervariablen den zulässigen Wertebereich überschreitest? Erzeugt der Compiler wirklich eine 16bit-Zahl, wenn du sie einfach mit einem Wert der größer 8bit ist, initialisierst? Oder mußt du selbst eine Routine schreiben, in der du zwei Byte als eine Variable definierst?

Probier einfach mal folgendes: Schreibe in die Zählervariablen einen Wert, der sich mit 8 Bit darstellen läßt. Dann schau mal, ob die Lampe blinkt (vielleicht wirst du kein Blinken feststellen können, weil es zu schnell ist, aber zumindest sollte sie zuverlässig angehen).

Wenn es daran gelegen hat, kommst du nicht herum, eine Routine für 16Bit-Variablen zu schreiben.

Flo

Hallo Günther,

ich bin mir nicht ganz sicher, aber wenn du einen 10MHz-Oszi verwendest, solltest du da nicht statt
FOSC[2…0]=001;
eher
FOSC[2…0]=010;
eintragen (für HS)?
M.E. ist XT nur bis 4MHz.

Ich kenne mich mit dem C18 Compiler nicht aus, ich nehme immer den CSC oder den PICLite, so ist es auch ziemlich schweirig, das CONFIG-Wort zu lesen. I.a. lasse ich es immer weg und stelle es bei meinem Programmer
http://my-japan.de/electronics/microchip/prog7.html
unter IC-PROG dann ein. Das ist manchmal transparenter.

Die Schleife ist etwas ungewöhnlich, aber akzeptabel. Ich hätte sie bur von 0…1000 zählen lassen und den Pin ver-exklusiiv-odert. So habe ich das zum Test bei meinem MSP430 gemacht. Der C18 müsste auch sowas kennen. Wenn nicht, nimmt man eine Variable, xort diese und schreibt den Wert in den Pin.

Steven

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Günther,

ich bin mir nicht ganz sicher, aber wenn du einen 10MHz-Oszi
verwendest, solltest du da nicht statt
FOSC[2…0]=001;
eher
FOSC[2…0]=010;
eintragen (für HS)?
M.E. ist XT nur bis 4MHz.

Das werde ich mal überprüfen. Danke für den Tipp.

Die Schleife ist etwas ungewöhnlich, aber akzeptabel. Ich
hätte sie bur von 0…1000 zählen lassen und den Pin
ver-exklusiiv-odert. So habe ich das zum Test bei meinem
MSP430 gemacht. Der C18 müsste auch sowas kennen. Wenn nicht,
nimmt man eine Variable, xort diese und schreibt den Wert in
den Pin.

Ich wollte das so einfach wie möglich machen und nicht noch mehr Unsicherheiten reinbringen, von wegen: was kann der Compiler, was nicht. Der Compiler hat die 16-bit-zahl nicht angemeckert. Daher nahm ich sie. Allerdings meckert er auch keine 128-bit-zahlen an.

Ich habe mir jetzt mal die erzeugten Assemblerfiles angesehen und siehe da: Aus den Schleifen werden sofortige unbedingte Sprünge. Soll heißen: While springt immer wieder auf sich selbst, ohne seinen Inhalt auszuführen. Auch die For-Schleifen würden nur x-mal auf sich selbst springen und danach würde ordnungsgemäß alles nacheinander abgearbeitet, eben nur einmal und nicht x-mal.
Ich habe dann etwas rumprobiert und bemerkt, wenn ich etwas direkt hinter das for-Kommando schreibe wird es auch wie erwartet wiederholt.

also habe ich den gleichen Test hiermit gemacht:

void blink(void){
 int zaehler;
 PORTBbits.RB4 = 1; 
 for(zaehler=0; zaehler
In der oben beschriebenen main rufe ich nur noch die blink()-routine auf und die sich selbst. Im Prinzip eine Endlosschleife. 

Aber auch das funktioniert nicht. Wo liegt denn mein Fehler? Ich lade mir nachher mal nen anderen Compiler runter. Das hält man ja nicht aus. 

Bin weiterhin offen für Vorschläge. 

der Günther

Hallo Günther,

probier mal folgendes:

statt
PORTBbits.RB4 = 1;
Schreibe
LATBbits.LATB4 = 1;

Steven

Hi!

In der oben beschriebenen main rufe ich nur noch die
blink()-routine auf und die sich selbst. Im Prinzip eine
Endlosschleife.

Aber auch das funktioniert nicht. Wo liegt denn mein Fehler?
Ich lade mir nachher mal nen anderen Compiler runter. Das hält
man ja nicht aus.

Natürlich funtkioniert das mit der verschachtelten Funktion nicht. Du hast ja nur eine endliche Anzahl von Rückspungadressen zur Verfügung. Jedes mal, wenn sich die Funktion wieder aufruft, wird erneut dieser Wert abgelegt, die Aufrufende Funktion wird aber nie verlassen.

Hast du inzwischen den Wert der Zählervariable mal auf 8bit beschränkt? Nur weil der Compiler nicht meckert, heißt das nicht, das es auch funktiniert.

Hallo Günther,

nochmal.

ich hab das mal mit dem CSC-Compiler übersetzt:
Raus kam dabei folgendes:

0004: CLRF FF8
0006: BCF FD0.7
0008: CLRF FEA
000A: CLRF FE9
000C: MOVLW 06
000E: MOVWF FC1
....................
.................... int cnt, zaehler;
.................... output\_a(0); //Latches löschen (zur Sicherheit)
0010: MOVLW 00
0012: MOVWF F92
0014: CLRF F89
.................... output\_b(0);
0016: MOVWF F93
0018: CLRF F8A
.................... output\_c(0);
001A: MOVWF F94
001C: CLRF F8B
.................... set\_tris\_a(0b00000000); //Ports auf Ausgang
001E: MOVWF F92
.................... set\_tris\_b(0b00000000);
0020: MOVWF F93
.................... set\_tris\_c(0b00000000);
0022: MOVWF F94
.................... cnt=0; //Zählvariable initialisieren
0024: CLRF 06
.................... while (1){
.................... cnt=cnt+1;
0026: MOVLW 01
0028: ADDWF 06,F
.................... output\_high(PIN\_B4); //eine LED an, zum Test ob in Schleife eingetreten
002A: BCF F93.4
002C: BSF F8A.4
.................... if(cnt\>0x3E8){
.................... output\_high(PIN\_B5); //andere LED an
.................... }
.................... else{
.................... output\_low(PIN\_B5); //andere LED aus
002E: BCF F93.5
0030: BCF F8A.5
.................... }
.................... if(cnt\>0x7D0){
.................... cnt=0;
.................... }
.................... }
0032: GOTO 0026

Wie du siehst, passiert nichts.

Der Grund liegt in der Initialisierung der Variablen cnt.
Wird diese als long int oder besser als unsigned long int deklariert, kommt folgendes raus:

.................... void main(void)
.................... {
0004: CLRF FF8
0006: BCF FD0.7
0008: CLRF FEA
000A: CLRF FE9
000C: MOVLW 06
000E: MOVWF FC1
....................
.................... unsigned long int cnt;
.................... output\_a(0); //Latches löschen (zur Sicherheit)
0010: MOVLW 00
0012: MOVWF F92
0014: CLRF F89
.................... output\_b(0);
0016: MOVWF F93
0018: CLRF F8A
.................... output\_c(0);
001A: MOVWF F94
001C: CLRF F8B
.................... set\_tris\_a(0b00000000); //Ports auf Ausgang
001E: MOVWF F92
.................... set\_tris\_b(0b00000000);
0020: MOVWF F93
.................... set\_tris\_c(0b00000000);
0022: MOVWF F94
.................... cnt=0; //Zählvariable initialisieren
0024: CLRF 07
0026: CLRF 06
.................... while (1){
.................... output\_high(PIN\_B4); //eine LED an, zum Test ob in Schleife eingetreten
0028: BCF F93.4
002A: BSF F8A.4
.................... cnt = cnt + 1;
002C: MOVLW 01
002E: ADDWF 06,F
0030: MOVLW 00
0032: ADDWFC 07,F
.................... if(cnt\>1000)
.................... {
0034: MOVF 07,W
0036: SUBLW 02
0038: BTFSC FD8.0
003A: GOTO 0058
003E: XORLW FF
0040: BTFSS FD8.2
0042: GOTO 0050
0046: MOVF 06,W
0048: SUBLW E8
004A: BTFSC FD8.0
004C: GOTO 0058
.................... output\_high(PIN\_B5);
0050: BCF F93.5
0052: BSF F8A.5
.................... }
.................... else
.................... {
0054: GOTO 005C
.................... output\_low(PIN\_B5);
0058: BCF F93.5
005A: BCF F8A.5
.................... }
.................... if(cnt\>0x7D0)
.................... {
005C: MOVF 07,W
005E: SUBLW 06
0060: BTFSC FD8.0
0062: GOTO 007C
0066: XORLW FF
0068: BTFSS FD8.2
006A: GOTO 0078
006E: MOVF 06,W
0070: SUBLW D0
0072: BTFSC FD8.0
0074: GOTO 007C
.................... cnt=0;
0078: CLRF 07
007A: CLRF 06
.................... }
.................... }
007C: GOTO 0028
.................... }

Du siehst, jetzt sind die Schleifen vorhanden.

Aber Vorsicht:
Ich weiß jetzt nicht, wie das beim PIC18F ist, aber normalerweise wird der externe Takt geviertelt, dh, er arbeitet intern mit 2,5 MHz. Deine LED blinkt mit 1/1000 dieser Frequenz, also 2,5 kHz. Meinst du, du siehst da noch etwas? :smile:

Steven

1 „Gefällt mir“

Hallo Steven,

Ich weiß jetzt nicht, wie das beim PIC18F ist, aber
normalerweise wird der externe Takt geviertelt, dh, er
arbeitet intern mit 2,5 MHz. Deine LED blinkt mit 1/1000
dieser Frequenz, also 2,5 kHz. Meinst du, du siehst da noch
etwas? :smile:

Dort ist es genauso. Aber sie sollte doch merklich dunkler werden, schließlich ist sie nur die halbe Zeit an. Und wie gesagt, sie leuchtet manchmal gar nicht, nach dem Einschalten.

Kannst du mir mal ne URL von deinem Compiler geben? Würde ihn gern mal probieren. Was für nen Editor benutzt du denn dazu? Das MPLAB hat kein sonderlich gutes Highlighting und die Debug-funktionen lassen zu wünschen übrig.

Danke für deine Hilfe.

der Günther

Hallo Papa-Schlumpf,

Natürlich funtkioniert das mit der verschachtelten Funktion
nicht. Du hast ja nur eine endliche Anzahl von
Rückspungadressen zur Verfügung. Jedes mal, wenn sich die
Funktion wieder aufruft, wird erneut dieser Wert abgelegt, die
Aufrufende Funktion wird aber nie verlassen.

Richtig, allerdings sollte sie dann eine kurze Weile leuchten und nicht einfach mal aus oder an bleiben.

Hast du inzwischen den Wert der Zählervariable mal auf 8bit
beschränkt? Nur weil der Compiler nicht meckert, heißt das
nicht, das es auch funktiniert.

Ich dachte, das erkennt man aus dem Code. Habe ich gemacht, hat aber gar nichts genutzt.

der Günther

Hallo Günther,

Dort ist es genauso. Aber sie sollte doch merklich dunkler
werden, schließlich ist sie nur die halbe Zeit an. Und wie
gesagt, sie leuchtet manchmal gar nicht, nach dem Einschalten.

Ja, sie sollte mit halber Helligkeit leuchten. Hattest du den Oszillator auf HS gestellt. Das musst du machen. Und die Variable muss long werden.

Kannst du mir mal ne URL von deinem Compiler geben? Würde ihn
gern mal probieren. Was für nen Editor benutzt du denn dazu?
Das MPLAB hat kein sonderlich gutes Highlighting und die
Debug-funktionen lassen zu wünschen übrig.

Er bringt eienn Editor mit.
Es war nicht der CSC sonder der CCS-Compiler:
http://www.ccsinfo.com/picc.shtml

MPLAB hat aber einen sehr guten Simulator.
Ich hatte ihn früher mit PICLite verwendet, in der 5.3-Version. In der 6eer läuft er nicht mehr richtig.

1 „Gefällt mir“

Hallo Papa-Schlumpf,

Natürlich funtkioniert das mit der verschachtelten Funktion
nicht. Du hast ja nur eine endliche Anzahl von
Rückspungadressen zur Verfügung. Jedes mal, wenn sich die
Funktion wieder aufruft, wird erneut dieser Wert abgelegt, die
Aufrufende Funktion wird aber nie verlassen.

Richtig, allerdings sollte sie dann eine kurze Weile leuchten
und nicht einfach mal aus oder an bleiben.

Hallo Günther,

das stimmt nicht. Es sind Branches, nur Subroutinen benötigen Rücksprungadressen.

???
Hi Steven!

das stimmt nicht. Es sind Branches, nur Subroutinen benötigen :Rücksprungadressen.

Aha, und was ist das dann deiner Meinung nach in der vorletzten Zeile?

void blink(void){
int zaehler;
PORTBbits.RB4 = 1;
for(zaehler=0; zaehler

Aha, und was ist das dann deiner Meinung nach in der
vorletzten Zeile?

Es werden Gotos verwendet.

Hallo Steven,

Vielen Dank für deine Hilfe. Ich habe mal einen anderen Compiler probiert und siehe da, es ging sofort.

Es lag tatsächlich nur am Compiler. Sehr erstaunlich. Ich danke dir wie wahnsinnig, hast mir sehr viel weitergeholfen.

der Günther