PIC18F Trainer - MCP23S08 SPI 8-Bit I/O Expander.

0.Contents

PIC18F Trainer : PIC18F2620 @8MHz Internal oscillator.

1.MCP23S08 Write in Byte Mode.

// Configuration register.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v1.44).
// PIC18F2620 - @8MHz Internal oscillator.

// MCP23S08 - 8-bit I/O Expander - Write in Byte Mode.

// PIC18F Trainer Jumpers.
// JP1 - SCL Open.
// JP2 - SDA Open.
// JP3 - VEE Open.
// JP4 - BCKL Not use.

// Definitions.
// SPI Port.
#define SPI_CS					LATAbits.LATA5
#define SPI_CS_TRIS				TRISAbits.TRISA5
#define SPI_SCK_TRIS			TRISCbits.TRISC3
#define SPI_SDI_TRIS			TRISCbits.TRISC5
// MCP23S08 Port.
#define MCP23S08_RESET_TRIS		TRISAbits.TRISA2
#define MCP23S08_RESET			LATAbits.LATA2
// MCP23S08 Address Select Bits A1 A0.
#define MCP23S08_ADDRESS_40		0x40
#define MCP23S08_ADDRESS_42		0x42
#define MCP23S08_ADDRESS_44		0x44
#define MCP23S08_ADDRESS_46		0x46
#define MCP23S08_WRITE			0x00
#define MCP23S08_READ			0x01
// MCP23S08 Configuration Registers.
#define MCP23S08_IODIR			0x00
#define MCP23S08_IPOL			0x01
#define MCP23S08_GPINTEN		0x02
#define MCP23S08_DEFVAL			0x03
#define MCP23S08_INTCON			0x04
#define MCP23S08_IOCON			0x05
#define MCP23S08_GPPU			0x06
#define MCP23S08_INTF			0x07
#define MCP23S08_INTCAP			0x08
#define MCP23S08_GPIO			0x09
#define MCP23S08_OLAT			0x0A
// MCP23S08 Configuration Bits.
#define MCP23S08_SEQOP			0x20
#define MCP23S08_HAEN			0x08
#define MCP23S08_ODR			0x04
#define MCP23S08_INTPOL			0x02

// Function prototypes.
void mcp23s08_initialize(uint8_t u8Address);
uint8_t mcp23s08_readData(uint8_t u8Address);
void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data);
void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data);
void mcu_initialize(void);
void spi_initializeMaster(void);

// Main.
int main(void)
{
	mcu_initialize();
	spi_initializeMaster();
	mcp23s08_initialize(MCP23S08_ADDRESS_40);
	// Configure MCP23S08 in Byte Mode.
	mcp23s08_writeRegister(MCP23S08_ADDRESS_40, MCP23S08_IOCON, MCP23S08_SEQOP);

	SPI_CS = 0;
	SSPBUF = (uint8_t)(MCP23S08_ADDRESS_40 | MCP23S08_WRITE);
	while(!SSPSTATbits.BF);
	SSPBUF = MCP23S08_OLAT;
	while(!SSPSTATbits.BF);
	while(1){
		SSPBUF = 0x00;
		while(!SSPSTATbits.BF);
		SSPBUF = 0x01;
		while(!SSPSTATbits.BF);
	}
	return(0);
}

