I2C-Kommunikationsproblem zwischen TI 28016 und Sensor BMA020

Gast #2109716
Lesenswert?

Hallo.

Ich versuche seit einer Woche vergeblich die I2C-Kommunikation zwischen 
meinem TI 28016, welcher auf nem Olimex Development Board sitzt, und 
einem  BMA020 Beschleunigungssensor herzustellen. Laut Datenblatt zum 
Sensor sind dafür "nur" folgende Schritte notwendig:

- Befehl 0x02 an Adresse 0x70 (fixe Sensoradresse 0x38 plus RW=0) senden
- 6 Byte (Messergebnisse) von Adresse 0x71 (fixe Sensoradresse 0x38 plus 
RW=1) auslesen

Meine µC-Kenntnis sind eher rudimentär und  mit dem TI arbeite ich erst 
seit 3 Wochen. Deshalb habe ich versucht ein fertiges Snippet 
anzupassen, geschrieben von Brad Griffis 2008.
Das ist dabei rausgekommen:
1
//I2C test 
2

3
#include "DSP280x_Device.h"     // DSP280x Headerfile Include File
4
#include "DSP280x_Examples.h"   // DSP280x Examples Include File
5

6
// Prototype statements for functions found within this file.
7
void   I2CA_Init(void);
8
Uint16 I2C_Write(Uint16 slvaddr, int data, Uint16 length);
9
Uint16 I2C_Read(Uint16 slvaddr, Uint16* data, Uint16 length);
10

11
Uint16 Values[6];
12

13
void main(void)
14
{
15
   InitSysCtrl();  // Step 1. Initialize System Control:
16
   InitI2CGpio();  // Step 2. Initalize GPIO only for I2C functionality
17
   I2CA_Init();    // Step 4. Initialize all the Device Peripherals
18

19
   for(;;)    // Application loop
20
   {   
21
     I2C_Write(0x70,0x02,2);
22
     I2C_Read(0x71,Values,6);
23
   }   // end of for(;;)
24
}   // end of main
25

26

27
void I2CA_Init(void)
28
{
29
//   I2caRegs.I2CSAR = 0x38;    // Slave address - EEPROM control code
30
   I2caRegs.I2CPSC.all = 6;    // Prescaler - need 7-12 Mhz on module clk for 60MHz CPU
31
   I2caRegs.I2CCLKL = 4200;    // NOTE: must be non zero
32
   I2caRegs.I2CCLKH = 4200;    // NOTE: must be non zero
33
   I2caRegs.I2CIER.all = 0x3E;    // Enable SCD,XRDY,RRDY,ARDY,NACK interrupts
34
//   I2caRegs.I2CMDR.all = 0x0020;  // Take I2C out of reset, Stop I2C when suspended
35
//   I2caRegs.I2CFFTX.all = 0x6000;  // Enable FIFO mode and TXFIFO
36
//   I2caRegs.I2CFFRX.all = 0x2040;  // Enable RXFIFO, clear RXFFINT,
37
   return;
38
}
39

40
Uint16 I2C_Write(Uint16 slvaddr, int data, Uint16 length)
41
{
42
   Uint16 i;
43
   while (( I2caRegs.I2CSTR.bit.BB==1 ));  //bus busy?
44
   if (I2caRegs.I2CSTR.bit.BB == 1)
45
   {
46
      return I2C_BUS_BUSY_ERROR;
47
   }
48
  I2caRegs.I2CMDR.all = 0;  //disable I2C during config
49
  I2caRegs.I2CCNT = length;  //number of bytes to be send
50
  I2caRegs.I2CSAR = slvaddr;  //setup receiver addr
51
//  Mode settings
52
  I2caRegs.I2CMDR.bit.IRS=1;  //I2C module enable              
53
  I2caRegs.I2CMDR.bit.STT=1;  //If master -> start condition generated
54
  I2caRegs.I2CMDR.bit.STP=1;  //If master -> stop condition generated if data counter=0
55
  I2caRegs.I2CMDR.bit.TRX=1;  //Transmitter mode
56
  I2caRegs.I2CMDR.bit.MST=1;  //Master mode
57
  I2caRegs.I2CMDR.bit.FREE=1;  //I2C module runs free
58
  I2caRegs.I2CMDR.bit.RM=1;  
59
  
60
  /* Transmission*/
61
  for(i=0;i<length;i++)
62
  {
63
    while(!(I2caRegs.I2CSTR.bit.XRDY|I2caRegs.I2CSTR.bit.ARDY));  //wait for xdry flag before transmit data or ardy if NACK appears
64
    if (I2caRegs.I2CSTR.bit.NACK==1)        //if NACK appears -> SCL=low, STP=0
65
    {
66
      I2caRegs.I2CMDR.all=0;          //reset I2C -> SCL not held low
67
    }
68
    I2caRegs.I2CDXR = data;
69
  }
70
}
71

