Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem with interrupts between I2C data transfer

Status
Not open for further replies.

Navid T

Full Member level 3
Joined
Jan 21, 2005
Messages
186
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,296
Location
Iran
Activity points
1,385
Hi friends

I want to read ITG-3200 ( by I2C module of dspic30F2011 ). in normal program it's ok and i can read it without problem, but the problem is my main program has timer interrupt too, the timer interrupt happens so faster than reading from i2c and when it's reading ITG-3200 from I2C module lot of interrupt comes between reading and after short time it makes problem for ITG read. ( i use timer interrupt to make software pwm )

do you have any suggestion?
Regards
 

Yes but i thought nobody read lot of codes here:
Code:
/*ertebat ba ITG-3200 ( khandane x y z ) 
	va pwm rooye 4 kanal ( hamzaman ) ( barname kami irad darad 
	va gaahi gir mikonad va nemoone bardari anjam nemidahad bayad
	tabe haa ra kami taghir daham ke ba timer moshkel peyda nakonand*/
#include "P30F2011.h"
#define	itgaddw	0B11010010
#define itgaddr	0B11010011

_FOSC(CSW_FSCM_OFF & FRC_PLL16);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN);
_FGS(CODE_PROT_OFF);

//--------------- FUNCTIONS ----------------
void send( unsigned char );
unsigned char get( void );
void i2c_start();
void i2c_restart();
void i2c_stop();
void i2c_ack();
void i2c_nack();
void i2c_write(unsigned char);
unsigned char i2c_read();

//-------------- Global vars ------------
unsigned int counter,front,rear,left,right;

//-------------- Timer 1 INT -------------------
void _ISR _T1Interrupt(void)
{
   counter++;
   if(counter<front)
      _RB0=1;
   else
      _RB0=0;
   if(counter<rear)
      _RB1=1;
   else
      _RB1=0;
   if(counter<left)
      _RB2=1;
   else
      _RB2=0;
   if(counter<right)
      _RB3=1;
   else
      _RB3=0;
   if(counter>1670)
      counter=0;
   TMR1 = 0;
   _T1IF = 0;
}

//----------------- MAIN() -------------------
void main()
{
	unsigned char temp,i;
	unsigned  char xh,xl,yh,yl,zh,zl;

    front = 250;
    rear = 200;
    left = 100;
    right = 50;
    ADPCFG=0XFFFF;             //PORTB DIGITAL
    TRISB = 0;
    PORTB = 0;
    IPC0= IPC0 | 0X4000;            	//TIMER1 INTERRUPT PRIORITY = 4
    TMR1=0;
    PR1=150;
    T1CON = 0X8000;            //1:256 PRESCALE
    _T1IF=0;
    _T1IE=1;

    U1BRG=15;                     //BAUD RATE = 115200
    U1MODE=0X8400;                //ENABLE UART MODULE AND ALTERNATE IO
 	U1STA=0X8400;
	
	I2CCON = 0X9000;
	I2CBRG = 188;	
		
	//------- ITG SETTINGS ---------
	i2c_start();
	i2c_write(itgaddw);
	i2c_write(0x16);
	i2c_write(0B00011010);
	i2c_stop();
	//----- SETTING FINISHED ---------

	while(1)
	{	
	i2c_start();
	i2c_write(itgaddw);
	i2c_write(0x1D);			//X high byte Address
	i2c_restart();
    i2c_write(itgaddr);
	xh = i2c_read();				
	i2c_ack();
	xl = i2c_read();				
	i2c_ack();
	yh = i2c_read();
	i2c_ack();
	yl = i2c_read();
	i2c_ack();
	zh = i2c_read();
	i2c_ack();
	zl = i2c_read();
	i2c_nack();
	i2c_stop();
	send(xh);
	send(xl);
	send(yh);
	send(yl);
	send(zh);
	send(zl);

	T3CON = 0X8030;					//DELAY			
	TMR3 = 0;
	while(TMR3<1000);
	T3CON = 0;		

	}//end of while(1)

}//end of main()