// Functions.
void mcp23s08_initialize(uint8_t u8Address)
{
	MCP23S08_RESET = 1;
	__delay_ms(1);

	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	// IODIR - I/O Direction - 0b11111111 (Default).
	// IO7.0 = 0 PIN as configured as Output.
	// IO7.0 = 1 PIN as configured as Input.
	SSPBUF = MCP23S08_IODIR;
	while(!SSPSTATbits.BF);
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IPOL - Input Polarity - 0b00000000 (Default).
	// IP7.0 = 0 GPIO Register bit will reflect the same logic state of the input pin.
	// IP7.0 = 1 GPIO Register bit will reflect the opposite logic state of the input pin.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPINTEN - Interrupt-on-change - 0b00000000 (Default).
	// GPINT7.0 = 0 Disable GPIO input PIN for interrupt-on-change event.
	// GPINT7.0 = 1 Enable GPIO input PIN for interrupt-on-change event.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// DEFVAL - Default Compare Interrupt-on-change - 0b00000000 (Default).
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCON - Interrupt Control - 0b00000000 (Default).
	// IOC7.0 = 0 PIN value is compared against the previous PIN value.
	// IOC7.0 = 1 Control how the associated PIN value is compared for interrupt-on-change.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IOCON - Configuration - 0b--00000- (Default).
	// SEQOP - Sequential Operation - 0 = Sequential enable, 1 = Sequential disable.
	// DISSLW - Slew Rate Control for SDA output - 0 = Slew rate enabled, 1 = Slew rate disabled.
	// HAEN - Hardware Address Bit - 0 = Disable, 1 = Enabled.
	// ODR - Open-drain PIN output - 0 = Active driver output, 1 = Open-drain output.
	// INTPOL - Set the polarity of the INT output pin - 0 = Active LOW, 1 = Active HIGH.
	SSPBUF = 0b00001000;
	while(!SSPSTATbits.BF);
	// GPPU - Pull-up resistor - 0b00000000 (Default).
	// PU7.0 = 0 Pull-up disabled.
	// PU7.0 = 1 Pull-up enabled.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTF - Interrupt Flag - 0b00000000 (Default) - Read-only.
	// INT7.0 = 0 Interrupt not pending.
	// INT7.0 = 1 PIN caused interrupt.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCAP - Interrupt Capture - 0b00000000 (Default) Read-only.
	// ICP7.0 = 0 Logic-low.
	// ICP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPIO - Port GPIO - 0b00000000 (Default).
	// GP7.0 = 0 Logic-low.
	// GP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// OLAT - Output Latch - 0b00000000 (Default).
	// OL7.0 = 0 Logic-low.
	// OL7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

uint8_t mcp23008_readData(uint8_t u8Address)
{
	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_READ));
	while(!SSPSTATbits.BF);
	SSPBUF = MCP23S08_GPIO;
	while(!SSPSTATbits.BF);
	SSPBUF = 0x00;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;

	return(SSPBUF);
}

void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = MCP23S08_OLAT;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Register;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcu_initialize(void)
{
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// SPI Port.
	SPI_CS = 1;
	SPI_CS_TRIS  = 0;
	SPI_SCK_TRIS = 0;
	SPI_SDI_TRIS = 0;
	// MCP23S08 RESET.
	MCP23S08_RESET = 0;
	MCP23S08_RESET_TRIS = 0;
}

void spi_initializeMaster(void)
{
	// SPI - Master, Mode 0, MSB First.
	// SPI Clock frequency - 8000000 / 4 = 2MHz.
	SSPSTAT = 0x40;
	SSPCON1 = 0x20;
}
Size : 278bytes.
SPI @2MHz

2.MCP23S08 Write in Sequential Mode.

// Configuration register.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v1.44).
// PIC18F2620 - @8MHz Internal oscillator.

// MCP23S08 - 8-bit I/O Expander - Write in Sequential Mode.

// PIC18F Trainer Jumpers.
// JP1 - SCL Open.
// JP2 - SDA Open.
// JP3 - VEE Open.
// JP4 - BCKL Not use.

// Definitions.
// SPI Port.
#define SPI_CS					LATAbits.LATA5
#define SPI_CS_TRIS				TRISAbits.TRISA5
#define SPI_SCK_TRIS			TRISCbits.TRISC3
#define SPI_SDI_TRIS			TRISCbits.TRISC5
// MCP23S08 Port.
#define MCP23S08_RESET_TRIS		TRISAbits.TRISA2
#define MCP23S08_RESET			LATAbits.LATA2
// MCP23S08 Address Select Bits A1 A0.
#define MCP23S08_ADDRESS_40		0x40
#define MCP23S08_ADDRESS_42		0x42
#define MCP23S08_ADDRESS_44		0x44
#define MCP23S08_ADDRESS_46		0x46
#define MCP23S08_WRITE			0x00
#define MCP23S08_READ			0x01
// MCP23S08 Configuration Registers.
#define MCP23S08_IODIR			0x00
#define MCP23S08_IPOL			0x01
#define MCP23S08_GPINTEN		0x02
#define MCP23S08_DEFVAL			0x03
#define MCP23S08_INTCON			0x04
#define MCP23S08_IOCON			0x05
#define MCP23S08_GPPU			0x06
#define MCP23S08_INTF			0x07
#define MCP23S08_INTCAP			0x08
#define MCP23S08_GPIO			0x09
#define MCP23S08_OLAT			0x0A
// MCP23S08 Configuration Bits.
#define MCP23S08_SEQOP			0x20
#define MCP23S08_HAEN			0x08
#define MCP23S08_ODR			0x04
#define MCP23S08_INTPOL			0x02

