This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SCI Communication TMS320F28035 Problem with captured data via I2C

Other Parts Discussed in Thread: TMS320F28035

Hi,

I want to implement a code to send data, recieved from 5 sensors, to PC via USB. I used an example program sci_loopback, took a couple of lines from it and put it in the program which captures data from the sensors via I2C.

Before I added the lines using SCI, everything was going well... Every sensor responded as it should have. 

But when I added a function responsible for sending data via UART from 2 sensors, the other sensors started giving weird and wrong data.

The funny thing is that when I add the SCI function only to the first sensor, I was able to see the data on RealTerm form COM port and the rest of the sensors worked good as well. But add the SCI function to another sensor - it ruins the rest of data recieved from other sensors.

I suppose it has something to do with I2CDRR register fom which I save data to Uint16 buffer.

The whole code is beneath:

(heared files addede to the project are the same as those from example i2c_eeprom + sci.h obviously)

(some comments are in polish)

/*
temp_LM_1
temp_LM_2
RH_SHT
Bufor_TSL_1
Bufor_TSL_2
*/
#include "DSP28x_Project.h"

void I2CA_Init(void);
void delay(unsigned char);

//interrupt void scia_rx_isr(void);
//interrupt void scia_tx_isr(void);
void scia_loopback_init(void);
void scia_fifo_init(void);

void scia_xmit(int a);

Uint16 Bufor_LM_1[2],Bufor_LM_2[2], Bufor_SHT[3], Bufor_TSL_1[5], Bufor_TSL_2[5];
Uint16 i, licznik, flag, czujnik;
Uint16 temp;
float temp_LM_1, temp_LM_2, RH_SHT;

long WaitTime = 110; // (9.3uS) @ 60Mhz TMS320F28035

void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2803x_SysCtrl.c file.
InitSysCtrl();

// Step 2. Initalize GPIO:
// This example function is found in the DSP2803x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();
// Setup only the GP I/O only for I2C functionality
InitI2CGpio();
InitSciGpio();
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2803x_PieCtrl.c file.
InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP2803x_DefaultIsr.c.
// This function is found in DSP2803x_PieVect.c.
InitPieVectTable();
EnableInterrupts();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
// PieVectTable.I2CINT1A = &i2c_int1a_isr;
EDIS; // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2803x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
I2CA_Init();
scia_fifo_init(); // Initialize the SCI FIFO
scia_loopback_init(); // Initalize SCI for digital loop back

// Enable interrupts required for this example

// Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

// Enable CPU INT8 which is connected to PIE group 8
IER |= M_INT8;
EINT;

flag = 0;
licznik = 0;
temp_LM_1 = 0;
temp_LM_2 = 0;
RH_SHT = 0;
czujnik = 1;

