Si tu veux j'ai une librairie pour l'i2C en langage C pour un 18F4550
Voila le .c
#include <p18F4550.h>
#include "i2c.h"
#include "LCD_I2C.h"
#include "delays.h"
#define vitesse_I2C 400000 // I2C a 100Khz (pas touche...)
#define FOSC 48000000 // microcontroleur à 48 Mhz
#define v (FOSC/4*vitesse_I2C)-1
//-------------------------------------------------------------------------------------------------------------------------
// Définition et initialisation des variables de type structuré "I2C_CONTROL"
I2C_CONTROL GYRO_EEPROM = {Gyro_EEaddr, Gyro_EEaddr<<1, (Gyro_EEaddr<<1)|1 };
I2C_CONTROL GYRO_MG1101 = {Gyro_MG1101addr, Gyro_MG1101addr<<1, (Gyro_MG1101addr<<1)|1 };
void Init_I2C(void)
{
SSPSTAT &= 0x3F; // power on state
SSPCON1 = 0x00; // power on state
SSPCON2 = 0x00; // power on state
SSPCON1 |= SLAVE_7; // select serial mode
SSPSTAT |= 0; // slew rate on/off
DDRBbits.RB1 = 1; // Set SCL (PORTB,1) pin to input
DDRBbits.RB0 = 1; // Set SDA (PORTB,0) pin to input
SSPCON1 |= SSPENB; // enable synchronous serial port
SSPADD = 0x20<<1; // slave address
SSPCON1bits.CKP = 1; // no clock
PIE1bits.SSPIE = 1; // autorisation de l'interruption de l'i2c
IPR1bits.SSPIP = 0; // I2C en basse priorité
PIR1bits.SSPIF = 0; // on déactive le bit SSPIF pour permettre a l'interruption d'avoir lieu
}
/*********************************************************************/
#undef StartI2C
void StartI2C( void )
{
SSPCON2bits.SEN = 1; // initiate bus start condition
}
/*******************************************************************/
#undef IdleI2C
void IdleI2C( void )
{
while ( ( SSPCON2 & 0x1F ) | ( SSPSTATbits.R_W ) )
continue;
}
/*******************************************************************/
signed char putsI2C( unsigned char *wrptr )
{
while ( *wrptr ) // transmit data until null character
{
if ( SSPCON1bits.SSPM3 ) // if Master transmitter then execute the following
{
if ( putcI2C ( *wrptr ) ) // write 1 byte
{
return ( -3 ); // return with write collision error
}
IdleI2C(); // test for idle condition
if ( SSPCON2bits.ACKSTAT ) // test received ack bit state
{
return ( -2 ); // bus device responded with NOT ACK
} // terminate putsI2C() function
}
else // else Slave transmitter
{
PIR1bits.SSPIF = 0; // reset SSPIF bit
SSPBUF = *wrptr; // load SSPBUF with new data
SSPCON1bits.CKP = 1; // release clock line
while ( !PIR1bits.SSPIF ); // wait until ninth clock pulse received
if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
{
return ( -2 ); // terminate PutsI2C() function
}
}
wrptr ++; // increment pointer
} // continue data writes until null character
return ( 0 );
}
/*******************************************************************/
unsigned char ReadI2C( void )
{
SSPCON2bits.RCEN = 1; // enable master for 1 byte reception
while ( !SSPSTATbits.BF ); // wait until byte received
return ( SSPBUF ); // return with read byte
}
/*******************************************************************/
#undef StopI2C
void StopI2C( void )
{
SSPCON2bits.PEN = 1; // initiate bus stop condition
}
/*******************************************************************/
#undef AckI2C
void AckI2C( void )
{
SSPCON2bits.ACKDT = 0; // set acknowledge bit state for ACK
SSPCON2bits.ACKEN = 1; // initiate bus acknowledge sequence
}
//////////////////////////////////
unsigned char TestAck()
{
if ( !SSPCON2bits.ACKSTAT ) // test la condition ACK=0
return I2C_SUCCESS; // retourne avec pas d'erreur sur le bit acknowledge ACKSTAT
else
return I2C_ERROR; // retourne avec erreur sur le bit acknowledge ACKSTAT
}
/*******************************************************************/
unsigned char WriteI2C( unsigned char data_out )
{
SSPBUF = data_out; // write single byte to SSPBUF
if ( SSPCON1bits.WCOL ) // test if write collision occurred
return ( -1 ); // if WCOL bit is set return negative #
else
{
while( SSPSTATbits.BF ); // wait until write cycle is complete
return ( 0 ); // if WCOL bit is not set return non-negative #
}
}
char EMByteWrite( unsigned char *pTxData, unsigned short Length )
{
int ii;
IdleI2C(); // ensure module is idle
StartI2C(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
else // start condition successful
{
if ( WriteI2C( *pTxData ) ) // write byte - R/W bit should be 0
{
return ( -3 ); // set error for write collision
}
pTxData++;
for( ii = 1; ii<Length; ii++ )
{
IdleI2C(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
// PORTB|=0b00001100;
if ( WriteI2C( *pTxData ) ) // write word address for EEPROM
{
// PORTB&=0b11111011;
return ( -3 ); // set error for write collision
}
pTxData++;
}
else
{
// PORTB|=0b00000001;
return ( -2 ); // return with Not Ack error condition
ii=Length;
}
}
IdleI2C(); // ensure module is idle
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
return ( 0 ); // return with no error
}
}
unsigned char PageRead( unsigned char control, unsigned char address, unsigned char *rdptr, unsigned char length )
{
unsigned char status;
IdleI2C(); // ensure module is idle
StartI2C(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
WriteI2C( control<<1 ); // write 1 byte
IdleI2C();
status = TestAck(); // ensure module is idle
if( status == I2C_SUCCESS )
{
WriteI2C( address ); //The register memory address (used to address the 16 bytes in MG1101 RAM)
// is internally incremented following the receipt of each data word.
IdleI2C();
status = TestAck();
if( status == I2C_SUCCESS )
{
RestartI2C(); // generate I2C bus restart condition
while ( SSPCON2bits.RSEN ); // wait until re-start condition is over
WriteI2C( (control<<1) | 1 );// WRITE 1 byte - R/W bit should be 1 for read
IdleI2C();
status = TestAck();
if( status == I2C_SUCCESS )
{
while ( length )
{
*rdptr++ = ReadI2C(); // save byte received
length--;
if(length)
AckI2C();
else
NotAckI2C();
while ( SSPCON2bits.ACKEN ); // wait until ACK sequence is over
}
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN );// wait until stop condition is over
}
}
}
return status;
}
unsigned char PageWrite( unsigned char control, unsigned char address, unsigned char *pData, unsigned char length ) //EEPageWrite
{
unsigned char addr=0, status;
IdleI2C(); // ensure module is idle
StartI2C(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
WriteI2C( control ); // write 1 byte
IdleI2C();
status = TestAck(); // ensure module is idle
if( status == I2C_SUCCESS )
{
WriteI2C( address ); //The register memory address (used to address the 16 bytes in MG1101 RAM)
// is internally incremented following the receipt of each data word.
IdleI2C();
status = TestAck();
}
while( (status == I2C_SUCCESS) && (addr<length) ) // test for ACK condition, if received
{
WriteI2C( *pData++ );
IdleI2C();
status = TestAck();
addr++;
}
StopI2C(); // réalise une condition de stop sur le bus I2C
while( SSPCON2bits.PEN );
Delay10KTCYx(5); // temps d'attente de 50ms
return status;
}
unsigned char ByteWrite( unsigned char control, unsigned char address, unsigned char data )
{
unsigned char status;
IdleI2C(); // ensure module is idle
StartI2C(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
WriteI2C( control );
IdleI2C();
status = TestAck(); // ensure module is idle
if( status == I2C_SUCCESS )
{
WriteI2C( address ); //The register memory address (used to address the 16 bytes in MG1101 RAM)
// is internally incremented following the receipt of each data word.
IdleI2C();
status = TestAck();
if( status == I2C_SUCCESS )
{
WriteI2C( data );
IdleI2C();
status = TestAck();
}
}
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
Delay10KTCYx(5); // temps d'attente de 50ms
return status;
}
unsigned char ByteRead( unsigned char control, unsigned char address )
{
unsigned char status, data;
IdleI2C(); // ensure module is idle
StartI2C(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
WriteI2C( control<<1 );
IdleI2C();
status = TestAck(); // ensure module is idle
if( status == I2C_SUCCESS )
{
WriteI2C( address ); //The register memory address (used to address the 16 bytes in MG1101 RAM)
// is internally incremented following the receipt of each data word.
IdleI2C();
status = TestAck();
if( status == I2C_SUCCESS )
{
RestartI2C(); // generate I2C bus restart condition
while ( SSPCON2bits.RSEN );// wait until re-start condition
WriteI2C( (control<<1) | 1 );
IdleI2C();
status = TestAck();
if( status == I2C_SUCCESS )
{
data = ReadI2C(); // enable master for 1 byte reception
NotAckI2C(); // send ACK condition
while ( SSPCON2bits.ACKEN ); // wait until ACK sequence is over
}
}
}
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condit
return ( data );
}
Et voila le .h associé
/* PIC18 I2C peripheral library header */
/* SSPCON1 REGISTER */
#define SSPENB 0x20 /* Enable serial port and configures
SCK, SDO, SDI */
#define SLAVE_7 6 /* I2C Slave mode, 7-bit address */
#define SLAVE_10 7 /* I2C Slave mode, 10-bit address */
#define MASTER 8 /* I2C Master mode */
/* SSPSTAT REGISTER */
#define SLEW_OFF 0xC0 /* Slew rate disabled for 100kHz mode */
#define SLEW_ON 0x00 /* Slew rate enabled for 400kHz mode */
//-------------------------------------------------------------------------------------------------------------------------
// Modèle de structure de control I2C
typedef struct
{
unsigned char addr;
unsigned char write;
unsigned char read;
}I2C_CONTROL;
//-------------------------------------------------------------------------------------------------------------------------
// Variables de type structuré importées du fichier "i2c.c"
extern I2C_CONTROL GYRO_EEPROM;
extern I2C_CONTROL GYRO_MG1101;
//-------------------------------------------------------------------------------------------------------------------------
// Adresse des modules I2C
#define Gyro_EEaddr 0b1010000
#define Gyro_MG1101addr 0b1010111
//-------------------------------------------------------------------------------------------------------------------------
// I2C bus states
#define I2C_SUCCESS 1
#define I2C_ERROR 0
#define StopI2C() SSPCON2bits.PEN=1
#define StartI2C() SSPCON2bits.SEN=1
#define RestartI2C() SSPCON2bits.RSEN=1
#define NotAckI2C() SSPCON2bits.ACKDT=1, SSPCON2bits.ACKEN=1
#define AckI2C() SSPCON2bits.ACKDT=0, SSPCON2bits.ACKEN=1
#define IdleI2C() while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W))
#define CloseI2C() SSPCON1 &=0xDF
#define DataRdyI2C() (SSPSTATbits.BF)
#define getcI2C ReadI2C
#define putcI2C WriteI2C
void Init_I2C(void);
unsigned char WriteI2C( unsigned char data_out );
unsigned char ReadI2C( void );
unsigned char TestAck( void );
unsigned char ByteWrite( unsigned char control, unsigned char address, unsigned char data );
unsigned char ByteRead( unsigned char control, unsigned char address );
unsigned char PageWrite( unsigned char control, unsigned char address, unsigned char *pData, unsigned char length );
unsigned char PageRead( unsigned char control, unsigned char address, unsigned char *rdptr, unsigned char length );
Ça date méchamment... De mémoire ce protocole est assez pénible à faire marcher. Regarde au moins la méthode d'initialisation celle la elle fonctionne c'est sur.