mikrocontroller.net

Forum: Compiler & IDEs Variable ändert sich nur bei 8. Bit


Autor: spencer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forengemeinde!

Ich möchte PINA auf Änderung beobachten (per TimerInterrupt) und dann 
eine Flankenauswertung der geänderten Pins machen. Controller ist ein 
Mega32, Eingangsbeschaltung low-aktiv mit internen Pullups. Leider wird 
das Änderungschar (e1c) nur auf 0xFF gesetzt, wenn PINA.0 sich ändert. 
Sitze nun schon seit mehreren Stunden an diesem Problem und komme 
einfach nicht weiter. Weiter unten hab ich das UART-Debug gepostet.


MfG

spencer

char tempPINA = PINA;

e1c = 0x00;

int i;

for (i=0;i<8;i++) {  // Zustand der Eingänge 1 bis 8 vergleichen und an Array e1 weitergeben

      if (!(tempPINA == pina_last)){ // Mindestens ein Pin auf E1 hat sich verändert, prüfen!!!
      if (!(tempPINA&(1<<i)) == (pina_last&(1<<i))) // Alle Bits durchgehen und vergleichen

{ 

    e1c =0xFF;  // Änderungsindex setzen

  if (!(tempPINA&(1<<i))){
      e1hi[i] = 1;
          e1lo[i] = 0;
}

else{     e1hi[i] = 0;
          e1lo[i] = 1;
}

}}



e1hi = Eingang 1 (PINA) wurde bei n-Bit high (GND)
e1lo = Eingang 1 (PINA) wurde bei n-Bit low (VCC)
e1c = Eingang 1 (PINA) hat sich verändert

Zustand pina_last: 00000000
Zustand tempPINA:  00010000
Zustand e1hi:      00000000
Zustand e1lo:      00000000
Zustand e1c:       00000000

Zustand pina_last: 00000000
Zustand tempPINA:  10000000
Zustand e1hi:      10000000
Zustand e1lo:      00000000
Zustand e1c:       11111111

Autor: spencer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm.. ich muss zugeben, das ist kein aussagekräftiger betreff, sorry, zu 
spät gemerkt.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi spencer,

auf den ersten Blick sehe ich mehrere Probleme mit Deinem Code:

1. Du verrätst uns nicht die Deklaration von pina_last.
2. tempPINA & pina_last sollten vom Typ uint8_t sein -- sonst kann es 
alle möglichen Probleme geben!
3. tempPINA wird bei Deinem jetzigen Code nur einmal (als 
Initialisierung) von PINA gelesen.
4. Irgendwo müsste doch auch
pina_last=tempPINA;
 o.ä. stehen!
5.
  if (!(tempPINA&(1<<i))){
      e1hi[i] = 1;
          e1lo[i] = 0;
}

else{     e1hi[i] = 0;
          e1lo[i] = 1;
}
 könnte man stark vereinfachen!
Gruß

Fred

Autor: spencer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm der Code ließ mir keine Ruhe, also strengte ich nochmal die 
Forensuche an. Daraus wandelte ich mir folgenden Code ab, der wunderbar 
funzt :)
schnipp

char tempPINA = PINA;
char tempPINC = PINC;

int i;

char h = 0;

if (tempPINA != pina_last) //wenn Änderung
 {
e1c = 0xFF;

 for (i = 0x01; i <= 0x80; i = i << 1)

   {
   if ((tempPINA & i) ^ (pina_last & i))  //wenn Unterschied
    {

    if(pina_last & i)    //wenn H-Input
     e1hi[h] = 1;    //dann H-Output
    else
     e1lo[h] = 1;    //L-Output
    }
h++;
   }
 }

schnapp

Trotzdessen vielen Dank an Fred! tempPINA und pina_last sind übrigens 
char.
Und hier wird der pina_last gelesen:
int reade1(void){    // E1 abgleichen
pina_last = PINA;
}

Wenigstens hab ich das mit dem shiften jetzt verstanden.

MfG

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spencer wrote:

> Trotzdessen vielen Dank an Fred! tempPINA und pina_last sind übrigens
> char.

Gewöhn dir an, bei Byte-Werten immer einen unsigned char zu
nehmen.

Bei char überlässt du es dem Compiler, ob ein char ein signed char
oder ein unsigned char ist. Um auf Byte-Ebene zu arbeiten, will
man aber meistens eine unsigned Behandlung haben. Dadurch, dass du
gezielt unsigned angibst, schliesst du eine mögliche Fehlerquelle
aus.

> Und hier wird der pina_last gelesen:
> int reade1(void){    // E1 abgleichen
> pina_last = PINA;
> }

Integrier dieses Setzen des pina_last in deine Auswerteroutine!
Zwischen dem Abfragen des PINA für die Auswertung und dem erneuten
Aufruf dieser Funktion vergeht Zeit! In dieser Zeit könnte dein
Eingang seinen Pegel verändern -> mit deiner Strategie kriegst
diesen Pegelwechsel dann nicht mehr mit. Du willst ja den jetzigen
Pegel des Eingangs mit dem Pegel vergleichen, mit dem du die letzte
Auswertung gemacht hast.
  unsigned char tempPINA = PINA;
  unsigned char tempPINC = PINC;

  unsigned char i;
  unsigned char h = 0;

  if (tempPINA != pina_last) //wenn Änderung
  {
    e1c = 0xFF;

    for (i = 0x01; i != 0x00; i = i << 1)
    {
      if ((tempPINA & i) ^ (pina_last & i))  //wenn Unterschied
      {
        if(pina_last & i)    //wenn H-Input
          e1hi[h] = 1;    //dann H-Output
        else
          e1lo[h] = 1;    //L-Output
      }
      h++;
    }
  }

  pina_last = tempPINA;

Die for-Schleife sieht etwas gewöhnungsbedürftig aus. Aber zusammen
mit dem Wissen, dass i ein unsigned char ist, solltest du rauskrigen
können, wie das läuft.

Autor: spencer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dankeschön, ich dachte es ist egal, ob ein char signed oder unsigned 
ist, wenn man sowieso nur hochzählt bzw. sich nur im positiven bereich 
bewegt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spencer wrote:
> Dankeschön, ich dachte es ist egal, ob ein char signed oder unsigned
> ist, wenn man sowieso nur hochzählt bzw. sich nur im positiven bereich
> bewegt.

Bei deiner Anwendung (=letztes Program) ist es tatsächlich egal.
Interessant wird es allerdings dann wenn irgendwann mal Konvertierungen
nach int bzw. umgekehrt ins Spiel kommen. Da wird dann flugs aus einer
255 im char ein -1 im int und dann ist das Suchen groß, was denn
da schief gelaufen sein könnte.

Ein simples

   char c = 255;

   if( c == 255 ) {
     ...
   }

kann dann schnell mal in unvorhergesehene Probleme ausarten.

Das einfachste ist es, einfach nach den Regeln zu spielen:
Du willst Bytes bearbeiten  -> unsigned char
Du willst "Strings" (also Zeichenketten) verarbeiten  -> char

Damit bist du praktisch immer auf der sicheren Seite.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich bin da noch mehr Purist und habe deshalb
uint8_t
 vorgeschlagen, obwohl man dann
inttypes.h
 einbinden muss.

Gruß

Fred

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.