//------------- send() -----------------
void send(unsigned char a)
{
     while(!_U1TXIF);
     _U1TXIF=0;
     U1TXREG=a;              //SEND
}
//------------- get() ------------------
unsigned char get(void)
{
     unsigned char a;
     while(!_U1RXIF);
     _U1RXIF=0;
     a=U1RXREG;            //RECEIVE
     return a;
}
//-------------- i2c_start() -----------
void i2c_start()
{
	_SEN=1;
	while(_SEN);
}
//-------------- i2c_restart() ----------
void i2c_restart()
{
	_RSEN=1;				
    while(_RSEN);
}
//------------- i2c_write() -------------
void i2c_write(unsigned char a)
{
	I2CTRN = a;
	while(_TRSTAT);	
}
//-------------- i2c_stop() --------------
void i2c_stop()
{
	_PEN = 1;
	while(_PEN);
}
//-------------- i2c_read() --------------
unsigned char i2c_read()
{
	unsigned char a;
	_RCEN=1;
    while(_RCEN);
	while(!_RBF);
    a = I2CRCV;
	return a;
}
//-------------- i2c_ack() ----------------
void i2c_ack()
{
	_ACKDT=0;
    _ACKEN=1;
	while(_ACKEN);
}
//-------------- i2c_nack() ----------------
void i2c_nack()
{
	_ACKDT=1;
    _ACKEN=1;
	while(_ACKEN);
}
 

Only when we want to give good advice!

:lol:

---------- Post added at 15:12 ---------- Previous post was at 15:10 ----------

I'll look the code over and get back with you after I eat breakfast.
 

so give me good advice please;-)
 

I just gave your code a quick look. Have you set the NSTDIS bit?

If the NSTDIS bit (INTCON1<15>) is set, nesting of
interrupts is prevented. Thus, if an interrupt is currently
being serviced, processing of a new interrupt is
prevented even if the new interrupt is of higher priority
than the one currently being serviced.

Back to breakfast.
 

Attachments

  • 70139G.pdf
    2.8 MB · Views: 81

Thanks for your help
Here is just one interrupt source ( Timer 1 ), i didn't use I2C interrupt, so nesting interrupt will not happen.
in this program pwm is generate correctly but the problem is with reading 6byte stream from I2C and sending those values throught uart.
 

You didn't specify the observed problems. By design, an I2C slave will tolerate master clocks down to zero frequency. I guess, there may be a problem with data consistency, if registers are read at different times. If so, it's rather a design problem of the slave.
 

I think Slave doesn't have any problem, the problem is in my program but unfortunately i don't now is it for Timer interrupt or anything else !!

---------- Post added at 16:33 ---------- Previous post was at 15:59 ----------

now i disable Timer interrupt befor reading and enable it after reading I2C string finished, in this way all works well but pwm frequency is not ok ( lower because of duration that interrupt is disable )
 
Last edited:

the problem is in my program
Yes, I guess so. You didn't tell yet how the problem shows. I reviewed your code and found that using the interrupt flags for polled UART operation is rather unusual, and possibly causes problems. There's the UTXBF flag available for polled operation.

In addition I wonder, if 30F2011 has a silicon bug related to IO port read-modify-write and I2C operation, as some 8 bit PICs had. If so, it would be mentioned in the errata sheets.
 

when timer interrupt is disable , program reads from I2C and send those data through uart for ever in while(1) loop ( i see data from uart on pc ), but when timer interrupt is enable it only sends data in short time ( about 1 sec ) and then nothing is sending through uart.

---------- Post added at 17:53 ---------- Previous post was at 17:30 ----------

what do you mean by silicon bug?
 

what do you mean by silicon bug?
Erratical hardware behaviour. According to the dspic30f2011 errata sheet, there are no known problems, however.
only sends data in short time ( about 1 sec ) and then nothing is sending through uart.
You should be able to figure out, what the processor is waiting for in this situation. Either the I2C master or the UART may "hang". Hardware debugging with MPLAB would be the best option to find out what's going on.
 
I found hanging is in reade function, after short time that it works properly it'll lock on " while(!_RBF); "
it means reading is not complete and I2CRCV is empty. i don't know the reason but i see when i disable interrupt temporary on i2c_write(); function hanging doesn't happens!
 

Did you check, if I2C stops due to clock stretching performed by the slave?
 

can you explain more please? I2C stops after reading slave and sending Nack to it, how it's possible to stop while clock stretching of slave?!
 

As far as I understand, clock stretching (slave is pulling SCK low) would be the only way to stop the master during read. It can be determined by checking the bus levels.
 

If you are sure of your firmware...Do check the errata of this controller...its microchip...its error prone...
 

No, I'm sure to microchip more than my firmware, all times i was worry about microcontroller i found mistake in my work not microcontroller, I don't have much time to finish this project so i change my method now but as soon as possible that i'm free i'll find my problem.
Thanks for your helps
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top