bit_is_set Abfrage in Software i2c auf Atmega8

Gast #916099
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:
1
#define SCL_PORT PORTC
2
#define SCL_DDR  DDRC
3
#define SCL_PINREG PINC
4
#define SCL_PIN PC5
5
#define SDA_PORT PORTC
6
#define SDA_DDR DDRC
7
#define SDA_PINREG PINC
8
#define SDA_PIN PC4
9

10
unsigned char i2c_readNak(void)
11
{
12
    unsigned char data;
13
    unsigned char i = 1;
14
    // sicherstellen dass alle zustände auf richtigem ausgangspunkt sind
15
    SDA_DDR &= ~(1<<SDA_PIN);  // SDA: Datenrichtung: in
16
    SDA_PORT &= ~(1<<SDA_PIN);   // SDA: low
17
    SCL_DDR |= (1<<SCL_PIN);  // SCL: Datenrichtung: out
18
    SCL_PORT &= ~(1<<SCL_PIN);  // SCL: low
19
    // empfangen einleiten 
20
    data = 0;
21
    i = 1;
22
    while( i <= 8)    
23
    {
24
       i2c_wait_quaterpuls();
25
       SCL_DDR &= ~(1<<SCL_PIN);  // SCL: Datenrichtung: in (clockstreching)
26
       SCL_PORT |= (1<<SCL_PIN);   // SCL: high
27
       while( bit_is_clear(SCL_PINREG,SCL_PIN) )
28
       {
29
         asm volatile ("nop");
30
       }
31
       SCL_DDR |= (1<<SCL_PIN);  // SCL: Datenrichtung: out
32
       i2c_wait_quaterpuls();
33
       if( bit_is_set(SDA_PINREG,SDA_PIN) )
34
       {
35
          data = ( (data<<1) | 0x01);    // neue information einschreiben
36
       }
37
       else
38
       {
39
          data = ( (data<<1) | 0x00);
40
       }
41
       i2c_wait_quaterpuls();
42
       SCL_PORT &= ~(1<<SCL_PIN);  // SCL: low
43
       i2c_wait_quaterpuls();    // lowpuls abwarten  
44
       i = i + 1;
45
    }
46
    SDA_DDR |= (1<<SDA_PIN);  // SDA: Datenrichtung: out
47
    SDA_PORT |= (1<<SDA_PIN);   // SDA: high = NO ACK
48
    i2c_wait_quaterpuls();    // lowpuls fertig warten
49
    SCL_DDR &= ~(1<<SCL_PIN);  // SCL: Datenrichtung: in (clockstreching)
50
    SCL_PORT |= (1<<SCL_PIN);   // SCL: high
51
    while( bit_is_clear(SCL_PINREG,SCL_PIN) )
52
    {
53
      asm volatile ("nop");
54
    }
55
    SCL_DDR |= (1<<SCL_PIN);  // SCL: Datenrichtung: out
56
    i2c_wait_quaterpuls();    // highpuls abwarten
57
    i2c_wait_quaterpuls();
58
    SCL_PORT &= ~(1<<SCL_PIN);  // zurück auf "warten auf Aufgabe"
59

60
    return data;        // Daten ausgeben    
61
}/* 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
(Firma: MicroForge) #1057817
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!
1
SIGNAL(PCINT2_vect){
2
  if(bit_is_set(PINK, PORTK0)){
3
    doSomeFineStuff();
4
  }
5
  if(PINK & (1 << PORTK1)){
6
    doSomeThingElse();
7
  }
8
  if(PINK & _BV(PORTK2)){
9
    doSomeNastyCrap();
10
  }
11
}

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
Gast #1059332
Lesenswert?

Das beste ist eigentlich, dass wenn ich
1
  
2
if(PINK & (1 << PORTK1)){
3
   doSomeThingElse();
4
}

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

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

welche wiederum
1
#include <avr/iom2560.h>

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

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

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

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

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

Gruß
Timo
(Firma: MicroForge) #1059412
Lesenswert?

Datenrichtung steht auf
1
DDRK = 0x00;
2
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:
1
SIGNAL(PCINT2_vect){
2
  if(~bit_is_set(PINK, PORTK0)){
3
    doSomeFineStuff();
4
  }
5
  if(~(PINK & (1 << PORTK1))){
6
    doSomeThingElse();
7
  }
8
  if(~(PINK & _BV(PORTK2))){
9
    doSomeNastyCrap();
10
  }
11
}

Oder klappt das nicht?

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