Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
/*
i2c support for LPC21XX
(c) 2004 Yuri Tiomkin (yuri@tnkernel.com)
Includes drivers:
- EEPROM 24XX series (from 24XX04 to 24XX512)
- Real Time Clock DS1307
- I/O Extender PCA9555
- Temperature sensor LM75
Supports uCOS-II and TNKernel
THIS SOFTWARE IS PROVIDED BY THE YURI TIOMKIN AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL YURI TIOMKIN OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* This is a modified I2C module based on the code by Pierre Seguin */
/* it tests the status of all transactions and returns any error codes */
/* via a "longjmp" */
/* It is easily modified to directly return the status codes instead of */
/* using the longjmps */
/* This code returns an error value of 1 for the most likley error:- */
/* - no device available. This is not a code that can be confused with the */
/* standard status values. */
/* A sample of its use is getBattery() using a PCF8591 A/D device */
/* Owen Mooney */
jmp_buf i2cerror;
#define STA 0x20
#define SIC 0x08
#define SI 0x08
#define STO 0x10
#define STAC 0x20
#define AA 0x04
void InitI2C(void) {
I2CONCLR = 0xFF;
PINSEL0 |= 0x50; // Set pinouts as scl and sda
I2SCLL =19; //speed at 100Khz for a VPB Clock Divider = 4 at 14 MHz
I2SCLH =19;
// I2SCLL=60; //speed at 375Khz for a VPB Clock Divider = 1
// I2SCLH=70; // Pierre Seguin's origional values.
I2CONSET = 0x40; //Active Master Mode on I2C bus
}
void SendI2CAddress(unsigned char Addr_S){
unsigned char r;
I2CONCLR = 0xFF; // clear I2C - included if User forgot to "StopI2C()"
// else this function would hang.
I2CONSET = 0x40; // Active Master Mode on I2C bus
if((Addr_S & 0x01)) // test if it's reading
I2CONSET = STA | AA; // set STA - allow master to acknowlege slave;
else
I2CONSET = STA; // set STA dont allow acknowledges;
while(I2STAT!=0x08) ; // Wait for start to be completed
I2DAT = Addr_S; // Charge slave Address
I2CONCLR = SIC | STAC; // Clear i2c interrupt bit to send the data
while( ! ( I2CONSET & SI)) ; // wait till status available
r=I2STAT; // read Status. See standard error codes pdf (link in manual).
if(!(Addr_S & 0x01)) { // if we are doing a write
if (r != 0x18) { // look for "SLA+W has been transmitted; ACK has been received"
if ( r==0x20 ) // check for "SLA+W has been transmitted; NOT ACK has been received"
longjmp(i2cerror,1); // no acknowlege - probably no device there. Return a 1 in longjmp
longjmp(i2cerror,r); // other error - return status code in longjmp
}
} else {
if (r != 0x40) { // look for "SLA+R has been transmitted; ACK has been received"
if ( r==0x48 ) // check for "SLA+R has been transmitted; NOT ACK has been received"
longjmp(i2cerror,1); // no acknowlege - probably no device there. Return a 1 in longjmp
longjmp(i2cerror,r); // other error - return status code in longjmp
}
}
}
unsigned char ReadI2C(void) {
unsigned char r;
I2CONCLR = SIC; // clear SIC;
while( ! (I2CONSET & 0x8)); // wait till status available
r=I2STAT; // check for error
if (r != 0x50){ // look for "Data byte has been received; ACK has been returned"
longjmp(i2cerror,r); // read fail
}
return I2DAT;
}
void WriteI2C(unsigned char Data) {
unsigned char r;
I2DAT = Data; // Charge Data
I2CONCLR = 0x8; // SIC; Clear i2c interrupt bit to send the data
while( ! (I2CONSET & 0x8)); // wait till status available
r=I2STAT;
if (r != 0x28){ // look for "Data byte in S1DAT has been transmitted; ACK has been received"
longjmp(i2cerror,r); // write fail
}
}
void StopI2C(void){
I2CONCLR = SIC;
I2CONSET = STO;
while((I2CONSET&STO)) ; // wait for Stopped bus I2C
}
float getBattery(void){ // Read the battery voltage with a PCF8591 A/D device
unsigned char err,r;
char mess[10];
int x;
InitI2C();
if (err=setjmp(i2cerror)) {
if (err==1)
error("no A/D device found");
else
sprintf(mess,"I2C error %d",err);
error(mess);
return;
}
SendI2CAddress(0x90); // PCF8591 A/D device address
WriteI2C(0); // Set the control port value
WriteI2C(0); // and the D/A output
StopI2C();
SendI2CAddress(0x91); // Start the read
ReadI2C(); // dummy read cycle to do the first conversion
r=ReadI2C(); // read the result
StopI2C();
return r*12.15/118; // return the battery voltage
}