I2C Startcondition und dann nix mehr

#1372284
Lesenswert?

Hallo,
ich bin bald am verzweifeln.
Ich versuche einen I2C BUs zum laufen zu bringen, aber das einzige was 
funktionniert ist, dass die Startcondition gesendet wird.
Ich verwende den LPC2148 auf dem MBC2140 EvaluatuonBorad von Keil und 
debugge das Ganze mit Hitop5.

Pull-Ups habe ich bereits zwischen 1k und 10k variert.
Hier mein Source Code:
1
#include "LPC214x.h"                        /* LPC21xx definitions */
2
#include "type.h"
3
#include "I2C.h"
4
#include "irq.h"
5

6
char buf[]={'A','B','C','D','E'};
7
int count = 5, i = 0;
8

9
int temp = 0;
10
void i2c_init(void)
11
{
12
  PINSEL0 = 0;
13
  PINSEL1 = 0;
14
  PCONP |= (1 << I2C_POWER);
15

16
  PINSEL0 |=(1 << SCL0_PINSEL) | (1 << SDA0_PINSEL); //SDA und SCL Pins auf I2C-MOdus
17

18
  I20CONCLR |= (1 << STO) | (1 << AA) | (1 << STA) | (1 << SI);
19
  temp =   I20CONCLR;
20

21
  I20CONSET |= (1 << I2EN) ;//| (1 << STA);  //enable the I2C function.
22
  //temp = I20CONSET;
23

24
  I20SCLH = 100;
25
  temp = I20SCLH;
26
  I20SCLL = 50;
27
  temp = I20SCLL;
28

29
  VICIntSelect = 0;
30
  temp = VICIntSelect;
31
        //VICIntEnable = (1 << IE_I2C);
32
  temp = VICIntEnable;
33
  
34
  VICVectCntl0 = (DWORD)(IRQ_SLOT_EN | IE_I2C);
35
  temp = VICVectCntl0;
36
  VICVectAddr0 = (DWORD) I2C_ISR;
37
  temp = VICVectAddr0;  
38

39
  IOSET0 = 0x00000000;                // clear the ZEROs output
40
    IODIR0 = 0x00000000;               // set the output bit direction
41
}
42

43
int i2c_write()
44
{
45
  while (count--)
46
  {
47
    I20DAT = buf[i++];            //  load data into I2DAT-Register
48
    wait_for_SI();
49
    if (I20STAT != 0x28) return 0;    //  no acknowledge
50
  }
51
  return 1;
52
}
53

54
void warte(unsigned int dauer)
55
{
56
  while(dauer--);
57
}
58

59

60
void i2c_start(int addr)
61
{    
62
  VICIntEnable = (1 << IE_I2C);  
63
  I20CONSET |= (1 << STA) ;      //  set STA  
64
}
65

66

67
void wait_for_SI(void)
68
{
69
  long timeout = 400000;
70
            //  clear SI starts action
71
  while (timeout-- && !(I20CONSET & SI));    //  check SI with timeout
72
}
73

74

75
void i2c_stop(void)
76
{
77
  I20CONSET |= (1 << STO);    //  set STO
78
  I20CONCLR |=(1 << SI);      //  clear SI
79
}
80

81
void CCLK_set(void)
82
{ 
83
  PLLCFG |= (4 << MSEL); 
84
  PLLCFG |= (1 << PSEL);  //Fosc*5 =CCLK
85
  PLLFEED = 0xAA;
86
  PLLFEED = 0x55;
87

88
  PLLCON |= (1 << PLLE) | (1 << PLLC); //PLL Enable.//PLL Connect.
89
  PLLFEED = 0xAA;
90
  PLLFEED = 0x55;
91
  
92

93
  VPBDIV = 0;//00 VPB bus clock is one fourth of the processor clock.  
94
}
95

96
void I2C_ISR(void) //__irq
97
{  int temp1 = 0;
98
  temp1 = I20STAT;
99

100
  switch(temp1)
101
  {
102
    case 0x08:
103
    {  
104
      //I20DAT = 0x90; //addr
105
      temp1 = I20DAT;
106
      I20CONCLR |= (1 << SIC) | (1 << STA);
107
      break;
108
    }
109
    case 0x10:
110
    {
111
      I20DAT = 0x90;
112
      I20CONCLR |= (1 << SIC);
113
      break;
114
    }
115
    case 0x18:
116
    {
117
      if(count==0)
118
        i2c_stop();
119
      else
120
        count--;
121
      I20DAT = *(buf);
122
      I20CONCLR |= (1 << SIC);
123
      break;
124
    }
125
    case 0x20:
126
    {
127
      i2c_stop();
128
      I20CONCLR |= (1 << SIC);
129
      break;  
130
    }
131
    case 0x28:
132
    {
133
      if(count==0)
134
        i2c_stop();
135
      else
136
        count--;
137
      I20DAT = *buf;
138
      I20CONCLR |= (1 << SIC);
139
      break;
140
    }
141
    case 0x30:
142
    {
143
      i2c_stop();  
144
      I20CONCLR |= (1 << SIC);
145
      break;  
146
    }
147
  }
148

149
  VICVectAddr = 0;
150
    
151
}

Wie gesagt, Startcondition wird gesendet( erst SDA auf LOW gezogen und 
dann SCL), im I2CStatusregister ist der Wert 0x08, dann bleibt beides 
auf LOW, bis in der ISR das SI-Flag gelöscht wird.

