mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP I2C-Kommunikationsproblem zwischen TI 28016 und Sensor BMA020


Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
//I2C test 

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

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

Uint16 Values[6];

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

   for(;;)    // Application loop
   {   
     I2C_Write(0x70,0x02,2);
     I2C_Read(0x71,Values,6);
   }   // end of for(;;)
}   // end of main


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

Uint16 I2C_Write(Uint16 slvaddr, int data, Uint16 length)
{
   Uint16 i;
   while (( I2caRegs.I2CSTR.bit.BB==1 ));  //bus busy?
   if (I2caRegs.I2CSTR.bit.BB == 1)
   {
      return I2C_BUS_BUSY_ERROR;
   }
  I2caRegs.I2CMDR.all = 0;  //disable I2C during config
  I2caRegs.I2CCNT = length;  //number of bytes to be send
  I2caRegs.I2CSAR = slvaddr;  //setup receiver addr
//  Mode settings
  I2caRegs.I2CMDR.bit.IRS=1;  //I2C module enable              
  I2caRegs.I2CMDR.bit.STT=1;  //If master -> start condition generated
  I2caRegs.I2CMDR.bit.STP=1;  //If master -> stop condition generated if data counter=0
  I2caRegs.I2CMDR.bit.TRX=1;  //Transmitter mode
  I2caRegs.I2CMDR.bit.MST=1;  //Master mode
  I2caRegs.I2CMDR.bit.FREE=1;  //I2C module runs free
  I2caRegs.I2CMDR.bit.RM=1;  
  
  /* Transmission*/
  for(i=0;i<length;i++)
  {
    while(!(I2caRegs.I2CSTR.bit.XRDY|I2caRegs.I2CSTR.bit.ARDY));  //wait for xdry flag before transmit data or ardy if NACK appears
    if (I2caRegs.I2CSTR.bit.NACK==1)        //if NACK appears -> SCL=low, STP=0
    {
      I2caRegs.I2CMDR.all=0;          //reset I2C -> SCL not held low
    }
    I2caRegs.I2CDXR = data;
  }
}

Uint16 I2C_Read(Uint16 slvaddr, Uint16* data, Uint16 length)
{
  Uint16 i;
  while (( I2caRegs.I2CSTR.bit.BB==1 ));    //bus busy?
   if (I2caRegs.I2CSTR.bit.BB == 1)
   {
      return I2C_BUS_BUSY_ERROR;
   }
  I2caRegs.I2CMDR.all = 0;      //disable I2C during config
  I2caRegs.I2CCNT = length;      //number of bytes to be send
  I2caRegs.I2CSAR = slvaddr;      //setup receiver addr
//  Mode settings
  I2caRegs.I2CMDR.bit.IRS=1;      //I2C module enable              
  I2caRegs.I2CMDR.bit.STT=1;      //If master -> start condition generated
  I2caRegs.I2CMDR.bit.STP=1;      //If master -> stop condition generated if data counter = 0
  I2caRegs.I2CMDR.bit.MST=1;      //Master mode
  I2caRegs.I2CMDR.bit.FREE=1;       //I2C module runs free
  I2caRegs.I2CMDR.bit.NACKMOD=1;

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

//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
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:
//I2C test 


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

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

Uint16 Values[6],i;


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


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

      
      //---> Read values <--- //
      I2caRegs.I2CMDR.bit.STT = 1;
      I2caRegs.I2CSAR = 0x71;        //Read addr
      I2caRegs.I2CCNT = 1;        //6bytes=2bytes per coordinate
      Values[0] = I2caRegs.I2CDRR;
      /*for(i=0;i<6;i++)
      {
        Values[i] = I2caRegs.I2CDRR;
      }*/
      I2caRegs.I2CMDR.all = 0x2C20;      //Send restart as master receiver
       I2caRegs.I2CMDR.bit.STP = 1;          
   }   // end of for(;;)
}   // end of main


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

//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

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
//I2C test 

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

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

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

void main(void)
{
   InitSysCtrl();      // Step 1. Initialize System Control:
   InitI2CGpio();      // Step 2. Initalize GPIO only for I2C functionality
   I2CA_Init();        // Step 4. Initialize all the Device Peripherals
   
   D2G=0.00390625;      // 4g/1024
   
   for(;;)          // Application loop
     {  
       I2caRegs.I2CSAR = 0x38;             //Set slave address
       I2caRegs.I2CCNT = 1;             //Set count to 5 characters plus 2 address bytes
       I2caRegs.I2CDXR = 0x02;            //Send eeprom high address            
       I2caRegs.I2CMDR.bit.TRX = 1;         //Set to Transmit mode
       I2caRegs.I2CMDR.bit.MST = 1;         //Set to Master mode
       I2caRegs.I2CMDR.bit.FREE = 1;        //Run in FREE mode
       I2caRegs.I2CMDR.bit.STP = 1;         //Stop when internal counter becomes 0
       I2caRegs.I2CMDR.bit.STT = 1;         //Send the start bit, transmission will follow
        
    
       while(I2caRegs.I2CSTR.bit.XRDY == 0){};     //Do nothing till data is shifted out
       I2caRegs.I2CCNT = 6;              //read 6 bytes from eeprom
       I2caRegs.I2CMDR.bit.TRX = 0;         //Set to Recieve mode
       I2caRegs.I2CMDR.bit.MST = 1;         //Set to Master mode
       I2caRegs.I2CMDR.bit.FREE = 1;        //Run in FREE mode
       I2caRegs.I2CMDR.bit.STP = 1;         //Stop when internal counter becomes 0
       I2caRegs.I2CMDR.bit.STT = 1;         //Repeated start, Reception will follow
       for(i = 0; i < 6; i++)
         {
           while(I2caRegs.I2CSTR.bit.RRDY == 0){};   //I2CDRR not ready to read?
           Values[i] = I2caRegs.I2CDRR;
         }
       DELAY_US(100);                //wait for new data provided
       dx=Values[0];                //dataadaptation by malthy & Sternthaler
       dx=(dx|((Values[1]<<8))>>6);
       gx=dx*D2G;
       dy=Values[2];
       dy=(dx|((Values[3]<<8))>>6);
       gy=dy*D2G;
    dz=Values[4];
       dz=(dx|((Values[5]<<8))>>6);
       gz=dz*D2G;
                         
   }   // end of for(;;)
}   // end of main


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

//EOF

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

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.