• AVR Freaks

LockedI2C Master/Slave Example using PIC18 C

Author
Guest
Super Member
  • Total Posts : 80500
  • Reward points : 0
  • Joined: 2003/01/01 00:00:00
  • Location: 0
  • Status: online
2004/04/27 10:21:31 (permalink)
0

I2C Master/Slave Example using PIC18 C

Hello,

Does anyone have a working example using two PIC18XXX devices connected via the I2C bus, with one configured as an I2C Master and the other configured as an I2C Slave? Ideally it would use the MSSP hardware to emulate a 24LC01 Serial EEPROM using an interrupt service routine (ISR) for the slave, similar to the AN734 application that is written in PIC18 C.

Regards,

Daniel
#1

5 Replies Related Threads

    Guest
    Super Member
    • Total Posts : 80500
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: I2C Master/Slave Example using PIC18 C 2004/04/28 10:19:37 (permalink)
    0
    maybe this can help you:

    master:



    #include <p18f2220.h>
    #include <i2c.h>
    #include <delays.h>
    #include <portb.h>
    #include <timers.h>


    #pragma romdata CONFIG
    _CONFIG_DECL(0x39,0xFD,0xEC,0xFD,0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
    #pragma romdata

    #define SLAVE_ADD1_W 0x40 // R/W bit en 0 (escritura);
    #define SLAVE_ADD1_R 0x41 // R/W bit en 1 (lectura);
    #define SLAVE_ADD2_W 0x70 // R/W bit en 0 (escritura);
    #define SLAVE_ADD2_R 0x71 // R/W bit en 1 (lectura);
    #define SLAVE_PIC 0x02 //

    int EscribirBI2C(char Address,char Data);
    unsigned int LeerBI2C(char Address);
    void delayms(int tiempo );

    void main ()
    {
    OSCCON = 0x7F; // Frecuencia Oscilador: 8MHz
    // OSCTUNE = 0x02; // Calibracion del oscilador
    ADCON1 = 0xFF; // Deshabilita las entradas analogas

    LATA = 0; LATB = 0; LATC = 0;

    TRISA = 0xFF; // Puerto A todo como entrada
    TRISB = 0x0; // Puerto B todo como salida
    TRISC = 0xFF; // Puerto C todo como entrada

    DDRCbits.RC3 = 1; // Set SCL (PORTC,3) pin to input
    DDRCbits.RC4 = 1; // Set SDA (PORTC,4) pin to input


    OpenI2C(MASTER, SLEW_OFF); // Clock = FOSC/(4 * (SSPADD + 1))
    SSPADD = 19; // 100 KHz = 8E6/4*20 = 100 KHz.

    while(1)
    {

    EscribirBI2C ( SLAVE_ADD1_W , 0xAA );
    PORTBbits.RB0 = 1;
    delayms( 1000 );

    EscribirBI2C ( SLAVE_ADD1_W , 0x55 );
    PORTBbits.RB0 = 0;
    delayms( 1000 );


    EscribirBI2C ( SLAVE_ADD2_W , 0xAA );
    PORTBbits.RB0 = 1;
    delayms( 1000 );

    EscribirBI2C ( SLAVE_ADD2_W , 0x55 );
    PORTBbits.RB0 = 0;
    delayms( 1000 );



    EscribirBI2C ( SLAVE_PIC, 0xAA );
    PORTBbits.RB0 = 1;
    PORTBbits.RB1 = 1;
    delayms( 1000 );

    EscribirBI2C ( SLAVE_PIC, 0x55 );
    PORTBbits.RB0 = 0;
    PORTBbits.RB1 = 0;
    delayms( 1000 );


    }
    }

    //*************************************************************************************
    // Descripcion de las funciones de I2C
    // EscribirBI2C: Escribe un byte a un esclavo y retorna con codigos de error, si los hubo
    // LeerBI2C: retorna con un byte leido desde un esclavo
    //***************************************************************************************
    int EscribirBI2C(char Address, char Data) // Escribe un byte a un esclavo en I2C
    {
    IdleI2C(); // ensure module is idle
    StartI2C(); // initiate START condition
    while ( SSPCON2bits.SEN ); // wait until start condition is over
    WriteI2C( Address ); // Selecciona el dispositivo esclavo
    IdleI2C(); // Asegura que el modulo este desocupado
    if ( SSPCON2bits.ACKSTAT ) // Prueba por la condicion de ACK, si es recibida
    {
    StopI2C(); // send STOP condition
    while ( SSPCON2bits.PEN ); // wait until stop condition is over
    return 1;
    }

    WriteI2C( Data ); // Escribe un byte de datos al esclavo
    IdleI2C(); // ensure module is idle
    StopI2C(); // send STOP condition
    while ( SSPCON2bits.PEN ); // wait until stop condition is over
    return 0;
    }
    // ****************************************************************************
    unsigned int LeerBI2C(char Address) // Escribe un byte a un esclavo en I2C
    {
    char DATA_I2C;
    IdleI2C(); // ensure module is idle
    StartI2C(); // initiate START condition
    while ( SSPCON2bits.SEN ); // wait until start condition is over
    WriteI2C( Address ); // Selecciona el dispositivo esclavo
    IdleI2C(); // Asegura que el modulo este desocupado
    if ( !SSPCON2bits.ACKSTAT ) // Prueba por la condicion de ACK, si es recibida
    {
    DATA_I2C = ReadI2C();
    IdleI2C(); // ensure module is idle
    StopI2C(); // send STOP condition
    while ( SSPCON2bits.PEN ); // wait until stop condition is over
    }
    return DATA_I2C;
    }
    //***********************************************************************************

    void delayms(int tiempo) // delays en ms a 8MHz
    {
    int cuenta_ = 0;
    while ( cuenta_ < tiempo )
    {

    Delay1KTCYx(2);
    cuenta_++;
    }
    }




    slave:

    [code]

    #include <p18f2220.h>
    #include <sw_i2c.h>
    #include <delays.h>
    #include <i2c.h>
    #include <timers.h>


    #pragma romdata CONFIG
    _CONFIG_DECL(0x39,0xFD,0xEC,0xFD,0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
    #pragma romdata

    #define SLAVE_PIC 0x02

    // FUNCTION Prototype
    void InterruptVectorHigh ( void );
    void InterruptHandlerHigh ( void );
    void delayms( unsigned int tiempo );

    unsigned char IntF = 0;

    unsigned char mivar1, mivar2;

    void main ()
    {
    OSCCON = 0x7F;
    ADCON1 = 0xFF; // Deshabilita las entradas analogas.

    LATA = 0; LATB = 0; LATC = 0;

    TRISA = 0xFF; // Puerto A todo como salida.
    TRISB = 0x0; // Puerto B todo como salida.
    TRISC = 0xFF; // Puerto C todo como entrada.

    // Configuracion del moudulo SSP como I2C en modo esclavo con 7 bits de direccion

    SSPCON1 = 0x36; // Modo esclavo 7 bits de direccion.
    SSPCON2 = 0x00; //
    SSPADD = SLAVE_PIC; //

    DDRCbits.RC3 = 1; // Set SCL (PORTC,3) pin to input
    DDRCbits.RC4 = 1; // Set SDA (PORTC,4) pin to input

    SSPCON1bits.SSPEN = 1;

    SSPSTATbits.SMP = 1; //
    SSPSTATbits.CKE = 1; //
    PIR1bits.SSPIF = 0; //

    // OpenTimer2( TIMER_INT_ON & T2_PS_1_16 & T2_POST_1_16 );

    // Configuracion de las interrupciones.
    PIE1bits.SSPIE = 1; // Habilita la interrupcion del modulo SSP
    INTCONbits.PEIE = 1; // Habilita las interrupciones de los perifericos
    INTCONbits.GIE = 1; // Habilita las interrupciones globales!

    while(1)
    {
    if( IntF )
    {
    if( mivar2 == 0xAA )
    PORTBbits.RB0 = !PORTBbits.RB0;

    if( mivar2 == 0x55 )
    PORTBbits.RB1 = !PORTBbits.RB1;

    IntF = 0;
    }
    }
    }

    // Vector de interrupcion de Alta Prioridad

    #pragma code InterruptVectorHigh = 0x08
    void InterruptVectorHigh ()
    {
    _asm goto InterruptHandlerHigh _endasm
    }

    //----------------------------------------------------------------------------
    // Rutina de interrupion para el vector de Alta Prioridad

    #pragma code
    #pragma interrupt InterruptHandlerHigh
    void InterruptHandlerHigh ()
    {
    if( PIR1bits.TMR2IF )
    {
    // PORTBbits.RB1 = !PORTBbits.RB1;
    PIR1bits.TMR2IF = 0;
    }

    if( PIR1bits.SSPIF )
    {
    if( !SSPSTATbits.R_W & !SSPSTATbits.D_A & SSPSTATbits.BF )
    mivar1 = SSPBUF;
    PIR1bits.SSPIF = 0;

    if( !SSPSTATbits.R_W & SSPSTATbits.D_A & SSPSTATbits.BF )
    mivar2 = SSPBUF;
    PIR1bits.SSPIF = 0;

    IntF = 1;

    }
    }

    //----------------------------------------------------------------------------

    void delayms(unsigned int tiempo) // delays en ms a 8MHz
    {
    int cuenta_s = 0;
    while ( cuenta_s < tiempo )
    {

    Delay1KTCYx(2);
    cuenta_s++;
    }
    }
    #2
    Guest
    Super Member
    • Total Posts : 80500
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: I2C Master/Slave Example using PIC18 C 2004/04/30 05:54:03 (permalink)
    0
    Hi marcos7,

    Thank you for the I2C example, I will try it out soon. Could you tell me what values you used for the two I2C pull-up resistors?

    Regards,

    Daniel
    #3
    Guest
    Super Member
    • Total Posts : 80500
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: I2C Master/Slave Example using PIC18 C 2004/05/03 00:21:43 (permalink)
    0
    Hi,
    Pull-up resistors from 4K7 to 10K are common and safe.

    Vito.
    #4
    Olin Lathrop
    Super Member
    • Total Posts : 7463
    • Reward points : 0
    • Joined: 2004/02/26 17:59:01
    • Location: Littleton Massachusetts
    • Status: offline
    RE: I2C Master/Slave Example using PIC18 C 2004/05/03 06:28:37 (permalink)
    0
    Pull-up resistors from 4K7 to 10K are common and safe.


    Those will work at low speeds. Unless power is a big issue, I prefer to get the pullup current to near its maximum of 3mA. That's about 1.8Kohm pullups to +5V.
    #5
    Guest
    Super Member
    • Total Posts : 80500
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: I2C Master/Slave Example using PIC18 C 2004/05/03 06:54:51 (permalink)
    0
    He he, it's sort of fun...

    I used to seamlessly put 1K to 10K resistors until someone in this forum (maybe you Olin?) recalled me about the max. current in the I2C spec.

    Vito.
    #6
    Jump to:
    © 2019 APG vNext Commercial Version 4.5