//czyszczenie buforow
for (i=0; i<2; i++)
{
Bufor_LM_1[i] = 0x0000;
Bufor_LM_2[i] = 0x0000;
}
for (i=0; i<5; i++)
{
Bufor_TSL_1[i] = 0x0000;
Bufor_TSL_2[i] = 0x0000;
}
for (i=0; i<3; i++)
{
Bufor_SHT[i] = 0x0000;
}
//nieskonczona petla programu
for(;;)
{
if(czujnik == 1)
{
while(czujnik != 2)
{

I2caRegs.I2CSAR = 0x4F; //ustalenie adresu czujnika LM_1
I2caRegs.I2CCNT = 2; //ile bajtow chcemy otrzymać
I2caRegs.I2CMDR.all = 0x2C20; //send restart as master reciver
if(I2caRegs.I2CSTR.bit.RRDY == 1) //register access ready
{
Bufor_LM_1[0] = I2caRegs.I2CDRR; //wypelnianie bufora danymi z czujnika
while(I2caRegs.I2CSTR.bit.RRDY == 0)
{
I2caRegs.I2CMDR.all = 0x2C20;
flag++;
}
Bufor_LM_1[1] = I2caRegs.I2CDRR;
temp_LM_1 = ((Bufor_LM_1[0]*256 + Bufor_LM_1[1])/32)*0.125;

czujnik = 2;


}
}
//czujnik = 2;
}

if(czujnik == 2)
{
while(czujnik != 3)
{

I2caRegs.I2CSAR = 0x48; //ustalenie adresu czujnika LM_2
I2caRegs.I2CCNT = 2; //ile bajtow chcemy otrzymać
I2caRegs.I2CMDR.all = 0x2C20; //send restart as master reciver
if(I2caRegs.I2CSTR.bit.RRDY == 1) //register access ready
{
Bufor_LM_2[0] = I2caRegs.I2CDRR; //wypelnianie bufora danymi z czujnika
while(I2caRegs.I2CSTR.bit.RRDY == 0)//sprawdzenie czy bit zostal odebrany
{
I2caRegs.I2CMDR.all = 0x2C20;
flag++;
}
Bufor_LM_2[1] = I2caRegs.I2CDRR; //wypelnianie bufora danymi z czujnika
temp_LM_2 = ((Bufor_LM_2[0]*256 + Bufor_LM_2[1])/32)*0.125;//obliczenie temp.

czujnik = 3;


}
}
//czujnik = 3;
}

if(czujnik == 3)
{
while(czujnik != 4)
{

I2caRegs.I2CSAR = 0x40; //ustalenie adresu czujnika SHT21
I2caRegs.I2CCNT = 1; //ile bajtow chcemy wyslac
//I2caRegs.I2CDXR = 0x00F3; //komenda pomiar temperatury SHT21
I2caRegs.I2CDXR = 0x00F5; //komenda pomiar wilgotnosci SHT21
I2caRegs.I2CMDR.all = 0x2620; //send start as master transmitter no stop

for(i=0; i<10000; i++) licznik++;

I2caRegs.I2CSAR = 0x40; //ustalenie adresu czujnika SHT21
I2caRegs.I2CCNT = 3; //ile bajtow chcemy odebrac
I2caRegs.I2CMDR.all = 0x2C20;

for(i=0;i<3;i++)
{
while(I2caRegs.I2CSTR.bit.RRDY == 0)//sprawdzenie czy bit zostal odebrany
{
I2caRegs.I2CMDR.all = 0x2C20; //send start as master reciever with stop
flag++;
}

Bufor_SHT[i] = I2caRegs.I2CDRR; //wypelnianie bufora danymi z czujnika
} //1 i 2-dane, 3-Checksum
RH_SHT = (Bufor_SHT[0]*256 + Bufor_SHT[1]-2);
I2caRegs.I2CMDR.all = 0x0032;
czujnik = 4;



}
//czujnik = 4;
}

if(czujnik == 4)
{
while(czujnik != 5)
{
I2caRegs.I2CSAR = 0x49; //ustalenie adresu czujnika TSL_1
I2caRegs.I2CCNT = 1; //ile bajtow chcemy wyslac
I2caRegs.I2CDXR = 0x03; //data byte 3 - turn ON
I2caRegs.I2CMDR.all = 0x6E20; //send start as master transmitter with stop

delay(10);

//ODBIÓR DANYCH

I2caRegs.I2CSAR = 0x49; //ustalenie adresu czujnika TSL_1
I2caRegs.I2CCNT = 1; //ile bajtow chcemy wyslac
I2caRegs.I2CDXR = 0x9B; //
I2caRegs.I2CMDR.all = 0x2620; //send start as master reciever no stop

delay(10);

I2caRegs.I2CSAR = 0x49; //ustalenie adresu czujnika TSL_1
I2caRegs.I2CCNT = 5; //ile bajtow chcemy odebrac
I2caRegs.I2CMDR.all = 0x2C20; //send start as master reciever with stop


for(i=0;i<5;i++)
{
while(I2caRegs.I2CSTR.bit.RRDY != 1)//sprawdzenie czy bit zostal odebrany
{
I2caRegs.I2CMDR.all = 0x2C20; //send start as master reciever with stop
flag++;
}
Bufor_TSL_1[i] = I2caRegs.I2CDRR; //wypelnianie bufora danymi z czujnika
} //1-byte count, 2-5 - Data
czujnik = 5;


}
//czujnik = 5;
}

if(czujnik == 5)
{
while(czujnik != 1)
{
//RAMKA WŁĄCZANIA CZUJNIKA

I2caRegs.I2CSAR = 0x29; //ustalenie adresu czujnika TSL_2
I2caRegs.I2CCNT = 1; //ile bajtow chcemy wyslac
I2caRegs.I2CDXR = 0x03; //data byte 3 - turn ON
I2caRegs.I2CMDR.all = 0x6E20; //send start as master transmitter with stop

delay(10);

//ODBIÓR DANYCH

I2caRegs.I2CSAR = 0x29; //ustalenie adresu czujnika TSL_2
I2caRegs.I2CCNT = 1; //ile bajtow chcemy wyslac
I2caRegs.I2CDXR = 0x9B; //
I2caRegs.I2CMDR.all = 0x2620; //send start as master reciever no stop

delay(10);

I2caRegs.I2CSAR = 0x29; //ustalenie adresu czujnika TSL_2
I2caRegs.I2CCNT = 5; //ile bajtow chcemy odebrac
I2caRegs.I2CMDR.all = 0x2C20; //send start as master reciever with stop

for(i=0;i<5;i++)
{
while(I2caRegs.I2CSTR.bit.RRDY != 1)//sprawdzenie czy bit zostal odebrany
{
I2caRegs.I2CMDR.all = 0x2C20; //send start as master reciever with stop
flag++;
}
Bufor_TSL_2[i] = I2caRegs.I2CDRR; //wypelnianie bufora danymi z czujnika
} //1-byte count, 2-5 - Data

czujnik = 1;


}
//czujnik = 1;
}

licznik++;

}//koniec petli for
}//koniec funkcji main


