mikrocontroller.net

Forum: Compiler & IDEs bit_is_set Abfrage in Software i2c auf Atmega8


Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi

ich bin grade mit dem Versuch beschäftigt, für einen Atmega8 mit 
Winavr/GCC eine Software i2c-routine zu schreiben. Dummerweise treibt 
mich dabei aber eine kleine if-Abfrage so langsam aber sicher in den 
Wahnsinn. Das Ding wehrt sich schon seit tagen:
#define SCL_PORT PORTC
#define SCL_DDR  DDRC
#define SCL_PINREG PINC
#define SCL_PIN PC5
#define SDA_PORT PORTC
#define SDA_DDR DDRC
#define SDA_PINREG PINC
#define SDA_PIN PC4

unsigned char i2c_readNak(void)
{
    unsigned char data;
    unsigned char i = 1;
    // sicherstellen dass alle zustände auf richtigem ausgangspunkt sind
    SDA_DDR &= ~(1<<SDA_PIN);  // SDA: Datenrichtung: in
    SDA_PORT &= ~(1<<SDA_PIN);   // SDA: low
    SCL_DDR |= (1<<SCL_PIN);  // SCL: Datenrichtung: out
    SCL_PORT &= ~(1<<SCL_PIN);  // SCL: low
    // empfangen einleiten 
    data = 0;
    i = 1;
    while( i <= 8)    
    {
       i2c_wait_quaterpuls();
       SCL_DDR &= ~(1<<SCL_PIN);  // SCL: Datenrichtung: in (clockstreching)
       SCL_PORT |= (1<<SCL_PIN);   // SCL: high
       while( bit_is_clear(SCL_PINREG,SCL_PIN) )
       {
         asm volatile ("nop");
       }
       SCL_DDR |= (1<<SCL_PIN);  // SCL: Datenrichtung: out
       i2c_wait_quaterpuls();
       if( bit_is_set(SDA_PINREG,SDA_PIN) )
       {
          data = ( (data<<1) | 0x01);    // neue information einschreiben
       }
       else
       {
          data = ( (data<<1) | 0x00);
       }
       i2c_wait_quaterpuls();
       SCL_PORT &= ~(1<<SCL_PIN);  // SCL: low
       i2c_wait_quaterpuls();    // lowpuls abwarten  
       i = i + 1;
    }
    SDA_DDR |= (1<<SDA_PIN);  // SDA: Datenrichtung: out
    SDA_PORT |= (1<<SDA_PIN);   // SDA: high = NO ACK
    i2c_wait_quaterpuls();    // lowpuls fertig warten
    SCL_DDR &= ~(1<<SCL_PIN);  // SCL: Datenrichtung: in (clockstreching)
    SCL_PORT |= (1<<SCL_PIN);   // SCL: high
    while( bit_is_clear(SCL_PINREG,SCL_PIN) )
    {
      asm volatile ("nop");
    }
    SCL_DDR |= (1<<SCL_PIN);  // SCL: Datenrichtung: out
    i2c_wait_quaterpuls();    // highpuls abwarten
    i2c_wait_quaterpuls();
    SCL_PORT &= ~(1<<SCL_PIN);  // zurück auf "warten auf Aufgabe"

    return data;        // Daten ausgeben    
}/* i2c_readNak */
die dabei spinnende Abfrage ist die Zeile: 
if(bit_is_set(SDA_PINREG,SDA_PIN) )
die spricht immer an, egal ob der Pin gesetzt ist oder nicht, was zur 
Folge hat, dass der Code immer 0xff als Ergebniss zurückgibt.

hat mir da irgendjemand eine idee, woran es liegen könnte?

gruß und Danke
Matthias

Autor: Timo Birnschein (Firma: MicroForge) (timob)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Total doof, ich habe momentan das gleiche Problem mit meinem Mega2560!

Egal wie ich mit einem if-Statement einen Port abfrage, es ist immer 
true!
SIGNAL(PCINT2_vect){
  if(bit_is_set(PINK, PORTK0)){
    doSomeFineStuff();
  }
  if(PINK & (1 << PORTK1)){
    doSomeThingElse();
  }
  if(PINK & _BV(PORTK2)){
    doSomeNastyCrap();
  }
}

Es werden immer alle funktionen ausgeführt, aber eigentlich will ich ja 
nur eine der drei ausführen...

Bug im Compiler, oder Bug im Kopf? Der IRQ feuert und dann frage ich ab, 
welche meiner Tasten diesen IRQ abgesetzt hat und vor allem mit welcher 
Flanke. Das geht ja mit den PCINT nicht anders. Aber aus einem mit nicht 
ersichtlichen Grund geht das nicht :(

Gruß
Timo

Autor: Timo Birnschein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das beste ist eigentlich, dass wenn ich
  
if(PINK & (1 << PORTK1)){
   doSomeThingElse();
}

durch
if((PINK & 0x02)){
   doSomeThingElse();
}

dann GEHTS!.... Aber warum? Nach folgendem stardard-Include
#include <avr/io.h>

welche wiederum
#include <avr/iom2560.h>

und von da aus
#include <avr/iomxx0_1.h>

steht:
# define PORTK  _SFR_MEM8(0x108)
# define PK7 7
# define PK6 6
# define PK5 5
# define PK4 4
# define PK3 3
# define PK2 2
# define PK1 1
# define PK0 0

Dann gehts wieder zurück zur io.h welche anschließend dann
#include <portpins.h>

includiert wird, worin steht:
#if defined(PK1)
#  define PORTK1 PK1
#endif

also frage ich gern nochmal: wo ist der Unterschied zwischen (1 << 
PORTK1) und 0x02? Oder anders:
if ((1 << PORTK1) != 0x02)
   burnAVR();

Gruß
Timo

Autor: A. F. (artur-f) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if(PINK & (1 << PK1))
sollte definitiv den Zustand der Leitung abfragen können. Datenrichtung 
richtig gesetzt? Pull-Ups aus?

Autor: Timo Birnschein (Firma: MicroForge) (timob)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datenrichtung steht auf
DDRK = 0x00;
PORTK = 0xFF; // Pull-ups an

Die Pullups sind an, da ich mit meinem Taster auf Lowpegel ziehe. Da 
aber auch die Abfrage auf High nicht klappt, habe ich hier das Beispiel 
mit dem HighPegel gemacht.

Im Code steht also eigentlich:
SIGNAL(PCINT2_vect){
  if(~bit_is_set(PINK, PORTK0)){
    doSomeFineStuff();
  }
  if(~(PINK & (1 << PORTK1))){
    doSomeThingElse();
  }
  if(~(PINK & _BV(PORTK2))){
    doSomeNastyCrap();
  }
}

Oder klappt das nicht?

Autor: Jean Player (fubu1000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,
probier doch mal if(!(PINK & (1 << PK0)) oder if(!(PINK & 0x01)) .

Gruß

Autor: Werner B. (werner-b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welche Version des Compiler?

Ich frage weil die "frühen" WinAVR mit GCC 4.3 alle möglichen Käfer 
haben.

Wenn AVR-GCC 4.3 auf Linux kann es das gleiche Problem sein.


(Noch) Aktuell ist WinAVR20080610 von 
http://sourceforge.net/projects/winavr/

P.S.
Es häufen sich in letzter Zeit wieder die "alter 4.3er WinAVR" Probleme.
Wer verteilt die?

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.