// Function prototypes.
void mcp23s08_initialize(uint8_t u8Address);
uint8_t mcp23s08_readData(uint8_t u8Address);
void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data);
void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data);
void mcu_initialize(void);
void spi_initializeMaster(void);

// Main.
int main(void)
{
	mcu_initialize();
	spi_initializeMaster();
	mcp23s08_initialize(MCP23S08_ADDRESS_40);

	while(1){
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x00);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x01);
	}
	return(0);
}

// Functions.
void mcp23s08_initialize(uint8_t u8Address)
{
	MCP23S08_RESET = 1;
	__delay_ms(1);

	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	// IODIR - I/O Direction - 0b11111111 (Default).
	// IO7.0 = 0 PIN as configured as Output.
	// IO7.0 = 1 PIN as configured as Input.
	SSPBUF = MCP23S08_IODIR;
	while(!SSPSTATbits.BF);
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IPOL - Input Polarity - 0b00000000 (Default).
	// IP7.0 = 0 GPIO Register bit will reflect the same logic state of the input pin.
	// IP7.0 = 1 GPIO Register bit will reflect the opposite logic state of the input pin.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPINTEN - Interrupt-on-change - 0b00000000 (Default).
	// GPINT7.0 = 0 Disable GPIO input PIN for interrupt-on-change event.
	// GPINT7.0 = 1 Enable GPIO input PIN for interrupt-on-change event.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// DEFVAL - Default Compare Interrupt-on-change - 0b00000000 (Default).
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCON - Interrupt Control - 0b00000000 (Default).
	// IOC7.0 = 0 PIN value is compared against the previous PIN value.
	// IOC7.0 = 1 Control how the associated PIN value is compared for interrupt-on-change.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IOCON - Configuration - 0b--00000- (Default).
	// SEQOP - Sequential Operation - 0 = Sequential enable, 1 = Sequential disable.
	// DISSLW - Slew Rate Control for SDA output - 0 = Slew rate enabled, 1 = Slew rate disabled.
	// HAEN - Hardware Address Bit - 0 = Disable, 1 = Enabled.
	// ODR - Open-drain PIN output - 0 = Active driver output, 1 = Open-drain output.
	// INTPOL - Set the polarity of the INT output pin - 0 = Active LOW, 1 = Active HIGH.
	SSPBUF = 0b00001000;
	while(!SSPSTATbits.BF);
	// GPPU - Pull-up resistor - 0b00000000 (Default).
	// PU7.0 = 0 Pull-up disabled.
	// PU7.0 = 1 Pull-up enabled.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTF - Interrupt Flag - 0b00000000 (Default) - Read-only.
	// INT7.0 = 0 Interrupt not pending.
	// INT7.0 = 1 PIN caused interrupt.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCAP - Interrupt Capture - 0b00000000 (Default) Read-only.
	// ICP7.0 = 0 Logic-low.
	// ICP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPIO - Port GPIO - 0b00000000 (Default).
	// GP7.0 = 0 Logic-low.
	// GP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// OLAT - Output Latch - 0b00000000 (Default).
	// OL7.0 = 0 Logic-low.
	// OL7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

uint8_t mcp23008_readData(uint8_t u8Address)
{
	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_READ));
	while(!SSPSTATbits.BF);
	SSPBUF = MCP23S08_GPIO;
	while(!SSPSTATbits.BF);
	SSPBUF = 0x00;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;

	return(SSPBUF);
}

void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = MCP23S08_OLAT;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Register;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcu_initialize(void)
{
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// SPI Port.
	SPI_CS = 1;
	SPI_CS_TRIS  = 0;
	SPI_SCK_TRIS = 0;
	SPI_SDI_TRIS = 0;
	// MCP23S08 RESET.
	MCP23S08_RESET = 0;
	MCP23S08_RESET_TRIS = 0;
}

void spi_initializeMaster(void)
{
	// SPI - Master, Mode 0, MSB First.
	// SPI Clock frequency - 8000000 / 4 = 2MHz.
	SSPSTAT = 0x40;
	SSPCON1 = 0x20;
}
Size : 250bytes.
SPI @2MHz

3.MCP23S08 Chase in Byte Mode.

// Configuration register.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v1.44).
// PIC18F2620 - @8MHz Internal oscillator.

// MCP23S08 - 8-bit I/O Expander - Chase in Byte Mode.

// PIC18F Trainer Jumpers.
// JP1 - SCL Open.
// JP2 - SDA Open.
// JP3 - VEE Open.
// JP4 - BCKL Not use.

