Forum: Mikrocontroller und Digitale Elektronik variables Bit setzen


von Michael S. (rbs_phoenix)


Lesenswert?

Hallo. Ich will ein Programm in C für einen PIC schreiben. In dem 
Programm will ich eine Funktion haben, der an einem Ausgang (z.b. 
PORTB.0) was macht. Jedoch will ich die Information, welcher Ausgang es 
ist, als Parameter in die Funktion übergeben.

Hier mein Versuch, der jedoch nicht funktioniert hat (Funktionen sind 
ziemlich sinnlos, Einstellungen sind auch getroffen, es geht mir hier 
aber ums Prinzip):
1
void ioschalt(bit ausgang){
2
  ausgang = 1;
3
}
4
5
void main(void){
6
  bit testio @ PORTB.0;
7
  while(1){
8
    ioschalt(&testio);    //Adresse von testio übergeben
9
  }
10
}

Wenn ich das mit cc5x compiliere, kommt eine Fehlermeldung beim Aufruf 
der Funktion. Wenn ich oben statt "bit ausgang" "char ausgang" schreibe, 
ist der Fehler weg, er erzeugt auch eine asm und hex, funktionieren tuts 
dann aber auch nicht.

Hat jemand eine Idee, wie man sowas machen kann? Also quasi die 
Adress-Information in eine Variable übergeben. Muss ich das mit dem * 
statt dem & übergeben?

von Michael S. (rbs_phoenix)


Lesenswert?

Hat keiner einen Vorschlag? Oder ist der Threade einfach nur zu weit 
nach hinten gewandert.

von Lehrmann M. (ubimbo)


Lesenswert?

Hmmm ich glaube hier ist jeder nur sprachlos was das "Programming" 
betrifft. Das ist doch nicht dein Ernst oder ?

Ich empfehle dir dringend dich mit C zu beschäftigen. Nimm zuerst 
"normales" ANSI-C. Wenn du das dann beherrschst dann kannst du darüber 
nachdenken, das ganze auf den PIC zu bringen.

Womit du dich gerade rumschlägst sind sog. Pointer.

http://www.hs-augsburg.de/~sandman/c_von_a_bis_z/c_014_000.htm

Wenn du die Pointer nicht behrrschst dann versuch ohne Pointer 
auszukommen.
Leider muss ich dir mitteilen, dass du die Pointer nicht beherrschst. 
Ist nicht böse oder persönlich gemeint aber du hast sie einfach noch 
nicht verstanden.

Michael Skropski schrieb:
> bit testio @ PORTB.0;

Auch wenn ich mit dem CC5X nochnie gearbeitet habe:

Ich muss dir sagen, dass das Programm absolut keinen Sinn ergibt. Selbst 
wenn das compiliert gibt das NULL Sinn.

Michael Skropski schrieb:
> void ioschalt(bit ausgang){
>   ausgang = 1;
> }
>
> void main(void){
>   bit testio @ PORTB.0;
>   while(1){
>     ioschalt(&testio);    //Adresse von testio übergeben
>   }
> }

Du deklarierst eine Variable testio als Bit (1/0) bei PORTB0. Was willst 
du damit bezwecken?