72
Uint16 I2C_Read(Uint16 slvaddr, Uint16* data, Uint16 length)
73
{
74
  Uint16 i;
75
  while (( I2caRegs.I2CSTR.bit.BB==1 ));    //bus busy?
76
   if (I2caRegs.I2CSTR.bit.BB == 1)
77
   {
78
      return I2C_BUS_BUSY_ERROR;
79
   }
80
  I2caRegs.I2CMDR.all = 0;      //disable I2C during config
81
  I2caRegs.I2CCNT = length;      //number of bytes to be send
82
  I2caRegs.I2CSAR = slvaddr;      //setup receiver addr
83
//  Mode settings
84
  I2caRegs.I2CMDR.bit.IRS=1;      //I2C module enable              
85
  I2caRegs.I2CMDR.bit.STT=1;      //If master -> start condition generated
86
  I2caRegs.I2CMDR.bit.STP=1;      //If master -> stop condition generated if data counter = 0
87
  I2caRegs.I2CMDR.bit.MST=1;      //Master mode
88
  I2caRegs.I2CMDR.bit.FREE=1;       //I2C module runs free
89
  I2caRegs.I2CMDR.bit.NACKMOD=1;
90

91
  /* Reception */
92
  for(i=0;i<length;i++)
93
  {
94
    while(!(I2caRegs.I2CSTR.bit.XRDY|I2caRegs.I2CSTR.bit.ARDY));  //wait for xdry flag before transmit data or ardy if NACK appears
95
    if (I2caRegs.I2CSTR.bit.NACK==1)        //if NACK appears -> SCL=low, STP=0
96
    {
97
      I2caRegs.I2CMDR.all=0;          //reset I2C -> SCL not held low
98
    }
99
    while(I2caRegs.I2CSTR.bit.RRDY==1);
100
    data[i] = I2caRegs.I2CDRR ;
101
  }
102
}
103

104
//EOF

Das Ergebnis hab ich mir mit nem Oszi angeschaut: Nach dem ersten Senden 
wird SDI auf low gezogen und SCK bleibt high. Wenn ich die
1
while (( I2caRegs.I2CSTR.bit.BB==1 ));
in der Schreib- bzw. Lesefunktion auskommentiere kann ich folgendes Bild 
sehen:

http://img24.imageshack.us/img24/7899/bild0027h.jpg

Meiner laienhaften Meinung nach wird keine Stop Condition erzeugt, 
weshalb BB immer 1 ist. Obwohl ich dachte dass ich das mit setzen von 
STP eingestellt hab.

Ein Versuch eine I2C-Minimalversion für diese Sache zu schreiben sah so 
aus:
1
//I2C test 
2

3

4
#include "DSP280x_Device.h"     // DSP280x Headerfile Include File
5
#include "DSP280x_Examples.h"   // DSP280x Examples Include File
6

7
// Prototype statements for functions found within this file.
8
void   I2CA_Init(void);
9

10
Uint16 Values[6],i;
11

12

13
void main(void)
14
{
15
   InitSysCtrl();      // Step 1. Initialize System Control:
16
   InitI2CGpio();      // Step 2. Initalize GPIO only for I2C functionality
17
   I2CA_Init();        // Step 4. Initialize all the Device Peripherals:
18

19

20
   for(;;)          // Application loop
21
   {
22
             //---> Write instruction <--- //
23
      I2caRegs.I2CMDR.bit.STT = 1;
24
      I2caRegs.I2CSAR = 0x70;        //Write addr
25
      I2caRegs.I2CCNT = 3;        //3bytes=2bytes addr + 1 byte instr
26
      I2caRegs.I2CDXR = 0x02;        //instr
27
      I2caRegs.I2CMDR.bit.STP = 1; 
28
//      I2caRegs.I2CMDR.all = 0x2620;    //Send data to setup EEPROM address
29

30
      
31
      //---> Read values <--- //
32
      I2caRegs.I2CMDR.bit.STT = 1;
33
      I2caRegs.I2CSAR = 0x71;        //Read addr
34
      I2caRegs.I2CCNT = 1;        //6bytes=2bytes per coordinate
35
      Values[0] = I2caRegs.I2CDRR;
36
      /*for(i=0;i<6;i++)
37
      {
38
        Values[i] = I2caRegs.I2CDRR;
39
      }*/
40
      I2caRegs.I2CMDR.all = 0x2C20;      //Send restart as master receiver
41
       I2caRegs.I2CMDR.bit.STP = 1;          
42
   }   // end of for(;;)
43
}   // end of main
44

45

46
void I2CA_Init(void)
47
{
48
//   I2caRegs.I2CSAR = 0x38;      // Slave address - EEPROM control code
49
   I2caRegs.I2CPSC.all = 6;      // Prescaler - need 7-12 Mhz on module clk for 60MHz CPU
50
   I2caRegs.I2CCLKL = 4200;      // NOTE: must be non zero
51
   I2caRegs.I2CCLKH = 4200;      // NOTE: must be non zero
52
   I2caRegs.I2CIER.all = 0x24;    // Enable SCD & ARDY interrupts
53
   I2caRegs.I2CMDR.all = 0x0020;  // Take I2C out of reset, Stop I2C when suspended
54
   I2caRegs.I2CFFTX.all = 0x6000;  // Enable FIFO mode and TXFIFO
55
   I2caRegs.I2CFFRX.all = 0x2040;  // Enable RXFIFO, clear RXFFINT,
56
   return;
57
}
58