// Definitions.
// SPI Port.
#define SPI_CS					LATAbits.LATA5
#define SPI_CS_TRIS				TRISAbits.TRISA5
#define SPI_SCK_TRIS			TRISCbits.TRISC3
#define SPI_SDI_TRIS			TRISCbits.TRISC5
// MCP23S08 Port.
#define MCP23S08_RESET_TRIS		TRISAbits.TRISA2
#define MCP23S08_RESET			LATAbits.LATA2
// MCP23S08 Address Select Bits A1 A0.
#define MCP23S08_ADDRESS_40		0x40
#define MCP23S08_ADDRESS_42		0x42
#define MCP23S08_ADDRESS_44		0x44
#define MCP23S08_ADDRESS_46		0x46
#define MCP23S08_WRITE			0x00
#define MCP23S08_READ			0x01
// MCP23S08 Configuration Registers.
#define MCP23S08_IODIR			0x00
#define MCP23S08_IPOL			0x01
#define MCP23S08_GPINTEN		0x02
#define MCP23S08_DEFVAL			0x03
#define MCP23S08_INTCON			0x04
#define MCP23S08_IOCON			0x05
#define MCP23S08_GPPU			0x06
#define MCP23S08_INTF			0x07
#define MCP23S08_INTCAP			0x08
#define MCP23S08_GPIO			0x09
#define MCP23S08_OLAT			0x0A
// MCP23S08 Configuration Bits.
#define MCP23S08_SEQOP			0x20
#define MCP23S08_HAEN			0x08
#define MCP23S08_ODR			0x04
#define MCP23S08_INTPOL			0x02
//
#define DELAY					200

// Function prototypes.
void mcp23s08_initialize(uint8_t u8Address);
uint8_t mcp23s08_readData(uint8_t u8Address);
void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data);
void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data);
void mcu_initialize(void);
void spi_initializeMaster(void);

// Main.
int main(void)
{
	mcu_initialize();
	spi_initializeMaster();
	mcp23s08_initialize(MCP23S08_ADDRESS_40);
	// Configure MCP23S08 in Byte Mode.
	mcp23s08_writeRegister(MCP23S08_ADDRESS_40, MCP23S08_IOCON, MCP23S08_SEQOP);

	SPI_CS = 0;
	SSPBUF = (uint8_t)(MCP23S08_ADDRESS_40 | MCP23S08_WRITE);
	while(!SSPSTATbits.BF);
	SSPBUF = MCP23S08_OLAT;
	while(!SSPSTATbits.BF);
	while(1){
		SSPBUF = 0x01;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x02;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x04;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x08;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x10;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x20;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x40;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x80;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x40;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x20;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x10;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x08;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x04;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
		SSPBUF = 0x02;
		while(!SSPSTATbits.BF);
        __delay_ms(DELAY);
	}
	return(0);
}

// Functions.
void mcp23s08_initialize(uint8_t u8Address)
{
	MCP23S08_RESET = 1;
	__delay_ms(1);

	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	// IODIR - I/O Direction - 0b11111111 (Default).
	// IO7.0 = 0 PIN as configured as Output.
	// IO7.0 = 1 PIN as configured as Input.
	SSPBUF = MCP23S08_IODIR;
	while(!SSPSTATbits.BF);
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IPOL - Input Polarity - 0b00000000 (Default).
	// IP7.0 = 0 GPIO Register bit will reflect the same logic state of the input pin.
	// IP7.0 = 1 GPIO Register bit will reflect the opposite logic state of the input pin.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPINTEN - Interrupt-on-change - 0b00000000 (Default).
	// GPINT7.0 = 0 Disable GPIO input PIN for interrupt-on-change event.
	// GPINT7.0 = 1 Enable GPIO input PIN for interrupt-on-change event.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// DEFVAL - Default Compare Interrupt-on-change - 0b00000000 (Default).
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCON - Interrupt Control - 0b00000000 (Default).
	// IOC7.0 = 0 PIN value is compared against the previous PIN value.
	// IOC7.0 = 1 Control how the associated PIN value is compared for interrupt-on-change.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IOCON - Configuration - 0b--00000- (Default).
	// SEQOP - Sequential Operation - 0 = Sequential enable, 1 = Sequential disable.
	// DISSLW - Slew Rate Control for SDA output - 0 = Slew rate enabled, 1 = Slew rate disabled.
	// HAEN - Hardware Address Bit - 0 = Disable, 1 = Enabled.
	// ODR - Open-drain PIN output - 0 = Active driver output, 1 = Open-drain output.
	// INTPOL - Set the polarity of the INT output pin - 0 = Active LOW, 1 = Active HIGH.
	SSPBUF = 0b00001000;
	while(!SSPSTATbits.BF);
	// GPPU - Pull-up resistor - 0b00000000 (Default).
	// PU7.0 = 0 Pull-up disabled.
	// PU7.0 = 1 Pull-up enabled.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTF - Interrupt Flag - 0b00000000 (Default) - Read-only.
	// INT7.0 = 0 Interrupt not pending.
	// INT7.0 = 1 PIN caused interrupt.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCAP - Interrupt Capture - 0b00000000 (Default) Read-only.
	// ICP7.0 = 0 Logic-low.
	// ICP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPIO - Port GPIO - 0b00000000 (Default).
	// GP7.0 = 0 Logic-low.
	// GP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// OLAT - Output Latch - 0b00000000 (Default).
	// OL7.0 = 0 Logic-low.
	// OL7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

uint8_t mcp23008_readData(uint8_t u8Address)
{
	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_READ));
	while(!SSPSTATbits.BF);
	SSPBUF = MCP23S08_GPIO;
	while(!SSPSTATbits.BF);
	SSPBUF = 0x00;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;

	return(SSPBUF);
}