In der Endlosschleife übergibst du dann den Wert von testio (also den 
Wert den PORTB0 bei der Deklaration hat an die Funktion ioschalt.

In der aufgerufenen Funktion weisst du dann der Variable ausgang den 
Wert 1 zu.

Was soll da deiner Meinung nach passieren?

Ich sitze jetzt seit knapp 5 Minuten vor deinem Code und versuche mir zu 
überlegen was du bezwecken willst. Wenn es das ist was ich denke dann 
hast du von PIC und Programmieren so viel Ahnung wie ne Kuh vom Fliegen:

Du hast dir gedacht durch "ausgang = 1;" geht es nun zurück zu "bit 
testio @ PORTB.0;" und damit wird PORTB = 1 ?

Ich gebe dir wirklich den Rat und schau dir C nochmal genau an:

Die Variable ausgang ist eine lokale Variable. D.h. sie existiert nur in 
der Funktion ioschalt().

Wenn du ausgang = 1 setzt dann hat sie halt den Wert aber das 
interessiert niemanden.

bit testio @ PORTB.0; wird nur einmal ausgeführt - das heißt nicht, dass 
wenn du testio veränderst, dass dann PORTB auch den neuen Wert von 
testio annimmt !

von Lehrmann M. (ubimbo)


Lesenswert?

Okay hier wie man's machen könnte:
1
void schaltio(){
2
 PORTB=1;
3
}
4
5
void main() {
6
 TRISB=0; // ganzer PortB ist Ausgang (je nach PIC und Sleep nötig / unnötig)
7
 while(1){
8
  schaltio();
9
 }
10
}

von (prx) A. K. (prx)


Lesenswert?

Bits sind auf PICs nicht einzeln frei und insbesondere indirekt 
adressierbar, auch wenn der Compiler mit der nicht standardkonformen 
@-Mimik eine Bitadressierung vortäuscht. Folglich muss man die Ports als 
Ganzes ansprechen und mit deren Adresse hantieren. Dem fügt man dann 
noch die Bitposition innerhalb des Ports hinzu, vorzusweise als 
Bitmaske. Um dann klassische Bitoperationen auf ganze Bytes anzuwenden. 
Das geht dann auch indirekt.

Also könnte sowas in der Art funktionieren:
1
  volatile uint8_t *portPtr = &LATB;
2
  uint8_t bitMask = 1<<5;
3
  *portPtr |= bitMask;

von Karl H. (kbuchegg)


Lesenswert?

Michael Skropski schrieb:

>   bit testio @ PORTB.0;

gewöhn dich daran, von solchen Spezialitäten Abschied zu nehmen

   PORTB |= ( 1 << Bit );

setzt das Bit mit der Nummer Bit am Port

   PORTB &= ~( 1 << Bit );

löscht das Bit mit der Nummer in Bit am Port

von Lehrmann M. (ubimbo)


Lesenswert?

Was mich wundert ist zum Beispiel: Warum übergibtst du Parameter? Die 
brauchst du doch garnicht für deine Funktion.

eines muss dir klar sein:

Unsere Funktion:
1
int schaltio( int ausgang ){
2
return(ausgang/2);
3
}


Ein Funktionsaufruf wie

[avrasm]schaltio(22);[avrasm]

bewirkt, dass die 22 an schaltio übergeben wird (one-way)

in der Funktion schaltio() nimmt die lokale Variable ausgang (die gibt's 
nur in der Funktion schaltio()) den Wert 22 an.

Der Rückgabewert der Funktion schaltio() ist logischerweise 11 (=22/2)

Beachte, dass die Funktion mit "int schaltio()" beginnt und nicht mit 
"void schaltio()".

Int bedeutet, dass ein Integer zurückgegeben wird - void bedeutet, dass 
nichts zurückgegeben wird / werden kann.

Bitte fang mit C ganz von Vorne an - klau dir keinen Code und hoffe dass 
das hier kein andere liest.

Es tut mir leid aber das ist das schlimmst was ich je in C gesehen habe.

Ich hab dir weiter oben einen Link gepostet (1. Antwort). Bring dir 
damit C bei. Arbeite alles durch und fang dann an das auf PICs zu 
machen. BITTE =)

Glaub mir wir haben alle so angefangen und es geht einfach nicht 
anderst. Du hast keine Ahnung von C und versuchst C auf einen 
Microcontroller zu bringen. Das ist in gewissen Maßen hoffnungslos. Du 
willst ja keine Mist entwickeln sondern was gescheites und dir nicht 
immer Code zusammenkopieren. Und glaube bitte nicht, dass du das auch so 
verstehst und die Grundlagen nicht brauchst - jeder denkt so =) Du hast 
uns das schon eindrucksvoll bewiesen.

Nichtsdesto trotz helfe ich dir gerne bei deinen PIC spezifischen 
Themen.


Viel Spaß

von Michael S. (rbs_phoenix)


Lesenswert?

AAllsoo.. Ich hab schon erfolgreich Programme mit C für PICs 
geschrieben, die genauso funktioniert haben wie sie sollten. Und mit:

Michael Skropski schrieb:
> Hier mein Versuch, der jedoch nicht funktioniert hat (Funktionen sind
> ziemlich sinnlos, Einstellungen sind auch getroffen, es geht mir hier
> aber ums Prinzip):

wollte ich verdeutlichen, dass mir Bewusst ist, dass die Funktion 
absolut sinnlos ist, jedoch vom Prinzip her das ist, was ich suche. Ich 
will eine 1-Wire-ähnliche Funktion zum senden schreiben. 1-Wire -> 1 Bit 
als Ausgang. Die Information, welches Bit das ist, will ich zusammen mit 
einem Byte in die Funktion übergeben. Aus diesem Grund kann ich aber 
z.B. PORTB.0 nicht in die Funktion schreiben, denn dann kann ich das nur 
für den PORTB.0 benutzen.

