PIC18f, I2C, 8bit I/O expander MCP23008 output to LEDS

Thread Starter

gargoor

Joined Jan 5, 2009
6
Ladies and Gents,

In between my hand are the following (also see images below) :
- PIC18f2580, Pickit2
- PICKkit Serial I2C Demo board (using 8bit I/O Expander MCP23008) input two wires I2C and outputed to 8 leds
- MPLABX, COMPILER : xC8

I got the code well written (in my opinion) based on my studies of PIC18f datasheet and MCP23008... I can't figure why the leds aren't getting lit. I tested SDA and SDL on oscilloscope and they are constant 5v.
Am I missing anything in the code? or is the expander burnt ? , or maybe I'm not generating a clock ?
I would appreciate your comments


Code:
#include <xc.h>
#include <i2c.h>
#include <delays.h>
#include <p18f2580.h>
#include <stdio.h>
#include <stdlib.h>

//Set configuratie bits
#pragma config OSC = HS         // HS oscillator, at C3 and C4= 22pF, crystal written on it 20MHz but I assume its 16MHz, P29 Table 3-1
#pragma config WDT = OFF          // Watchdog Timer disabled
#pragma config LVP = OFF          // Low Voltage ICSP disabled

#define WRITE 0xFE        // bitmask for writes
#define READ 0x01        // bitmask for reads

//Define MCP23008 Multiplexer to LEds
// Microchip MCP23008 8?bit I/O Expander
#define MCP23008_ADDR 0x40 // MCP23008 Device Identifier
#define IODIR 0x00 // MCP23008 I/O Direction Register set as output
#define GPIO 0x09 // MCP23008 General Purpose I/O Register
//#define OLAT 0x0A // MCP23008 Output Latch Register

  

void main(void)
{

    CloseI2C(); // close if was opened
    SSPCON1 = 0x28; //0010 1000// Enable SDA and SCL, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
    SSPCON2 = 0x00; // Reset MSSP Control Register
    SSPADD =  39; // 31, I2C Preload Clock 100kHz by 48MHz...Standard I2C Clock speed: 100 kHz
    // SSPAD=( Fosc/(4*I^C*clock) ) -1 For 20 MHz, the value is 49, for 40 MHz the value is 9
//    SSPCON1bits.SSPEN = 1;
  //    SSPSTAT = 0x80;
    TRISCbits.TRISC3=1; //SDA
    TRISCbits.TRISC4=1; //SLK
  
    OpenI2C(MASTER, SLEW_OFF); //init i2c SLEW_OFF= SSPSTAT=0x80
    Delay1KTCYx(550); // 1000 * 550 * (1/12) us = 50ms
    StartI2C(); //give start I2C
    // while(SSPCON2bits.SEN);//wait until start condition passes ---> this line is already defined and included in StartI2C4
    WriteI2C(MCP23008_ADDR & WRITE); //mcp23008 device opcode adres 0x40 + write
    WriteI2C(IODIR); //access mcp23008 register address 0 (IODIR) I/O register
    WriteI2C(0x00); //all IO pin's as output
    StopI2C();
    CloseI2C(); // close if was opened
  
    while(1)
    {
         Delay1KTCYx(550); // 1000 * 550 * (1/12) us = 50ms
         StartI2C();
         WriteI2C(MCP23008_ADDR & WRITE); //mcp23008 device opcode adres 0x40
        //while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slav
        WriteI2C(GPIO); //access mcp23008 register address 9 (GPIO) to read or write
        //while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slave
        WriteI2C(0xFF); //All GPIO output are set to high
        StopI2C(); //SSPCON2bits.PEN = 1;            // initiate bus stop condition
        CloseI2C();
    }
}

/*
// Enable Receive Mode
SSPCON2bits.RCEN = 1; // Enable master for 1 byte reception
while(!SSPSTATbits.BF); // Wait until buffer is full
return(SSPBUF);*/

1.jpg pic.jpg 2.jpg
 

tshuck

Joined Oct 18, 2012
3,534
Have you gone through the basic debugging steps? Is the processor doing anything?

If you have, try the following:
  • Try a check to see if WCOL is getting set on your first write to SSPBUF, the datasheets l datasheet makes note of this on page 213.
  • Set the TRISC<3:4> bits before configuring the MSSP for I2C.
  • Verify you have appropriate pull up resistors on SDA and SCK.
This is why I don't use the compiler functions, it makes it hard to see what they're doing to debug.
 

Thread Starter

gargoor

Joined Jan 5, 2009
6
Have you gone through the basic debugging steps? Is the processor doing anything?

