We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Question regards SCL timing I've got a slave application running on a 87LPC762 clocked at 9.8 Mhz (external clock). I'm siumulating a transmission of one byte of data from slave to master. what happens is as soon as the slave receives the address from master ans go into a routine to check up the address (the micro should look up into a table and see if any of adresses he has to respond to is there) the master receves a Negative acknowldgement insted of waiting for the slave till it finishes its job. This will cause a problem. I guess the problem here is that my routine is taking more time than the SCL LOW/High time (12us for the routine while the SCL is ~5 us I guess for 100Khz I2C bus).....Is there any clue how to overcome this issue ?!!! Thanks
My receibe byte (which is used alos for receivinf address byte) is based on the Philips application note AN463. In this note the ReciveByte routine implements this concepts of streching the Low period of SCL upon reading the last bit in byte. This is done by reading the last bit from I2CON (RDAT bit) and not from I2DAT. This way the data Ready (DRDY) flag is not cleared and the low period on SCL is streched. My question here is: This is not what I see in the I2C simulator of uVision2!!!! in the last bit I observe that DRDY flag is not cleared, ATN is not cleared and the SCL raising edege happens though when I ecpected it to stretch untill the DDRDY flag is cleared!!!!
Do you have an I2C timeout interrupt process enabled? The 762 times out after roughly 1024 instruction cycles if this timer is enabled. You also don't mention whether or not you have read or written I2DAT since the last bit. As was pointed out in a prior reply ... you need to implement the timeout to avoid a lock up on the master.
Kais, Haven't heard from you for a week ... you must have found a solution or you are stuck. In case you are stuck, here is sample code that handles the timeout and interrupt stuff. NOTE: The I2C Timeout must be the ONLY high priority interrupt active for this to work. This is because of the saved stack pointer which, when restored, pops the code back to the StartStop interrupt exit point to clean up interrupt flags.
#include <Reg764.h> #include <intrins.h> typedef unsigned char byte; #define FALSE 0 /* Logical false */ #define TRUE (~FALSE) /* Logical true */ bit InI2CInt; // In I2C Interrupt bit TimeOut; // I2C timed out byte SaveSP; // I2C Interrupt related void InitializeI2CSubSystem (void); void ProcessI2CMessage (void); /* -------------------------------------------------------------------------- */ void I2C_StartStopInterrupt (void) interrupt 6 using 1 { TimeOut = FALSE; // Clear I2C timeout if (!STP || STR) { // No Stop detected do { ProcessI2CMessage (); } while (STR); } I2CON = 0xFC; // Enter Idle, clear status } /* -------------------------------------------------------------------------- */ void I2C_TimeOut (void) interrupt 14 // This routine cannot use any registers { I2CFG &= 3; // Save CT0 and CT1 I2CFG |= 0xB0; // Set SLAVEN + CLRTI + TIRUN I2CON = 0xFC; // Enter Idle, clear all status bits SDA = TRUE; SCL = TRUE; TimeOut = TRUE; if (_testbit_(InI2CInt)) SP = SaveSP; } /* -------------------------------------------------------------------------- */ main () // Main Program { InitializeI2CSubSystem (); while (TRUE) { WDRST = 0x1E; // Pat watch dog WDRST = 0xE1; } } /* -------------------------------------------------------------------------- */ void InitializeI2CSubSystem () { P1M1 |= 0x0C; P1M2 |= 0x0C; // Make SDA and SCL OpenDrain SDA = TRUE; SCL = TRUE; I2CFG = 0xB2; // Enable Slave operation on I2C bus I2CON = 0xFC; // Enter idle mode clear all status bits EI2 = TRUE; // Enable I2C interrupts TIRUN = ETI = PTI = TRUE; // Turn on I2C timer } /* -------------------------------------------------------------------------- */ void ProcessI2CMessage (void) { SaveSP = SP; // Save SP in case I2C locks InI2CInt = TRUE; // Note that SaveSP is valid I2CON = 0x9C; // Clear flag bits // Receive byte, validate address, process request InI2CInt = FALSE; // Clear note on SaveSP }
Well...The solution should be what I have sent in my last reply (streching the clock low by not clearing the ATN flag the release it when the routine is covered) ...but again that's not what I see in the uVision2 simulator (Open question) ?!!!!! (....I overpassed my ptoblem as I figured out that the master clock is slow enough to make room for my address lookup routine in a clock period.)