Port Binärzahl in Dezimalzahl umwandeln

OP #579379
Lesenswert?

Hallo erstmal,

bin ein Neuling in Sachen uC-Progarmmierung und habe C im ersten 
Semester vor 2 Jahren "gelernt". Meine erste Frage mag deshalb für die 
erfahrenen unter uns sehr einfach klingen, ich scheitere jedoch bereits 
hieran.

Ich verwende einen AT90CAN128. Es geht um folgendes C-Problem.
AN PORTB sind alle Pins auf Eingang geschalten. PIN G0 dient ebenfalls 
als Eingang. Aufgrund von schaltungsspezifischen Vorgaben ist nur 
jeweils ein PORT high. Wäre z.B. Port B2 High sollte ich folgendes 
Bitmuster bekommen.

PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PG0
0   0   1   0   0   0   0   0   0

Nun möchte ich diese Information in eine dezimale Zahl umwandeln und 
zwar folgendermassen,

PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PG0
0   0   1   0   0   0   0   0   0
1   2   3   4   5   6   7   8   9

und in diesem Fall würde die unsigned char Variable "openport" den Wert 
3 bekommen. Ist kein Port High, dann soll die Variable den Wert 0 
erhalten. Diese Variable steht für den PORT der High ist. Nun mache ich 
das derzeit mit einer "hässlichen" For-Schleife und ich glaube das man 
das wesentlich schöner hinkriegt.
1
void check_active_port_gpi(void)
2
{
3
  unsigned char gpi_ports_high, gpi_ports_low;
4
  unsigned char i,openport=1;  
5

6
  gpi_ports_low  = PINB;
7
  gpi_ports_high = PING;
8
  
9
  for(i=0; i<8; i++)
10
  {
11
    if(bit_is_set(gpi_ports_low,i))
12
    {
13
      i=8;
14
    }
15
    else
16
    {
17
      openport += 1;
18
    }
19
  }
20
if((openport == 8) && (bit_is_set(gpi_ports_high,0)))
21
{
22
  openport += 1;
23
}
24
else
25
{
26
  openport = 0;
27
}
28
}

Vielen Dank für eure Hilfe
OP #579407
Lesenswert?

Vielen Dank erstmal für die schnelle Hilfe,

leider kann ich in meinen C-Büchern und im Web nichts über die Funktion 
finden (Deklaration etc.). Vielleicht könntest du mir eine gute 
Internetseite nennen, wo ich mehr über die Funktion bzw. die Bibliothek 
dazu erfahre.

Vielen Dank

! Nachtrag:

Habe gerade diese Seite gefunden:
http://www.opengroup.org/onlinepubs/009695399/functions/ffs.html

meinst du diese Funktion ?
Gast #579431
Lesenswert?

Wie wäre es damit:

1
byte check_active_port_gpi(void)
2
{
3
 word input = 0;
4

5
 input = PINB;
6
 input |= (PING<<8);
7

8
 switch( input )
9
 {
10
  case 1:return 1;break;
11
  case 2:return 2;break;
12
  case 4:return 3;break;
13
  case 8:return 4;break;
14
  case 16:return 5;break;
15
  case 32:return 6;break;
16
  case 64:return 7;break;
17
  case 128:return 8;break;
18
  case 256:return 9;break;
19
  default: return 0;break;
20
 }
21

22
}
OP #579817
Lesenswert?

Finde ich eine sehr gelungene Darstellung.
Allerdings habe ich mal gehört, dass Operationen mit "goto()" und 
"break" alte Programmierweise ist und aufgrund des harten Eingriffs in 
den Ablauf des Programms nicht mehr eingesetzt werden. Die Funktion 
müsste aber doch auch ohne dem break funktionieren.

Die nun vorläufige Funktion habe ich nochmal ein bisschen abgeändert. 
Habe nun nur noch 7 Eingänge. Und der alte Wert, steht im EEPROM und 
wird gegebenenfalls aktualisiert. Müsste doch so funktioieren oder ?
1
unsigned char check_active_port_gpi(void)
2
{
3
 unsigned char input, eeprom_port;
4

5
 input = PINB;
6

7
 switch( input )
8
 {
9
  case 1: input=1;
10
  case 2: input=2;
11
  case 4: input=3;
12
  case 8: input=4;
13
  case 16: input=5;
14
  case 32: input=6;
15
  case 64: input=7;
16
  default: input=0;
17
 }
18
 
19
 eeprom_port = eeprom_read_byte(EEP_OFFSET_SWITCH_PORT);
20

21
 if(input != eeprom_port)
22
 {
23
  eeprom_write_byte(EEP_OFFSET_SWITCH_PORT, input);
24
  enable_port(input);
25
 }
26

27
 return input;
28
}

