Forum: Compiler & IDEs Port als Variable


von Newby (Gast)


Lesenswert?

Hallo Zusammen,

stehe schon seit Tagen an einen Problem.
Und zwar ist folgendes, habe einen Master (zur Zeit noch ein PC)!
Ca. 7-8 Slave's sollen später dann (wenn ich endlich mal die richtigen 
Teile bekomme)über RS485 kommunizieren.
Zur Zeit hab ich nur einen Master und einen Slave mittels RS232 
verbunden.
Bei den Slaves soll dann immer die gleiche Software kommen und die 
Adresse soll über ein Port mittels Lötbrücken adressiert werden.

Zur Programm-Info: Mein Master schickt eine Adresse die Slaves sollen 
dies mit dem Adress-Port vergleichen und wenn diese stimmt dem Master 
antworten (temperatur schicken)

Meine Frage nun wie kann ich das Port in eine Variable umwandeln - 
irgendwie schaff ich dass nicht. Hat jemand von euch ein paar 
Vorschläge?

mfg Newby

von John-eric K. (mockup)


Lesenswert?

In dem du deinen Port als Eingang definierst und wenn du etwas 
vergleichen willst einfach ausliest.

Erklärt ist es hier:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29

von Fabian O. (xfr)


Lesenswert?

Statt Lötbrücken könntest Du die Adressen im EEPROM des Mikrocontrollers 
speichern. Dann kann auch überall die gleiche Software drauf.

von Newby (Gast)


Lesenswert?

uint8_t Adresse_Nr;
Adresse_Nr = (!(PINC));

if (Adresse_Nr == Adresse_UART)              {
  Adresse_OK = '1';
  }

hab dies so probiert aber irgendwass mach ich da ordenlich falsch ;)
Bei Adresse_UART werden zahlen geschickt. wenn ich z bsp. 1 schicke 
kommt auch eins wieder zurück wenn ich eine Schleife zum hypter terminal 
schicke was der prozessor bekommt.

@Fabian
wie soll das denn funktionieren sorry warscheinlich blöde frage aber ich 
bin relativ neu in C. weil woher sollen die Slaves denn wissen das z 
bsp. Raum 1 die 1 hat dann der raum 2 die 2 usw.

von Fabian O. (xfr)


Lesenswert?

Newby schrieb:
> hab dies so probiert aber irgendwass mach ich da ordenlich falsch ;)
> Bei Adresse_UART werden zahlen geschickt. wenn ich z bsp. 1 schicke
> kommt auch eins wieder zurück wenn ich eine Schleife zum hypter terminal
> schicke was der prozessor bekommt.

Vorschlag:
- Poste den ganzen Programmcode als C-Datei im Anhang.
- Schreib in verständlichen Sätzen:
  - Was Du machst (was schickst Du für Zeichen?).
  - Was das Programm machen soll (was soll es antworten?).
  - Was das Programm tatsächlich macht (was antwortet es?).
  - Wie sieht die Hardware aus? Was ist an welchem Pin angeschlossen,
    welche Spannungen sind an den Pins?

Denk daran, wir wissen das alles nicht. Nur wenn Du es verständlich 
beschreibst, haben wir eine Chance, Dir zu helfen.

Zum EEPROM: Du schreibst einmalig beim Programmieren die Adresse in das 
EEPROM. Bei dem Slave, der in Raum 1 kommt, schreibst Du die Zahl 1 
rein. Bei dem Slave, der in Raum 2 kommt, die Zahl 2. Und so weiter. Der 
Slave vergleicht die per UART empfangene Adresse, mit der in seinem 
EEPROM. Wenn sie gleich sind, antwortet er, ansonsten nicht.

Wenn Du das Programm später mal aktualisieren willst, musst Du beim 
Flashen auswählen, dass das EEPROM nicht neu beschrieben werden soll. 
Dann behält jedes Exemplar seine eingespeicherte Adresse. Dafür musst Du 
die EESAVE-Fuse setzen.

Aber stellt das mal hinten an, erstmal musst Du ein paar 
Programmiergrundlagen lernen ...

von Newby (Gast)


Lesenswert?

Ok Hardware is ein bischen schwierig hab zur zeit einen LM75 extern auf 
meinen MYAVR Board mit Atmega8 (später dann Atemga168)
Daran hängt noch ein Display über I2C was aber zur Zeit nichts zur Sache 
tut.

Meine Eingänge ich glaube man sagt low aktiv sprich sie sind immer '1' 
wenn man sie Schaltet '0'.

