I am currently testing the MCP23017 (slave device) 16 bit I/O Expander using a PIC18F45K20 with the C18 compiler to transmit data to the MCP23017. The address pins (A0, A1 and A2) of the MCP23017 are grounded. The serial clock (SCL) is running at 100kHz.
I've checked my program code from head to toe and I couldn't find any problem from my code even though it was compiled without error.
The problems I faced are:
The MCP23017 does not output the data transmitted from the PIC18F45K20 (Program code shown below).
The SCL waveform from PIC18F45K20 is not a square wave. It was measured using an oscilloscope
#include <stdio.h> #include <stdlib.h> #include <delays.h> #include <i2c.h> #include <p18f45k20.h> #include <sw_i2c.h> #define MCP_IODIR_A 0x00 #define MCP_IPOL_A 0x02 #define MCP_OLAT_A 0x14 #define MCP_GPIO_A 0x12 #define MCP_IOCON_A 0x0A #define MCP_GPINTEN_A 0x04 /* * */ //----------------------------Global variable---------------------------- // PIC18F45K20 Configuration Bit Settings // CONFIG1H #pragma config FOSC = INTIO67 // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // CONFIG2L #pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled)) #pragma config BORV = 30 // Brown Out Reset Voltage bits (VBOR set to 3.0 V nominal) // CONFIG2H #pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // CONFIG3H #pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) #pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset) #pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation) #pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.) #pragma config MCLRE = OFF // MCLR Pin Enable bit (RE3 input pin enabled; MCLR disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) // CONFIG5L #pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected) #pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected) #pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected) #pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected) #pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected) #pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected) #pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0(000800-001FFFh) not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks) void init_I2C() { DDRCbits.RC3 = 1; //Configure SCL as input DDRCbits.RC4 = 1; //Configure SDA as input // SSPSTAT Configuration (0x80) SSPSTATbits.SMP = 1; //Slew rate control disabled SSPSTATbits.CKE = 0; //SMBus disabled SSPSTATbits.D_A = 0; //Reserved in master mode SSPSTATbits.P = 0; //Stop bit was not detected last SSPSTATbits.S = 0; //Start bit was not detected last SSPSTATbits.R_W = 0; SSPSTATbits.UA = 0; //Address doesnot need to be updated SSPSTATbits.BF = 0; // SSPCON1 Configuration (0x28) SSPCON1bits.WCOL = 0; SSPCON1bits.SSPOV = 0; SSPCON1bits.SSPEN = 1; //Serial port enabled SSPCON1bits.CKP = 0; //Holds clock low SSPCON1bits.SSPM3 = 1; //1000 = I2C Master mode SSPCON1bits.SSPM2 = 0; //BitRate = FOSC/(4*(SPPADD+1)) SSPCON1bits.SSPM1 = 0; SSPCON1bits.SSPM0 = 0; // SSPADD Configuration SSPADD = 0x27; //should be 0x27 for 100kHz //SSPADD = [(FOSC/BitRate)/4]-1 // SSPCON2 Configuration (0x00) SSPCON2bits.GCEN = 0; //General call address disabled SSPCON2bits.ACKSTAT = 0; //Acknowledge was received from slave SSPCON2bits.ACKDT = 0; //Acknowledge SSPCON2bits.ACKEN = 0; //Acknowledge sequence idle SSPCON2bits.RCEN = 0; //Receive idle SSPCON2bits.PEN = 0; //Stop condition idle SSPCON2bits.RSEN = 0; //Repeated start condition idle SSPCON2bits.SEN = 0; } void MCP_write() { WriteI2C(0x40); } void MCP_read() { WriteI2C(0x41); } void MCP_addr() { StartI2C(); MCP_write(); } void init_MCP() { //IODIR A configuration MCP_addr(); AckI2C(); WriteI2C(MCP_IODIR_A); AckI2C(); WriteI2C(0x00); StopI2C(); //IPOL A configuration MCP_addr(); AckI2C(); WriteI2C(MCP_IPOL_A); AckI2C(); WriteI2C(0x00); StopI2C(); //OLAT A configuration MCP_addr(); AckI2C(); WriteI2C(MCP_OLAT_A); AckI2C(); WriteI2C(0xFF); StopI2C(); //IOCON A configuration MCP_addr(); AckI2C(); WriteI2C(MCP_IOCON_A); AckI2C(); WriteI2C(0x00); StopI2C(); //GPINTEN A configuration MCP_addr(); AckI2C(); WriteI2C(MCP_GPINTEN_A); AckI2C(); WriteI2C(0x00); StopI2C(); } //----------------------------Main program---------------------------- void main(void) { OSCCON = 0x70; //Set internal oscillation to 16 MHz TRISD=0; init_I2C(); //I2C initialization init_MCP(); //MCP23017 initialization while(1) { MCP_addr(); AckI2C(); WriteI2C(MCP_GPIO_A); AckI2C(); WriteI2C(0x11); StopI2C(); } }