If you have, try the following:
  • Try a check to see if WCOL is getting set on your first write to SSPBUF, the datasheets l datasheet makes note of this on page 213.
  • Set the TRISC<3:4> bits before configuring the MSSP for I2C.
  • Verify you have appropriate pull up resistors on SDA and SCK.
This is why I don't use the compiler functions, it makes it hard to see what they're doing to debug.
I just started debugging after the post. First time I do it... not so handy with it ... The debugger gets stuck in StartI2C() function (using step into), meaning that SDA isn't pulled low for start bit! --> as the oscilloscope shows

TRISCC<3:4> is set in the code I had, and also set in function OpenI2C , ...... WCOL condition is included in WriteI2C. Following is description of the first few functions

I was pretty desperate, I connected the board to Arduino... Yet no results.. I think the chip is burnt. Is there a way to test it ?

CloseI2C();
Code:
void CloseI2C( void )
{
  SSPCON1 &= 0xDF;                // disable synchronous serial port
}
OpenI2C
Code:
void OpenI2C( unsigned char sync_mode, unsigned char slew )
{
  SSPSTAT &= 0x3F;                // power on state
  SSPCON1 = 0x00;                 // power on state
  SSPCON2 = 0x00;                 // power on state
  SSPCON1 |= sync_mode;           // select serial mode
  SSPSTAT |= slew;                // slew rate on/off

  I2C_SCL = 1;
  I2C_SDA = 1;
  SSPCON1 |= SSPENB;              // enable synchronous serial port

}
I2CStart();
Code:
     SSPCON2bits.SEN=1;
     while(SSPCON2bits.SEN); //wait until start condition clears to allow data transmittion
Here is the modified code
Code:
//compiler XC8

#include <xc.h>
#include <i2c.h>
#include <delays.h>
#include <p18f2580.h>
#include <stdio.h>
#include <stdlib.h>

//Set configuratie bits
#pragma config OSC = HS         // HS oscillator, 22pF, 16MHz, P29 Table 3-1
#pragma config WDT = OFF          // Watchdog Timer disabled
#pragma config LVP = OFF          // Low Voltage ICSP disabled

#define WRITE 0xFE        // bitmask for writes
#define READ 0x01        // bitmask for reads
//#define I2C_IO_V5       // TRISC=24; I2C pins


// Microchip MCP23008 8?bit I/O Expander
#define MCP23008_ADDR 0x40 // MCP23008 Device Identifier
#define IODIR 0x00 // MCP23008 I/O Direction Register set as output
#define GPIO 0x09 // MCP23008 General Purpose I/O Register
//#define OLAT 0x0A // MCP23008 Output Latch Register

void main(void)
{

    CloseI2C(); // close if was opened
  
    SSPADD =  39; // 31, I2C Preload Clock 100kHz by 48MHz...Standard I2C Clock speed: 100 kHz
    // SSPAD=( Fosc/(4*I^C*clock) ) -1 For 20 MHz, the value is 49, for 40 MHz the value is 9

    TRISCbits.TRISC3=1; //SDA
    TRISCbits.TRISC4=1; //SLK
   
    OpenI2C(MASTER, SLEW_OFF); //init i2c SLEW_OFF= SSPSTAT=0x80  SSPCON1 = 0x28; //0010 1000// Enable SDA and SCL, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))     SSPCON2 = 0x00; // Reset MSSP Control Register
    Delay10TCYx(12); // 10 * 12 * (1/12) us = 10us --> time for counter to count based on baud rate 100kHz
    StartI2C();
    WriteI2C(MCP23008_ADDR);// & WRITE); //mcp23008 device opcode adres 0x40 + write
    WriteI2C(IODIR); //access mcp23008 register address 0 (IODIR) I/O register
    WriteI2C(0x00); //all IO pin's as output
    StopI2C();
    CloseI2C(); // close if was opened
   
    while(1)
   {
    
         Delay10TCYx(12); // 1000 * 550 * (1/12) us = 50ms
         StartI2C();
        WriteI2C(MCP23008_ADDR & WRITE); //mcp23008 device opcode adres 0x40
  //  while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slav
         WriteI2C(GPIO); //access mcp23008 register address 9 (  GPIO) to read or write
   // while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slave
    //can you combine the previous function with this ? what happens after transmitting first 8 bits
         WriteI2C(0x00); //All GPIO output
         StopI2C(); //SSPCON2bits.PEN = 1;            // initiate bus stop condition
         CloseI2C();
    }
}
 
Top