void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = MCP23S08_OLAT;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Register;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcu_initialize(void)
{
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// SPI Port.
	SPI_CS = 1;
	SPI_CS_TRIS  = 0;
	SPI_SCK_TRIS = 0;
	SPI_SDI_TRIS = 0;
	// MCP23S08 RESET.
	MCP23S08_RESET = 0;
	MCP23S08_RESET_TRIS = 0;
}

void spi_initializeMaster(void)
{
	// SPI - Master, Mode 0, MSB First.
	// SPI Clock frequency - 8000000 / 4 = 2MHz.
	SSPSTAT = 0x40;
	SSPCON1 = 0x20;
}
Size : 710bytes.

4.MCP23S08 Chase in Sequential Mode.

// Configuration register.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v1.44).
// PIC18F2620 - @8MHz Internal oscillator.

// MCP23S08 - 8-bit I/O Expander - Chase in Sequential Mode.

// PIC18F Trainer Jumpers.
// JP1 - SCL Open.
// JP2 - SDA Open.
// JP3 - VEE Open.
// JP4 - BCKL Not use.

// Definitions.
// SPI Port.
#define SPI_CS					LATAbits.LATA5
#define SPI_CS_TRIS				TRISAbits.TRISA5
#define SPI_SCK_TRIS			TRISCbits.TRISC3
#define SPI_SDI_TRIS			TRISCbits.TRISC5
// MCP23S08 Port.
#define MCP23S08_RESET_TRIS		TRISAbits.TRISA2
#define MCP23S08_RESET			LATAbits.LATA2
// MCP23S08 Address Select Bits A1 A0.
#define MCP23S08_ADDRESS_40		0x40
#define MCP23S08_ADDRESS_42		0x42
#define MCP23S08_ADDRESS_44		0x44
#define MCP23S08_ADDRESS_46		0x46
#define MCP23S08_WRITE			0x00
#define MCP23S08_READ			0x01
// MCP23S08 Configuration Registers.
#define MCP23S08_IODIR			0x00
#define MCP23S08_IPOL			0x01
#define MCP23S08_GPINTEN		0x02
#define MCP23S08_DEFVAL			0x03
#define MCP23S08_INTCON			0x04
#define MCP23S08_IOCON			0x05
#define MCP23S08_GPPU			0x06
#define MCP23S08_INTF			0x07
#define MCP23S08_INTCAP			0x08
#define MCP23S08_GPIO			0x09
#define MCP23S08_OLAT			0x0A
// MCP23S08 Configuration Bits.
#define MCP23S08_SEQOP			0x20
#define MCP23S08_HAEN			0x08
#define MCP23S08_ODR			0x04
#define MCP23S08_INTPOL			0x02
//
#define DELAY					200

// Function prototypes.
void mcp23s08_initialize(uint8_t u8Address);
uint8_t mcp23s08_readData(uint8_t u8Address);
void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data);
void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data);
void mcu_initialize(void);
void spi_initializeMaster(void);

// Main.
int main(void)
{
	mcu_initialize();
	spi_initializeMaster();
	mcp23s08_initialize(MCP23S08_ADDRESS_40);

	while(1){
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x01);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x02);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x04);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x08);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x10);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x20);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x40);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x80);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x40);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x20);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x10);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x08);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x04);
		__delay_ms(DELAY);
		mcp23s08_writeData(MCP23S08_ADDRESS_40, 0x02);
		__delay_ms(DELAY);
	}
	return(0);
}

