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.

Problems with I²C while write and read operation (F28335)

Other Parts Discussed in Thread: TMS320F28335, TMDSDOCK28335

Hi Community,


I'm new to this forum and I hope I'm doing everything correctly.

In context of my bachelor thesis I'm using the I²C module to communicate with the MD03 H Bridge Motor Drive, which controlls my 12V DC motor. You can find the technical documentation of the MD03 here

As you can see in the subject of this post I'm using the TMS320F28335 in combination with the TMDSDOCK28335.

My code for this is as follows:

#include "DSP2833x_Device.h"
#include "DSP2833x_GlobalVariableDefs.c"

// defines i'm using
#define Slave_HB1 0xB0						// Slave-address h-bridge
#define hbcommand 0x00						// address Command Register MD03 0x00
#define hbstatus  0x01						// address Status Register MD03 0x01
#define hbspeed   0x02						// address Speed Register MD03 0x02
#define hbacc     0x03						        // address Acceleration Register MD03 0x03
#define hbtemp	  0x04						// address Temperature Register MD03 0x04
#define hbcurr	  0x05						// address Motor Current Register MD03 0x05


extern void InitSysCtrl(void);
extern void InitPieCtrl(void);
extern void InitPieVectTable(void);
extern void InitCpuTimers(void);
extern void ConfigCpuTimer(struct CPUTIMER_VARS *, float, float);

void GPIO_setup(void);  	   				// method to configure the GPIO's i'm using
void IIC_Init(void);	   					// method to initialize the Inter-Integrated-Circuit