Vielen Dank
Moderator Persönliche Seite #579828
Lesenswert?

Matthias Nagel wrote:

> Allerdings habe ich mal gehört, dass Operationen mit "goto()" und
> "break" alte Programmierweise ist und aufgrund des harten Eingriffs
> in den Ablauf des Programms nicht mehr eingesetzt werden.

Kokolorus.

Donald E. Knuth hat in der Zeit, in der die sogenannte ,,strukturierte
Programmierung'' ihre politische Hochkonjunktur hatte, mal ein Buch
geschrieben, das heißt: ``Structured Programming with GOTO''.  Darin
hat er sehr detailliert beide Seiten der (eher politischen) Diskussion
beleuchtet und begründet, warum absolutistisch vertretene Meinungen
nicht automatisch zu einem gesunden Programmierstil führen.

> Die Funktion müsste aber doch auch ohne dem break funktionieren.

Nein, du hast die Funktion der switch-Anweisung von C noch nicht
verstanden.
OP #579833
Lesenswert?

> Donald E. Knuth hat in der Zeit, in der die sogenannte ,,strukturierte
> Programmierung'' ihre politische Hochkonjunktur hatte, mal ein Buch
> geschrieben, das heißt: ``Structured Programming with GOTO''.  Darin
> hat er sehr detailliert beide Seiten der (eher politischen) Diskussion
> beleuchtet und begründet, warum absolutistisch vertretene Meinungen
> nicht automatisch zu einem gesunden Programmierstil führen.

Interessant, so habe ich das noch nie gehört. Jetzt kenn ich wenigstens 
mal den Background dahinter.

>> Die Funktion müsste aber doch auch ohne dem break funktionieren.
>
> Nein, du hast die Funktion der switch-Anweisung von C noch nicht
> verstanden.

Richtig, habe ich verwechselt. SRY

Ich hätte eine Frage zu UART. Wäre wahrscheinlich besser einen neuen 
Beitrag aufzumachen oder ?
Gast #580125
Lesenswert?

Gruß an Meister "Matthias Nagel":


Wenn Du das brak bei einer Switch case Anweisung weglässt, dann erlebst 
du
dein blaues Wunder.

Die switch(value) Anweisung sollte vom Compiler in eine Sprungtabelle 
übersetzt werden. Dabei wird der Wert value so ausgewertet, dass daraus 
ein
Sprungoffset berechnet wird.

Beispiel:
1
// PC = Aktuelle Position in der Befehlsverarbeitung
2
// Wird entweder als "Instruction Pointer" (IP) od. auch als 
3
// "Program counter" (PC) bezeichnet.
4

5
Adresse   Pseudocode
6

7
00        Springe zu PC+x;// switch (value) - value ist hier 2; x = 0;
8
01        
9
02         Tue Prozedur 1;// wird bei value = 2 angesprungen
10
03         springe zu 07;
11
04         Tue Prozedur 2;// wird bei value = 4 angesprungen
12
05         springe zu 07;
13
06         ....
14
07         Tue was anderes;// ist das Ende der Switch case.

Ich garantiere hier nicht für Fehlerfreiheit, aber das Prinzip dürfte 
klar sein.

Eine stapel if-Anweisung erzeugt einen etwas komplexeren und dadurch 
langsameren code. Währen die switch-Anweisung schnelleren code 
produziert.
(Intelligente OPtimierungen eines Compilers mal vernachlässigt!)
Gast #580148
Lesenswert?

REM ** Wer lesen kann ist klar im Vorteil ***

Sorry, hab wohl den Thread zu schnell überflogen.
Ich hab noch einen Tip für "Matthias Nagel":

>Und der alte Wert, steht im EEPROM und
>wird gegebenenfalls aktualisiert. Müsste doch so funktioieren oder ?

Wie oft ändert sich der Wert? BEdenke dass das EEPROM nur eine begrenzte 
Anzahl an Schreibzyklen hat! Ausserdem ist die read_eeprom() Funktion 
relativ langsam. Ich empfehle eine Kombination aus Hardware- und 
Softwarelösung.

IN die Schaltung einen "dicken" Elko einbauen, der dem Controller noch 
für einige hundert Milisekunden Strom liefern kann.
Den alten Wert einmal in eine globale VAriable laden und dann bei jeder 
Änderung nur diese Aktualisieren. Wenn die Spannungsversorgung ausfllt 
sollte der Controller einen INterrupt bekommen, die globale Variable ins 
EEPROM sichern und dann solang in einer Schleife (bitte mit Zähler, 
falls wieder Strom kommt) warten, bis der Elko entladen ist!

Das spart Rechenzeit und eeprom-Zyklen ;)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren