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

Discussion in 'Embedded Systems and Microcontrollers' started by gargoor, Jun 30, 2015.

  1. gargoor

    Thread Starter New Member

    Jan 5, 2009
    6
    0
    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 (Text):
    1.  
    2. #include <xc.h>
    3. #include <i2c.h>
    4. #include <delays.h>
    5. #include <p18f2580.h>
    6. #include <stdio.h>
    7. #include <stdlib.h>
    8.  
    9. //Set configuratie bits
    10. #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
    11. #pragma config WDT = OFF          // Watchdog Timer disabled
    12. #pragma config LVP = OFF          // Low Voltage ICSP disabled
    13.  
    14. #define WRITE 0xFE        // bitmask for writes
    15. #define READ 0x01        // bitmask for reads
    16.  
    17. //Define MCP23008 Multiplexer to LEds
    18. // Microchip MCP23008 8?bit I/O Expander
    19. #define MCP23008_ADDR 0x40 // MCP23008 Device Identifier
    20. #define IODIR 0x00 // MCP23008 I/O Direction Register set as output
    21. #define GPIO 0x09 // MCP23008 General Purpose I/O Register
    22. //#define OLAT 0x0A // MCP23008 Output Latch Register
    23.  
    24.  
    25.  
    26. void main(void)
    27. {
    28.  
    29.     CloseI2C(); // close if was opened
    30.     SSPCON1 = 0x28; //0010 1000// Enable SDA and SCL, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
    31.     SSPCON2 = 0x00; // Reset MSSP Control Register
    32.     SSPADD =  39; // 31, I2C Preload Clock 100kHz by 48MHz...Standard I2C Clock speed: 100 kHz
    33.     // SSPAD=( Fosc/(4*I^C*clock) ) -1 For 20 MHz, the value is 49, for 40 MHz the value is 9
    34. //    SSPCON1bits.SSPEN = 1;
    35.   //    SSPSTAT = 0x80;
    36.     TRISCbits.TRISC3=1; //SDA
    37.     TRISCbits.TRISC4=1; //SLK
    38.  
    39.     OpenI2C(MASTER, SLEW_OFF); //init i2c SLEW_OFF= SSPSTAT=0x80
    40.     Delay1KTCYx(550); // 1000 * 550 * (1/12) us = 50ms
    41.     StartI2C(); //give start I2C
    42.     // while(SSPCON2bits.SEN);//wait until start condition passes ---> this line is already defined and included in StartI2C4
    43.     WriteI2C(MCP23008_ADDR & WRITE); //mcp23008 device opcode adres 0x40 + write
    44.     WriteI2C(IODIR); //access mcp23008 register address 0 (IODIR) I/O register
    45.     WriteI2C(0x00); //all IO pin's as output
    46.     StopI2C();
    47.     CloseI2C(); // close if was opened
    48.  
    49.     while(1)
    50.     {
    51.          Delay1KTCYx(550); // 1000 * 550 * (1/12) us = 50ms
    52.          StartI2C();
    53.          WriteI2C(MCP23008_ADDR & WRITE); //mcp23008 device opcode adres 0x40
    54.         //while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slav
    55.         WriteI2C(GPIO); //access mcp23008 register address 9 (GPIO) to read or write
    56.         //while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slave
    57.         WriteI2C(0xFF); //All GPIO output are set to high
    58.         StopI2C(); //SSPCON2bits.PEN = 1;            // initiate bus stop condition
    59.         CloseI2C();
    60.     }
    61. }
    62.  
    63. /*
    64. // Enable Receive Mode
    65. SSPCON2bits.RCEN = 1; // Enable master for 1 byte reception
    66. while(!SSPSTATbits.BF); // Wait until buffer is full
    67. return(SSPBUF);*/
    68.  

    1.jpg pic.jpg 2.jpg
     
  2. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    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.
     
  3. gargoor

    Thread Starter New Member

    Jan 5, 2009
    6
    0
    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 (Text):
    1. void CloseI2C( void )
    2. {
    3.   SSPCON1 &= 0xDF;                // disable synchronous serial port
    4. }
    5.  
    OpenI2C
    Code (Text):
    1. void OpenI2C( unsigned char sync_mode, unsigned char slew )
    2. {
    3.   SSPSTAT &= 0x3F;                // power on state
    4.   SSPCON1 = 0x00;                 // power on state
    5.   SSPCON2 = 0x00;                 // power on state
    6.   SSPCON1 |= sync_mode;           // select serial mode
    7.   SSPSTAT |= slew;                // slew rate on/off
    8.  
    9.   I2C_SCL = 1;
    10.   I2C_SDA = 1;
    11.   SSPCON1 |= SSPENB;              // enable synchronous serial port
    12.  
    13. }
    I2CStart();
    Code (Text):
    1.  
    2.      SSPCON2bits.SEN=1;
    3.      while(SSPCON2bits.SEN); //wait until start condition clears to allow data transmittion
    Here is the modified code
    Code (Text):
    1. //compiler XC8
    2.  
    3. #include <xc.h>
    4. #include <i2c.h>
    5. #include <delays.h>
    6. #include <p18f2580.h>
    7. #include <stdio.h>
    8. #include <stdlib.h>
    9.  
    10. //Set configuratie bits
    11. #pragma config OSC = HS         // HS oscillator, 22pF, 16MHz, P29 Table 3-1
    12. #pragma config WDT = OFF          // Watchdog Timer disabled
    13. #pragma config LVP = OFF          // Low Voltage ICSP disabled
    14.  
    15. #define WRITE 0xFE        // bitmask for writes
    16. #define READ 0x01        // bitmask for reads
    17. //#define I2C_IO_V5       // TRISC=24; I2C pins
    18.  
    19.  
    20. // Microchip MCP23008 8?bit I/O Expander
    21. #define MCP23008_ADDR 0x40 // MCP23008 Device Identifier
    22. #define IODIR 0x00 // MCP23008 I/O Direction Register set as output
    23. #define GPIO 0x09 // MCP23008 General Purpose I/O Register
    24. //#define OLAT 0x0A // MCP23008 Output Latch Register
    25.  
    26. void main(void)
    27. {
    28.  
    29.     CloseI2C(); // close if was opened
    30.  
    31.     SSPADD =  39; // 31, I2C Preload Clock 100kHz by 48MHz...Standard I2C Clock speed: 100 kHz
    32.     // SSPAD=( Fosc/(4*I^C*clock) ) -1 For 20 MHz, the value is 49, for 40 MHz the value is 9
    33.  
    34.     TRISCbits.TRISC3=1; //SDA
    35.     TRISCbits.TRISC4=1; //SLK
    36.    
    37.     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
    38.     Delay10TCYx(12); // 10 * 12 * (1/12) us = 10us --> time for counter to count based on baud rate 100kHz
    39.     StartI2C();
    40.     WriteI2C(MCP23008_ADDR);// & WRITE); //mcp23008 device opcode adres 0x40 + write
    41.     WriteI2C(IODIR); //access mcp23008 register address 0 (IODIR) I/O register
    42.     WriteI2C(0x00); //all IO pin's as output
    43.     StopI2C();
    44.     CloseI2C(); // close if was opened
    45.    
    46.     while(1)
    47.    {
    48.    
    49.          Delay10TCYx(12); // 1000 * 550 * (1/12) us = 50ms
    50.          StartI2C();
    51.         WriteI2C(MCP23008_ADDR & WRITE); //mcp23008 device opcode adres 0x40
    52.   //  while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slav
    53.          WriteI2C(GPIO); //access mcp23008 register address 9 (  GPIO) to read or write
    54.    // while(SSPCON2bits.ACKSTAT==1); // wait till ACK was received from slave
    55.     //can you combine the previous function with this ? what happens after transmitting first 8 bits
    56.          WriteI2C(0x00); //All GPIO output
    57.          StopI2C(); //SSPCON2bits.PEN = 1;            // initiate bus stop condition
    58.          CloseI2C();
    59.     }
    60. }
     
Loading...