interrupt void cpu_timer0_isr(void);

 void main(void) {
	int speed=0;

	InitSysCtrl();	// Basic Core Init from DSP2833x_SysCtrl.c

	EALLOW;
   	SysCtrlRegs.WDCR= 0x00AF;	// Re-enable the watchdog
			// 0x00AF  to NOT disable the Watch-Dog, Prescaler = 64
	//SysCtrlRegs.WDCR |= 0x0068;   			// switch of Watch-Dog 
	EDIS;

	DINT;						 		    // disable all interrupts

	GPIO_setup();							// configure GPIOs
	IIC_Init();								// initialize I²C 
	
	
	InitPieCtrl();		// basic setup of PIE table; from DSP2833x_PieCtrl.c
	InitPieVectTable();	// default ISR's in PIE

	EALLOW;
	PieVectTable.TINT0 = &cpu_timer0_isr;
	EDIS;

	InitCpuTimers();	// basic setup CPU Timer0, 1 and 2
	ConfigCpuTimer(&CpuTimer0,150,100000);

	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

	IER |=1;   // Enable Intterupt

	EINT;	
	ERTM;

CpuTimer0Regs.TCR.bit.TSS = 0;	// start timer0


while(1)
	{	  	
	
	while(CpuTimer0.InterruptCount == 0);
	CpuTimer0.InterruptCount = 0;

	EALLOW;
	SysCtrlRegs.WDKEY = 0x55;	// service WD #1
	EDIS;

	I2caRegs.I2CCNT =2;						// value of I2CCNT says after n data-bytes generate a stop condition 
	I2caRegs.I2CDXR=hbcommand;                           // send register address --> command register motor direction
I2caRegs.I2CMDR.all=0x6E20; // generate Start-Stop-Master-Transmitter
while (I2caRegs.I2CSTR.bit.XRDY==0); // wait until first byte is out I2caRegs.I2CDXR = 1; // value of I2CDXR is next data-byte i want to send //while(I2caRegs.I2CIER.bit.XRDY==0); // wait until second byte is out while(I2caRegs.I2CIER.bit.SCD==0); // wait for stop bit I2caRegs.I2CSTR.bit.SCD = 1; // clear stop condition flag I2caRegs.I2CCNT =2; I2caRegs.I2CDXR =hbspeed; I2caRegs.I2CMDR.all = 0x6E20; while(I2caRegs.I2CSTR.bit.XRDY==0); I2caRegs.I2CDXR = 0x32; // 0x32 --> 50 range of values (0-243) --> value of the max speed while(I2caRegs.I2CIER.bit.SCD==0); I2caRegs.I2CSTR.bit.SCD = 1; I2caRegs.I2CCNT =2; I2caRegs.I2CDXR =hbacc; I2caRegs.I2CMDR.all = 0x6E20; while(I2caRegs.I2CSTR.bit.XRDY==0); I2caRegs.I2CDXR = 0xFF; // 0xFF --> 255 range of values (0-255) --> controls how fast the motor reaches max speed of the speed register while(I2caRegs.I2CIER.bit.SCD==0); I2caRegs.I2CSTR.bit.SCD = 1; } } void GPIO_setup(void) { EALLOW; GpioCtrlRegs.GPBMUX2.all = 0; // Pins 32 - 47 use as I/O - Pins GpioCtrlRegs.GPBMUX1.bit.GPIO32=0x1; // Pin 32 us as SDA I²C GpioCtrlRegs.GPBMUX1.bit.GPIO33=0x1; // Pin 33 us as SCL I²C GpioCtrlRegs.GPBPUD.bit.GPIO32= 0; // Pull-Up Pin 32 GpioCtrlRegs.GPBPUD.bit.GPIO33= 0; // Pull-Up Pin 33 GpioCtrlRegs.GPBQSEL1.bit.GPIO32=0x3; // Async Input SDA GpioCtrlRegs.GPBQSEL1.bit.GPIO33=0x3; // Async Input SCL --> GPIO Doku S.69 EDIS; } void IIC_Init(void) { I2caRegs.I2CMDR.bit.IRS=0; // Reset Mode I²C module I2caRegs.I2CSAR= Slave_HB1; // value of I2CSAR is the next slave address i want to send to I2caRegs.I2CPSC.all= 0x0E; // I²C Module Clock = SYSCLOCK/(IPSC+1) = 10MHz --> S.14 I²C Doku. (0x0E = 14) // Master Clock fuer 7,5 kHz /* I2caRegs.I2CCLKL.all= 0x02A0; // TMaster= (IPSC+1)*[(ICCL+d)+(ICCH+d)] / SYSCLOCK --> (I²C Doku S.34) I2caRegs.I2CCLKH.all= 0x02A0; // 7,5 kHz --> TMaster= 133,3 µs , d=5 --> IPSC >1 // (133,3 µs * SYSCLOCK) / (IPSC+1) = [(ICCL+d)+(ICCH+d)] // (133,3 µs * 150MHz) / 15 = (ICCL + ICCH +10) // 1333 = ICCL + ICCH + 10 // ICCL + ICCH = 1343 // ICCL + ICCH time of the low and high level // ICCL = ICCH = 1343/2 = 671,5 // 671,5 --> float --> 672 --> 0x02A0 */ // Master Clock fuer 100 kHz I2caRegs.I2CCLKL= 45; // TMaster= 10 µs I2caRegs.I2CCLKH= 45; // ICCL = ICCH = 90/2 = 45 --> 0x009F I2caRegs.I2CMDR.bit.IRS=1; // takes I²C Module out of Reset-Mode } interrupt void cpu_timer0_isr(void) { CpuTimer0.InterruptCount++; EALLOW; SysCtrlRegs.WDKEY = 0xAA; // service WD #2 EDIS; PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; }

You can find all the registers and informations I used to generate the code in this pdf.file .

While debugging I found that my code works fine up line 75. The problem starts in line 76.
In this line I want to generate my start stop master transmitter, what means i have to write the 0x6E20 in the I2CMDR register.
But after executing this line the register value is 0x4E20. That means my STT bit was not set to 1.

I think it's not that bad because the I²C module generates (with a value of 0 in the STT bit) a start condition and clears the STT bit after it's generated the start condition.
But maybe I'm wrong with that?

In line 78 my programm stops working because in this line I'm waiting until the value of the XRDY bit of the status register is 1 (data is send to Slave-Address) . But this never happens and i haven't found my problem
after spending somedays with it. I'm not sure if  line 76 really generated the start condition or there is another problem.
I checked the status register of the I²C module after executing line 76 and the value of it was 0x1400. Which means the bus is busy, what happens after the a start condition has been generated and
it detected no underflow, what means that the data is written in I2DXR correctly.

Maybe my connections are the problem. Therefore I want to mention how i connected the MD03 with my µC and the DC motor.
For the connection between the MD03 and the µC I'm using a Breadboard and external voltage supply (+3,3V) and 2 Pull-Up Resistors with 4,7kOhm.
The MD03 is connected to an external voltage supply for the logic (+5V) and a 12V battery for the motor supply.
The connection of the Breadboard looks like this:



I connected the external voltage supply (3,3V) with the + and - wire of my breadboard. Than I connected the + wire with the wire where my Pull-Up resistors are connected.
My resistors are connected to the SDA and SCL wire of the µC (orange line to Pin 32 and Pin 33) and the MD03 (green lines in the Input of MD03 SDA and SCL).
My motor is connected to the both MOT inputs of the MD03.

While debugging I also found that the input of the SDA and SCL wire of the MD03 have a constant voltage level of 3,3V up to line 78.
In this line is the SDA wire on a voltage level of 3,7V and SCL wire on 2,9V. Both levels are constant. I looked at this wires with an oscilloscope and these levels are constant all the time so there are no high and low levels.
The only difference is after executing line 76 the change from 3,3V on SDA and SCL wire to 3,7V on SDA and 2,9V on SCL.

I hope there is someone who can help me and I described everything clearly.

Thanks and regards!


André

  • André,

    I haven't had a chance to try your code, but I do see a couple problems.

    First, when you poll for a status change, you should poll the I2CSTR register. I2CIER is the interrupt enable register. Its bits do not change unless you write to them.

    Second, you shouldn't be able to get 3.7V on SDA if you're pulling it up to 3.3V. Please check your connections carefully to make sure you're not connecting any 5V signals to the MCU.