void delay(unsigned char i)
{
long int k,j;

for(k=0;k<i;k++)
{
for(j=0;j<64000;j++);
}
}


void scia_loopback_init()
{
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function

SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =1;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
SciaRegs.SCIHBAUD =0x0000;
SciaRegs.SCILBAUD =0x00C2; // 9600 BAUD
SciaRegs.SCICCR.bit.LOOPBKENA =1; // Enable loop back
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
}

// Initalize the SCI FIFO
void scia_fifo_init()
{
SciaRegs.SCIFFTX.all=0xE040;
SciaRegs.SCIFFRX.all=0x2044;
SciaRegs.SCIFFCT.all=0x0;

}

//send byte do PC
void scia_xmit(int a)
{
while(SciaRegs.SCICTL2.bit.TXRDY == 0 || SciaRegs.SCICTL2.bit.TXEMPTY == 0){}
//czekaj jesli bufor transmisji nie jest gotowy lub jest niepusty
SciaRegs.SCITXBUF = a;
//while(I2caRegs.I2CSTR.bit.RRDY == 0){temp = I2caRegs.I2CDRR;}
}

void I2CA_Init(void)
{
// Initialize I2C
I2caRegs.I2CPSC.all = 6; // Prescaler - need 7-12 Mhz on module clk
I2caRegs.I2CCLKL = 10; // NOTE: must be non zero
I2caRegs.I2CCLKH = 5; // 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

return;
}

  • Hi,

    Did you try synchronizing all the events ie one at time? Try using CPUtimer as you main subroutine where you fetch data from I2C sensors and then send the data to PC. CPUtimer having the highest priority would make the I2C Rx interrupts wait until its execution; this will prevent collision.

    Regards,

    Gautam

  • Hi Gautam,

    do you mean like putting the routine for collecting data from sensors and sending them to the PC in different CPUTimer interrupts like in the example from control suite CPU Timer?

    Thank you in advance for your reply.

    Regards,

    Rafal

  • You can implement that, but what I mean to say is that, do it in a "structural way".

    Regards,

    Gautam

  • I finally solved the issue! 

    I did some research and found out that SCI also has a higher priority than I2C. I believe that your solution would also work (the one using CPU Timer), but I really did not even have an idea in my head how to implement it in my code. 

    Nevertheless, I tried to make my code more "structural". I gave up all the delays, which were supposed to "give some time" to I2C to put specific values in its registers. I used all the bits from I2CSTR I could to make sure that the program doesnt start doing anything else before other instructions aren't done. 

    I am almost sure that this is what was hapening before. The SCI was sending the right data via UART, but the data received by I2C were wrong, because without using SCI, the sensors gave me right values. There must have been a collision causing the received-data register to overrun.

    I learned a valuable lesson thanks to that problem I had ;)

    And thank you very much Gautam for giving me a hint. It was very useful.

    Kind Regards, 

    Rafal

  • That's great, Rafal. I would like you to close this thread by verifying the answer which means that this query has been solved.


    Good luck & Regards,

    Gautam