Was es macht: es wird später mal in ferner Zukunft eine 
Heizungssteuerung. Zur Zeit ist es ein PC über RS232 auf den Atmega8. 
Will aktuell nur eine Zahl (die später dann vom Master gesendet wird) 
vom PC senden und dass mir der Richtige Slave antwortet (zur Zeit auch 
nur einer angeschlossen)
Als Beispiel: PC sendet 1 => Slave antwortet 20°C

Zur Zeit geht es soweit dass ich die Adresse sende (1) und er mir dann 
die Temperatur zurück zum PC sendet. Was er aber zur Zeit noch nicht 
macht ist eben dass mit dem Port Vergleichen ob es wirklich der richtige 
Slave ist. Sprich bevor mein Atmega die Temperatur zurück sendet, sollte 
er schauen ob er auch wirklich gemeint ist.

while (1) // Mainloop
  {
  Adresse_OK = Adressabfrage(Adresse);

      if (Adresse_OK == '1')                          //wenn Adresse_OK 
richtig - Temp senden
      {
        uart_senden ();    //Temp senden
      }
      else
      {                //sonst nicht beachten
      //putChar (0b11110000);
      }
          }
//////////////////////////////////////////////////////////////////////// 
//
//ab hier Funktion für kontrolle Adresse
#include <avr/io.h>

char Adressabfrage (uint8_t Adresse)
{
char Adresse_OK;
uint8_t Adresse_Nr;
Adresse_Nr = PINB;

if (Adresse_Nr == Adresse)              //Achtung Port invertiert PortD 
vergleich mit Adresse UART
  {
  Adresse_OK = '1';
  }
  else
  {
  Adresse_OK = '0';
  }      // Port D auslesen welche Adresse
return (Adresse_OK);
}

Hoffe es ist soweit verständlich es fehlen natürlich die LM75 auswertung 
und div Init's aber die passt ja eh

von Fabian O. (xfr)


Lesenswert?

OK. Da kann man schon mal mehr mit anfangen. Bitte beim nächsten mal die 
Formatierungstags für C-Code (siehe Hinweis über den Antwortkasten) 
nutzen oder noch besser: KOMPLETT als Anhang anhängen.

Hier der Code erstmal lesbarer formatiert:
1
while (1) // Mainloop
2
{
3
  Adresse_OK = Adressabfrage(Adresse);
4
  if (Adresse_OK == '1') //wenn Adresse_OK richtig - Temp senden
5
  {
6
    uart_senden ();  //Temp senden
7
  }
8
  else
9
  { //sonst nicht beachten
10
      //putChar (0b11110000);
11
  }
12
}
13
14
// ab hier Funktion für kontrolle Adresse
15
#include <avr/io.h>
16
17
char Adressabfrage (uint8_t Adresse)
18
{
19
  char Adresse_OK;
20
  uint8_t Adresse_Nr;
21
  Adresse_Nr = PINB;
22
23
  if (Adresse_Nr == Adresse) //Achtung Port invertiert PortD vergleich mit Adresse UART
24
  {
25
    Adresse_OK = '1';
26
  }
27
  else
28
  {
29
    Adresse_OK = '0';
30
  }
31
  // Port D auslesen welche Adresse
32
  return (Adresse_OK);
33
}

Da Du ihn nicht komplett gepostet hast, ist unklar, ob die Reihenfolge 
der Funktionen überhaupt stimmt. Adressabfrage() muss auf jeden Fall vor 
der main-Funktion deklariert werden:
1
#include <avr/io.h>
2
3
char Adressabfrage (uint8_t Adresse)
4
{
5
  char Adresse_OK;
6
  uint8_t Adresse_Nr;
7
  Adresse_Nr = PINB;
8
9
  if (Adresse_Nr == Adresse) //Achtung Port invertiert PortD vergleich mit Adresse UART
10
  {
11
    Adresse_OK = '1';
12
  }
13
  else
14
  {
15
    Adresse_OK = '0';
16
  }
17
  // Port D auslesen welche Adresse
18
  return (Adresse_OK);
19
}
20
21
while (1) // Mainloop
22
{
23
  Adresse_OK = Adressabfrage(Adresse);
24
  if (Adresse_OK == '1') //wenn Adresse_OK richtig - Temp senden
25
  {
26
    uart_senden ();  //Temp senden
27
  }
28
  else
29
  { //sonst nicht beachten
30
      //putChar (0b11110000);
31
  }
32
}

Die ganze Adressabfrage-Funktion ist kann man zusammenfassen als:
1
char Adressabfrage (uint8_t Adresse)
2
{
3
  return (Adresse == PINB);
4
}