Was komisch ist, ich hatte einmal den Jumper7(für die, die des 
MCB2140Schematics zufällig vor sich haben) noch an, als ich den I2C1 
verwendete, und dann bekamm ich ein CLocksignal auf SCL, das nicht mehr 
aufhörte, aber das SI-Flag wurde nicht merh gesetzt. Über den Jumper 7 
wird SDA über einen Kondensator mit 100nF auf Ground gezogen und über 
einen 22k Wiederstand auf HIGH. Als ich den Jumper entfernte war es 
genauso, wie als ich den I2c0 verwendet habe.

Wie bekomme ich es jetzt hin, dass nicht nur die Startcondition sondern 
auch die Slaveaddresse gesendet wird? Und dann vielleicht auch mal Daten 
gesendet werden können?
#1372311
Lesenswert?

Pull-Ups habe ich bereits zwischen 1k und 10k variert.
Da aber 3mA fließen müssen,  werde ich eher die kleineren Widerstände 
verweden, wenn die Pullups nicht dran wären, könnte der IC ja nichts auf 
LOW ziehen.
Ich hatte schon den Verdacht dass ich vielleicht Bus-Arbitration 
verliere, aber gegen wen?
Ich hatte berits einen IC(den DS1624) angeschlossen ,habe jetzt aber, um 
Fehler beim DS1624 aus zu schließen, nur SDA und SCL über einen Pullup 
an High(3,3V) abgeschlossen.
Das komische ist ja, dass er die Startconidition macht und in der ISR 
die Slaveaddresse in I2DAT lädt, aber dann nichts passiert, nicht mal 
ein Clock genertiert wird. Ich schau das ganz natürlich mit dem Oszi an.
#1372446
Lesenswert?

Hallo,
ja ich habe den Teil mit der Main-Schleife in einer anderen Datei 
gehabt.
Ja die Application Notes kenne ich, habe mich so weit auch daran 
gehalten.
A.K. könnsest du deinen Code vom 2106 und 2129 eventuell mal hier rein 
stellen, würde mich mal interessieren.
Danke schon mal. Gruß Markus
1
int main (void)
2
{
3

4
  i2c_init();
5
  i2c_start(0x90);
6
  
7
  while(1)
8
  {
9
    i2c_write();    
10
  }
11
  return 0;
12

13
}
#1372703
Lesenswert?

Ok, Vielen Dank für den Code. Mir ist aber aufgefallen, dass ich den PLL 
garnicht verwende, da ich CCLK_set() garnicht aufrufe. Dann sollte der 
PLL ja defaultmäßig abgschaltet sein und CCLK = Fosc.
Habe jetzt I20SCLH auf 20 und I20SCLL auf 10 gesetzt, dann sollte mit 
einer Quarzfrequenz von 12MHZ die Bitrate 100kB betragen.
Was mir noch auffällt. Wenn ich an SCL messe erhalte ich 800ns bevor 
dieser abfällt einen kleinen Spannungseinbruch von 650mV. Könnte dass 
der Zeitpunkt sein, an dem SDA auf LOW geht?

Leider ändert sich bisher nichts daran, dass SDA und SCL auf LOW gehen 
und dann nichts mehr passiert, bis ich das SI Flag in der ISR lösche und 
dann beide wieder auf HIGH gehen.

Wäre für jeden Rat dankbar.
Gruß Markus
#1373780
Lesenswert?

Ich habe jetzt mal alle für diese Problem irrelavnten Codeteile raus 
gestrichen.

Die Slaveaddresse ist erstmal irrelavant, da ich keinen Slave angehängt 
habe, sindern SDA und SCl über Pullups auf HIGH gezogen habe.

Ich hoffe jemand kann mit diesem Problem was Anfangen.
Gruß Markus
1
#include "LPC214x.h"                        /* LPC21xx definitions */
2
#include "type.h"
3
#include "I2C.h"
4

5
int main (void)
6
{
7
  i2c_init();
8
  i2c_start(0x90);
9
      
10
  return 0;
11

12
}
13

14
void i2c_init(void)
15
{
16
  PINSEL0 = 0;
17
  PINSEL1 = 0;
18
  PCONP |= (1 << I2C_POWER);
19

20
  PINSEL0 |=(1 << SCL0_PINSEL) | (1 << SDA0_PINSEL); //SDA und SCL Pins auf I2C-MOdus
21

22
  I20CONCLR |= (1 << STO) | (1 << AA) | (1 << STA) | (1 << SI);
23
  I20CONSET |= (1 << I2EN) ;//| (1 << STA);  //enable the I2C function.
24

25
  I20SCLH = 100;
26
  I20SCLL = 50;
27

28
  VICIntSelect = 0;
29
  //VICIntEnable = (1 << IE_I2C);
30
   
31
  VICVectCntl0 = (DWORD)(IRQ_SLOT_EN | IE_I2C);
32
  VICVectAddr0 = (DWORD) I2C_ISR;
33
 
34
}
35

36
void i2c_start(int addr)
37
{    
38
  VICIntEnable = (1 << IE_I2C);  
39
  I20CONSET |= (1 << STA) ;      //  set STA  
40
}
41

42
void I2C_ISR(void) 
43
{  int temp1 = 0;
44
  temp1 = I20STAT;
45

46
  switch(temp1)
47
  {
48
    case 0x08:
49
    {  
50
      I20DAT = 0x90; //addr
51
      I20CONCLR |= (1 << SIC) | (1 << STA);
52
      break;
53
    }
54
  }
55

56
  VICVectAddr = 0;
57
    
58
}

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