// Functions.
void mcp23s08_initialize(uint8_t u8Address)
{
	MCP23S08_RESET = 1;
	__delay_ms(1);

	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	// IODIR - I/O Direction - 0b11111111 (Default).
	// IO7.0 = 0 PIN as configured as Output.
	// IO7.0 = 1 PIN as configured as Input.
	SSPBUF = MCP23S08_IODIR;
	while(!SSPSTATbits.BF);
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IPOL - Input Polarity - 0b00000000 (Default).
	// IP7.0 = 0 GPIO Register bit will reflect the same logic state of the input pin.
	// IP7.0 = 1 GPIO Register bit will reflect the opposite logic state of the input pin.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPINTEN - Interrupt-on-change - 0b00000000 (Default).
	// GPINT7.0 = 0 Disable GPIO input PIN for interrupt-on-change event.
	// GPINT7.0 = 1 Enable GPIO input PIN for interrupt-on-change event.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// DEFVAL - Default Compare Interrupt-on-change - 0b00000000 (Default).
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCON - Interrupt Control - 0b00000000 (Default).
	// IOC7.0 = 0 PIN value is compared against the previous PIN value.
	// IOC7.0 = 1 Control how the associated PIN value is compared for interrupt-on-change.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// IOCON - Configuration - 0b--00000- (Default).
	// SEQOP - Sequential Operation - 0 = Sequential enable, 1 = Sequential disable.
	// DISSLW - Slew Rate Control for SDA output - 0 = Slew rate enabled, 1 = Slew rate disabled.
	// HAEN - Hardware Address Bit - 0 = Disable, 1 = Enabled.
	// ODR - Open-drain PIN output - 0 = Active driver output, 1 = Open-drain output.
	// INTPOL - Set the polarity of the INT output pin - 0 = Active LOW, 1 = Active HIGH.
	SSPBUF = 0b00001000;
	while(!SSPSTATbits.BF);
	// GPPU - Pull-up resistor - 0b00000000 (Default).
	// PU7.0 = 0 Pull-up disabled.
	// PU7.0 = 1 Pull-up enabled.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTF - Interrupt Flag - 0b00000000 (Default) - Read-only.
	// INT7.0 = 0 Interrupt not pending.
	// INT7.0 = 1 PIN caused interrupt.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// INTCAP - Interrupt Capture - 0b00000000 (Default) Read-only.
	// ICP7.0 = 0 Logic-low.
	// ICP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// GPIO - Port GPIO - 0b00000000 (Default).
	// GP7.0 = 0 Logic-low.
	// GP7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	// OLAT - Output Latch - 0b00000000 (Default).
	// OL7.0 = 0 Logic-low.
	// OL7.0 = 1 Logic-high.
	SSPBUF = 0b00000000;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

uint8_t mcp23008_readData(uint8_t u8Address)
{
	SPI_CS = 0;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_READ));
	while(!SSPSTATbits.BF);
	SSPBUF = MCP23S08_GPIO;
	while(!SSPSTATbits.BF);
	SSPBUF = 0x00;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;

	return(SSPBUF);
}

void mcp23s08_writeData(uint8_t u8Address, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = MCP23S08_OLAT;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcp23s08_writeRegister(uint8_t u8Address, uint8_t u8Register, uint8_t u8Data)
{
	uint8_t dummy;

	SPI_CS = 0;
	dummy = SSPBUF;
	SSPBUF = ((uint8_t)(u8Address | MCP23S08_WRITE));
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Register;
	while(!SSPSTATbits.BF);
	dummy = SSPBUF;
	SSPBUF = u8Data;
	while(!SSPSTATbits.BF);
	SPI_CS = 1;
}

void mcu_initialize(void)
{
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// SPI Port.
	SPI_CS = 1;
	SPI_CS_TRIS  = 0;
	SPI_SCK_TRIS = 0;
	SPI_SDI_TRIS = 0;
	// MCP23S08 RESET.
	MCP23S08_RESET = 0;
	MCP23S08_RESET_TRIS = 0;
}

void spi_initializeMaster(void)
{
	// SPI - Master, Mode 0, MSB First.
	// SPI Clock frequency - 8000000 / 4 = 2MHz.
	SSPSTAT = 0x40;
	SSPCON1 = 0x20;
}
Size : 706bytes.

01.2018