Wenn die Adresse gleich PINB ist, wird 1 (wahr) zurückgegeben. Wenn 
nicht, dann 0 (falsch).

Dann die Hauptschleife:
1
while (1) // Mainloop
2
{
3
  Adresse_OK = Adressabfrage(Adresse);
4
  if (Adresse_OK == '1') //wenn Adresse_OK richtig - Temp senden
5
  {
6
    uart_senden ();  //Temp senden
7
  }
8
  else
9
  { //sonst nicht beachten
10
      //putChar (0b11110000);
11
  }
12
}

Du darfst nicht mit '1' vergleichen. '1' ist das ASCII-Zeichen der 
Ziffer 1. Genau wie 'A' das ASCII-Zeichen für den Buchstaben A ist. Die 
Zahl 1 musst Du ohne ohne Anführungszeichen schreiben:
1
while (1) // Mainloop
2
{
3
  Adresse_OK = Adressabfrage(Adresse);
4
  if (Adresse_OK == 1) //wenn Adresse_OK richtig - Temp senden
5
  {
6
    uart_senden ();  //Temp senden
7
  }
8
  else
9
  { //sonst nicht beachten
10
      //putChar (0b11110000);
11
  }
12
}

Das ist aber auch kein guter Stil, weil in C auch alle anderen Werte 
(außer 0) "wahr" bedeuten, nicht nur 1. Deshalb besser:
1
while (1) // Mainloop
2
{
3
  Adresse_OK = Adressabfrage(Adresse);
4
  if (Adresse_OK != 0) //wenn Adresse_OK richtig - Temp senden
5
  {
6
    uart_senden ();  //Temp senden
7
  }
8
  else
9
  { //sonst nicht beachten
10
      //putChar (0b11110000);
11
  }
12
}

Oder kürzer:
1
while (1) // Mainloop
2
{
3
  Adresse_OK = Adressabfrage(Adresse);
4
  if (Adresse_OK) //wenn Adresse_OK richtig - Temp senden
5
  {
6
    uart_senden ();  //Temp senden
7
  }
8
  else
9
  { //sonst nicht beachten
10
      //putChar (0b11110000);
11
  }
12
}

Und da die Funktion Adressabfrage() so trivial kurz ist, kann man das 
ganze auch einfach zusammenfassen als:
1
while (1) // Mainloop
2
{
3
  if (Adresse == PINB)
4
  {
5
    uart_senden (); //Temp senden
6
  }
7
}

von Newby (Gast)


Lesenswert?

danke soweit einmal - die main und die Adressabfrage sind in der 
richtigen reihenfolge dass passt soweit ein Frage wieso funktioniert 
dies nicht

Adresse_Nr = (!(PINB)); //PortB sollt in die Variable gehen oder?
putChar (Adresse_Nr);   //senden der Variable über UART zum PC

mein PC macht aber nichts hab dies direkt in der main schleife zum 
testen eingebaut oder hab ich das mit dem Port übernehmen falsch 
verstanden.

Aber soweit ich das von Fabian gesehen hab sollte dies doch 
funktionieren wenn ich Adresse_Nr = PINB; funktioniert es

von Fabian O. (xfr)


Lesenswert?

Wenn alls acht Bits der Ports invertiert werden sollen (aus 1 wird 0, 
aus 0 wird 1) musst Du den Operator zum bitweisen invertieren nehmen:
1
Adresse_Nr = ~PINB;

Der !-Operator ist eine logische Negation: Wenn alle Bits der Ports 0 
sind, gibt er 1 zurück. Wenn irgendein Bit des Ports 1 ist, gibt er 0 
zurück. Ist wahrscheinlich nicht, was Du haben wolltest ...

von Newby (Gast)


Lesenswert?

ja genau das ist das was ich gesucht habe gibt es auch einen Trick wie 
man das mit nur einen halben Port macht?? z bsp PD0,PD1,PD2,PD4

nochmal tausend Dank

von Newby (Gast)


Lesenswert?

bzw hab ich jetzt ein bischen falsch ausgedrückt

möchte einfach die letzten 4 bits immer auf 1 und die anderen variabel 
über das Port schalten

von Fabian O. (xfr)


Lesenswert?

Newby schrieb:
> möchte einfach die letzten 4 bits immer auf 1 und die anderen variabel
> über das Port schalten

Na dann mach das doch. Ist alles hier beschrieben:
http://www.mikrocontroller.net/articles/Bitmanipulation

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.