59
//EOF
Führte aber leider auch nicht zum Ergebnis.

Falls jemand hier Erfahrungen mit TI DSPs/I2C oder Vorschläge jeglicher 
Art zu meinen beiden Code-Versuchen hat wäre ich sehr dankbar.

Grüße
Stephan
Gast #2115783
Lesenswert?

habs jetzt hinbekommen und falls mal jemand den BMA020 mit TI C2000 DSPs 
nutzen will poste ich mal meinen, durchaus verbesserungswürdigen, Code, 
welcher im Roboternetz gepostete Codeschnipsel enthält.
1
//I2C test 
2

3
#include "DSP280x_Device.h"     // DSP280x Headerfile Include File
4
#include "DSP280x_Examples.h"   // DSP280x Examples Include File
5

6
// Prototype statements for functions found within this file.
7
void   I2CA_Init(void);
8

9
int Values[6]={0,0,0,0,0,0};
10
Uint16 instr=0x02;
11
int i,dx=0,dy=0,dz=0;
12
double D2G,gx=0,gy=0,gz=0;
13

14
void main(void)
15
{
16
   InitSysCtrl();      // Step 1. Initialize System Control:
17
   InitI2CGpio();      // Step 2. Initalize GPIO only for I2C functionality
18
   I2CA_Init();        // Step 4. Initialize all the Device Peripherals
19
   
20
   D2G=0.00390625;      // 4g/1024
21
   
22
   for(;;)          // Application loop
23
     {  
24
       I2caRegs.I2CSAR = 0x38;             //Set slave address
25
       I2caRegs.I2CCNT = 1;             //Set count to 5 characters plus 2 address bytes
26
       I2caRegs.I2CDXR = 0x02;            //Send eeprom high address            
27
       I2caRegs.I2CMDR.bit.TRX = 1;         //Set to Transmit mode
28
       I2caRegs.I2CMDR.bit.MST = 1;         //Set to Master mode
29
       I2caRegs.I2CMDR.bit.FREE = 1;        //Run in FREE mode
30
       I2caRegs.I2CMDR.bit.STP = 1;         //Stop when internal counter becomes 0
31
       I2caRegs.I2CMDR.bit.STT = 1;         //Send the start bit, transmission will follow
32
        
33
    
34
       while(I2caRegs.I2CSTR.bit.XRDY == 0){};     //Do nothing till data is shifted out
35
       I2caRegs.I2CCNT = 6;              //read 6 bytes from eeprom
36
       I2caRegs.I2CMDR.bit.TRX = 0;         //Set to Recieve mode
37
       I2caRegs.I2CMDR.bit.MST = 1;         //Set to Master mode
38
       I2caRegs.I2CMDR.bit.FREE = 1;        //Run in FREE mode
39
       I2caRegs.I2CMDR.bit.STP = 1;         //Stop when internal counter becomes 0
40
       I2caRegs.I2CMDR.bit.STT = 1;         //Repeated start, Reception will follow
41
       for(i = 0; i < 6; i++)
42
         {
43
           while(I2caRegs.I2CSTR.bit.RRDY == 0){};   //I2CDRR not ready to read?
44
           Values[i] = I2caRegs.I2CDRR;
45
         }
46
       DELAY_US(100);                //wait for new data provided
47
       dx=Values[0];                //dataadaptation by malthy & Sternthaler
48
       dx=(dx|((Values[1]<<8))>>6);
49
       gx=dx*D2G;
50
       dy=Values[2];
51
       dy=(dx|((Values[3]<<8))>>6);
52
       gy=dy*D2G;
53
    dz=Values[4];
54
       dz=(dx|((Values[5]<<8))>>6);
55
       gz=dz*D2G;
56
                         
57
   }   // end of for(;;)
58
}   // end of main
59

60

61
void I2CA_Init(void)
62
{
63
   I2caRegs.I2CSAR = 0x38;      // Slave address - EEPROM control code
64
   I2caRegs.I2CPSC.all = 6;      // Prescaler - need 7-12 Mhz on module clk for 60MHz CPU
65
   I2caRegs.I2CCLKL = 42;      // NOTE: must be non zero
66
   I2caRegs.I2CCLKH = 21;      // NOTE: must be non zero
67
   I2caRegs.I2CIER.all = 0x3E;    // Enable SCD,XRDY,RRDY,ARDY,NACK interrupts
68
   I2caRegs.I2CMDR.bit.IRS = 1;    // Take I2C out of reset, Stop I2C when suspended
69
   I2caRegs.I2CFFTX.all = 0x0000;  // Enable FIFO mode and TXFIFO
70
   I2caRegs.I2CFFRX.all = 0x0000;  // Enable RXFIFO, clear RXFFINT,
71
   return;
72
}
73

74
//EOF

An der Stelle nochmals danke an die "Code-Sponsoren".

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