Es stimmt zwar, dass ich mit C quasi erst angefangen habe, jedoch hab 
ich weder dabei noch vorher in ca 3-4 Jahren PHP einen Pointer 
gebraucht. Daher weiß ich nicht, wie das geht.



Lehrmann Michael schrieb:
> Michael Skropski schrieb:
>> bit testio @ PORTB.0;
>
> Auch wenn ich mit dem CC5X nochnie gearbeitet habe:
>
> Ich muss dir sagen, dass das Programm absolut keinen Sinn ergibt. Selbst
> wenn das compiliert gibt das NULL Sinn.

Laut einer Anleitung zu cc5x ist das eine Bit-zuweisung, sodass testio 
representiv für PORTB.0 steht. Wenn man das allgemein nciht macht, 
wusste ich das nicht, jedoch hat es bisher einwandtfrei funktioniert.



Lehrmann Michael schrieb:
> Du deklarierst eine Variable testio als Bit (1/0) bei PORTB0. Was willst
> du damit bezwecken?
>
> In der Endlosschleife übergibst du dann den Wert von testio (also den
> Wert den PORTB0 bei der Deklaration hat an die Funktion ioschalt.


Ich hab verscuht, dass die in der Funktion deklarierte Variable ausgang 
in diesem Fall PORTB.0 representiert. Quasi will ich, dass, wenn ich 
ausgang setze, ansich testio und somit PORTB.0 gesetzt wird. Das geht 
dann also anscheinend mit einem Pointer.



Wie gesagt wollte ich eine allgemeine Funktion schreiben, wo etwas mit 
einem Ausgangsbit passiert (ob eine Datenübertragung oder simples 
einschalten ist wie gesagt um das Prinzip zu verstehen egal), ich aber 
beim Aufruf der Funktion bestimmen will, mit welchem Bit.

von Karl H. (kbuchegg)


Lesenswert?

Michael Skropski schrieb:

> Laut einer Anleitung zu cc5x ist das eine Bit-zuweisung, sodass testio
> representiv für PORTB.0 steht. Wenn man das allgemein nciht macht,
> wusste ich das nicht, jedoch hat es bisher einwandtfrei funktioniert.

Du musst dir bewusst sein, das das eine Erweiterung ist, die der 
Compiler-Hersteller extra für diesen Compiler erfunden hat.

Und jetzt hast du auch gesehen, wo die Grenzen dieser Erweiterung 
liegen. Mit der üblichen C-Standardlösung gibt es diese Grenzen nicht. 
Auch wenn das ein wenig Verlust von Bequemlichkeit in der Tipparbeit 
bedeutet.

von Michael Skropski (Gast)


Lesenswert?

Würde das denn gehen, wenn ich als Übergabe-Parameter PORTB.0 schreibe 
oder liegt es allgemein am cc5x-Compiler. Wenn es am Compiler liegt, 
würde es dann mit MikroC for PIC gehen? Hat mir ein Freund empfohlen und 
ist wohl bis 2 kB kostenfrei.

von Lehrmann M. (ubimbo)


Lesenswert?

Michael Skropski schrieb:
> Ich hab verscuht, dass die in der Funktion deklarierte Variable ausgang
> in diesem Fall PORTB.0 representiert. Quasi will ich, dass, wenn ich
> ausgang setze, ansich testio und somit PORTB.0 gesetzt wird. Das geht
> dann also anscheinend mit einem Pointer.

Tja das mit dem Pointer den du falsch verwenden hast ändert noch nichts 
daran, dass es so nicht geht. PortB wird trotzdem immernoch nur 
verändert wenn du das anordnest. Das tust du nur in der Deklaration.

Dass du schon erfolgreicher Programme geschrieben hast möchte ich in 
Frage stellen ... Aber nichts für ungut. Lerne C einfach von Grund auf - 
wie jeder es tun muss .

von Michael S. (rbs_phoenix)


Lesenswert?

Lehrmann Michael schrieb:
> Dass du schon erfolgreicher Programme geschrieben hast möchte ich in
> Frage stellen

Dann tu das, weil du ja weißt, was ich alles gemacht hab. Da ich nicht 
von ausgehe, dass noch sinnvolle Antworten kommen, seht diesen Thread 
als Closed.

Trotzdem ein Danke an die, die mir wirklich Helfen wollten.

PS: Nobody is perfect. Habe schon gesehen, das hier wer im Forum gefragt 
hat, wie man einen Spannungsteiler berechnet. Der wurde allerdings nicht 
so angefahren, wie ich. Also keine Ahnung, was bei mir das Problem ist. 
Naja. Werde mal wen anderes Fragen.

von Karl H. (kbuchegg)


Lesenswert?

Michael Skropski schrieb:
> Der wurde allerdings nicht
> so angefahren, wie ich.

Dem wurde allerdings auch nicht 3 mal erklärt, dass er eine 
Spezialsyntax seines Compilers benutzt, die so erst mal toll aussieht 
aber ihre Schwächen hat.

> Also keine Ahnung, was bei mir das Problem ist.

Das Problem ist, kurz gesagt, dass die kleinste Einheit mit der in C 
operiert wird, das Byte ist. In C gibt es nicht kleineres. Wenn du doch 
ein Stilmittel dafür hast, dann ist das Compilerspezifisch und 
verallgemeinert nicht.

Du kannst dich drehen und wenden wie du willst. Mit einem Mini-Cooper 
kann man nun mal nicht vernünftig einen 5 Personen Haushalt von München 
nach Hamburg übersiedeln. Egal wieviel du vorher schon gesiedelt bist.

Pfeif auf diese Spezialsyntax, benutze Standard C, so wie alle anderen 
auch, und die bist im Rennen.

> Naja. Werde mal wen anderes Fragen.

Ah ja. Nach der Methode: Wenn mir die Diagnose nicht zusagt, geh ich 
halt zu einem anderen Arzt.

von Michael S. (rbs_phoenix)


Lesenswert?

Karl heinz Buchegger schrieb:
> Dem wurde allerdings auch nicht 3 mal erklärt, dass er eine
> Spezialsyntax seines Compilers benutzt, die so erst mal toll aussieht
> aber ihre Schwächen hat.

war allerdings schon beim ersten oder zweiten Post, aber sei es drumm.


Karl heinz Buchegger schrieb:
> Das Problem ist, kurz gesagt, dass die kleinste Einheit mit der in C
> operiert wird, das Byte ist. In C gibt es nicht kleineres.

Das z.B. hab ich nicht gewusst, weil ich wie gesagt das Tutorial von 
cc5x durchgemacht habe und es da den Datentyp Bit gibt.


Karl heinz Buchegger schrieb:
> Ah ja. Nach der Methode: Wenn mir die Diagnose nicht zusagt, geh ich
> halt zu einem anderen Arzt.

Ne, nach der Methode: Wenn mir hier keiner genau sagt, warum es nicht 
geht oder wie es gehen kann, frag ich wen, der mir mehr sagt, als dass 
ich nicht C programmieren kann..


Aber naja, die Antwort von dir hat jedenfalls meine Frage beantwortet, 
also hat sich das hier jetzt erledigt.

von Karl H. (kbuchegg)


Lesenswert?

Michael Skropski schrieb:

> Ne, nach der Methode: Wenn mir hier keiner genau sagt, warum es nicht
> geht oder wie es gehen kann, frag ich wen, der mir mehr sagt, als dass
> ich nicht C programmieren kann..

Dann solltest du dich mal fragen, warum er dir das wohl gesagt hat

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Bitpointer werden von C nicht unterstützt, war den C-Erfindern wohl zu 
lächerlich.
Ich wüßte jetzt auch keine CPU, die Bitpointer unterstützt.

Man kann sich aber die Funktionen selber schreiben. Anbei mal für nen 
8051.

Natürlich geht das auf Kosten der Geschwindigkeit, wenn man immer erst 
ne Funktion aufruft, anstatt nur einen Befehl. Dein 1-Wire Timing kannst 
Du damit vergessen.

1-Wire braucht ja auch keine mehrere Pins, man kann alle Device parallel 
schalten.
Nur wenn die Leitungen zu lang werden, kann ein Aufteilen helfen. In dem 
Fall legt man aber alle 1-Wire Busse auf einen Port und merkt sich nur 
in einer Masken-Variable, welchen Bus man auswählt. Damit kann man bis 
zu 8 Busse ansprechen (AND/OR) und es ist nur etwas langsamer als der 
Bitbefehl.


Peter

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.