/********************************************************************* * * i2c master library for Fraise pic18f device ********************************************************************* * Author Date Comment *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Antoine Rousseau october 2013 adapted from Vangelis Rokas's sdcc i2c lib. ********************************************************************/ /* # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. */ #include #include #ifndef I2CMASTER_PORT #define I2CMASTER_PORT 1 #endif #if I2CMASTER_PORT==1 #define SSPxBUF SSPBUF #define SSPxCON1 SSPCON1 #define SSPxCON1bits SSPCON1bits #define SSPxCON2 SSPCON2 #define SSPxCON2bits SSPCON2bits #define SSPxCON3 SSPCON3 #define SSPxCON3bits SSPCON3bits #define SSPxSTAT SSPSTAT #define SSPxSTATbits SSPSTATbits #define SSPxMSK SSPMSK #define SSPxMSKbits SSPMSKbits #define SSPxADD SSPADD #define SSPxADDbits SSPADDbits #define SSPxIF PIR1bits.SSPIF #define SSPxIE PIE1bits.SSPIE #define SSPxIP PIR1bits.SSPIP #define BCLxIF PIR2bits.BCLIF /*#define SSPxBUF SSP1BUF #define SSPxCON1 SSP1CON1 #define SSPxCON1bits SSP1CON1bits #define SSPxCON2 SSP1CON2 #define SSPxCON2bits SSP1CON2bits #define SSPxCON3 SSP1CON3 #define SSPxCON3bits SSP1CON3bits #define SSPxSTAT SSP1STAT #define SSPxSTATbits SSP1STATbits #define SSPxMSK SSP1MSK #define SSPxMSKbits SSP1MSKbits #define SSPxADD SSP1ADD #define SSPxADDbits SSP1ADDbits #define SSPxIF PIR1bits.SSP1IF #define SSPxIE PIE1bits.SSP1IE #define SSPxIP PIR1bits.SSP1IP #define BCLxIF PIR2bits.BCL1IF*/ #else #define SSPxBUF SSP2BUF #define SSPxCON1 SSP2CON1 #define SSPxCON1bits SSP2CON1bits #define SSPxCON2 SSP2CON2 #define SSPxCON2bits SSP2CON2bits #define SSPxCON3 SSP2CON3 #define SSPxCON3bits SSP2CON3bits #define SSPxSTAT SSP2STAT #define SSPxSTATbits SSP2STATbits #define SSPxMSK SSP2MSK #define SSPxMSKbits SSP2MSKbits #define SSPxADD SSP2ADD #define SSPxADDbits SSP2ADDbits #define SSPxIF PIR3bits.SSP2IF #define SSPxIE PIE3bits.SSP2IE #define SSPxIP PIR3bits.SSP2IP #define BCLxIF PIR3bits.BCL2IF #endif /*#ifndef SSP1CON1 #define SSPxBUF SSPBUF #define SSPxCON1 SSPCON1 #define SSPxCON1bits SSPCON1bits #define SSPxCON2 SSPCON2 #define SSPxCON2bits SSPCON2bits #define SSPxCON3 SSPCON3 #define SSPxCON3bits SSPCON3bits #define SSPxSTAT SSPSTAT #define SSPxSTATbits SSPSTATbits #define SSPxMSK SSPMSK #define SSPxMSKbits SSPMSKbits #define SSPxADD SSPADD #define SSPxADDbits SSPADDbits #define SSPxIF PIR1bits.SSPIF #define SSPxIE PIE1bits.SSPIE #define SSPxIP PIR1bits.SSPIP #define BCLxIF PIR2bits.BCLIF #endif*/ void i2cm_init(unsigned char mode, unsigned char slew, unsigned char addr_brd) { SSPxSTAT &= 0x3f; SSPxCON1 = 0; SSPxCON2 = 0; SSPxCON1 |= mode; SSPxSTAT |= slew; #if I2CMASTER_PORT==1 SetPinDigiIn(I2C1SDA); SetPinDigiIn(I2C1SCL); SetPinAnsel(I2C1SDA,0); SetPinAnsel(I2C1SCL,0); #else SetPinDigiIn(I2C2SDA); SetPinDigiIn(I2C2SCL); SetPinAnsel(I2C2SDA,0); SetPinAnsel(I2C2SCL,0); #endif SSPxADD = addr_brd; SSPxCON1 |= 0x20; // enable SSP SSPxIF = 0; // MSSP Interrupt Flag BCLxIF = 0; // Bus Collision Interrupt Flag } void i2cm_close(void) { SSPxCON1 &= 0xdf; } /*--------------------------------------*/ unsigned char i2cm_drdy(void) { if(SSPxSTATbits.BF) return (+1); else return (0); } void i2cm_idle(void) { while((SSPxCON2 & 0x1f) | (SSPxSTATbits.R_W)); } void i2cm_start(void) { i2cm_idle(); SSPxCON2bits.SEN = 1; while (SSPxCON2bits.SEN); } void i2cm_restart(void) { i2cm_idle(); SSPxCON2bits.RSEN = 1; while (SSPxCON2bits.RSEN); } void i2cm_stop(void) { i2cm_idle(); SSPxCON2bits.PEN = 1; while (SSPxCON2bits.PEN); } void i2cm_ack(void) { i2cm_idle(); SSPxIF = 0; SSPxCON2bits.ACKDT = 0; SSPxCON2bits.ACKEN = 1; while (!SSPxIF); } void i2cm_nack(void) { i2cm_idle(); SSPxIF = 0; SSPxCON2bits.ACKDT = 1; SSPxCON2bits.ACKEN = 1; while (!SSPxIF); } /*--------------------------------------*/ unsigned char i2cm_readchar(void) { i2cm_idle(); SSPxCON2bits.RCEN = 1; while( !i2cm_drdy() ); return ( SSPxBUF ); } char i2cm_readstr(_I2CPARAM_SPEC unsigned char *ptr, unsigned char len) { unsigned char count=0; while( len-- ) { *ptr++ = i2cm_readchar(); while(SSPxCON2bits.RCEN) { if(BCLxIF)return (-1); count++; if(len) { i2cm_ack(); while(SSPxCON2bits.ACKEN); } } } return count; } char i2cm_writechar(unsigned char dat) { SSPxCON1bits.WCOL = 0; SSPxBUF = dat; if( SSPxCON1bits.WCOL ) { return -1; } else { i2cm_idle(); return 0; } } char i2cm_writestr(unsigned char *ptr) { while( *ptr ) { if( SSPxCON1bits.SSPM3 ) { if(i2cm_writechar( *ptr )) { return (-3); } i2cm_idle(); if( SSPxCON2bits.ACKSTAT ) { return (-2); } } else { SSPxIF = 0; SSPxBUF = *ptr; SSPxCON1bits.CKP = 1; while( !SSPxIF ); if((!SSPxSTATbits.R_W) && ( !SSPxSTATbits.BF )) { return (-2); } } ptr++; } return 0; } /*--------------------------------------*/ void i2cm_begin(unsigned char address, unsigned char doread) { i2cm_start(); i2cm_writechar( (address<<1) | (doread != 0) ); }