CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Help w/ MCP23S17, SPI Port Expander

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

Help w/ MCP23S17, SPI Port Expander
PostPosted: Sun Apr 23, 2006 4:23 pm     Reply with quote

Hello All,

I’m having a hard time getting a SPI port expander working 100%. I’m using a MCP23S17 connected to the hardware SPI on a 18F4620. (The pertinent code is below.) I can reliably poll the switches, but the output to the LEDs just doesn’t want to work 100% of the time. Right now I just use them as ‘heartbeat’ to give visual indication that the PIC is running.

Symptoms:
Upon cycling power the LEDs may or may not flash, but everything else is working great. RS232 output works, PIC polls MCP23S17 and receives reliable and accurate info on PORTA switches. Unfortunately I can’t produce any repetitive results to narrow done the problem.

I have tried:
Replacing LDO
Replacing MCP23S17
Up to 10uF cap at MCP23S17


One thing I’m unsure of is the difference between the GPIOB register and the OLATB register. Do they both need to be set high for the output to be reliably high? My experiments have shown that either can be set high to get things working.. sometimes.


MCP23S17 Connections:

GPA0 P/U w/ 10K to 5V (RTC alarm active low)
GPA1 P/U w/ 10K to 5V (MOM Sw to Gnd)
GPA2 P/U w/ 10K to 5V (MOM Sw to Gnd)
GPA3 P/U w/ 10K to 5V (MOM Sw to Gnd)
GPA4 P/U w/ 10K to 5V (MOM Sw to Gnd)
GPA5 P/U w/ 10K to 5V (MOM Sw to Gnd)
GPA6 Unconnected
GPA7 Unconnected

GPB0 P/U w/ 10K to 5V (not connected otherwise)
GPB1 P/U w/ 10K to 5V (not connected otherwise)
GPB2 P/U w/ 10K to 5V (not connected otherwise)
GPB3 P/U w/ 10K to 5V (not connected otherwise)
GPB4 to LED then 470R then Gnd
GPB5 to LED then 470R then Gnd
GPB6 to LED then 470R then Gnd
GPB7 Unconnected


This is the stuff that's in the header:
Code:
//The following are for address 000, i.e. A2,A1,A0 = 0.
#define write_byte   0b01000000
#define read_byte    0b01000001

//The following are the Power-Up values for the control registers, they will
//be application specific. They are presented in the Bank 0 format,
//alternating between PORTA and PORTB.

//Port direction, 1 = input, 0 = output
#define IODIRA_PU    0b00111111
#define IODIRB_PU    0b00001111



These two functions are in the MAIN() prior to the WHILE(TRUE):
Code:
/*
Put EXT_IO chip in default power-up state
*/
void reset_ext_io(void) {
   output_low(EXT_IO_RESET);
   delay_us(5);                  //pulse reset pin low
   output_high(EXT_IO_RESET);    //bring reset pin high
   delay_us(5);                  //allow time to settle before continuing
}


/*
Put EXT_IO chip in user desired power-up state
NOTE: Only use after reset_ext_io(), and add any values to write_spi() that are
      different from default POR values.
*/
void setup_ext_io(void) {
   setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16); //use middle of the road clock speed, part is good to 10mHz
   output_low(EXT_IO_CS);        //select ext_io chip
   delay_us(5);                  //allow everything to catch-up
   spi_write(write_byte);        //send write op_code
   spi_write(0x00);              //send starting address for config
   spi_write(IODIRA_PU);
   spi_write(IODIRB_PU);
   output_high(EXT_IO_CS);       //de-select ext_io chip
   delay_us(5);                  //allow everything to catch-up
}


Any help would be greatly appreciated.

Thanks,

John
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Mon Apr 24, 2006 4:29 pm     Reply with quote

SOLVED.


Removed a
Code:
set_tris_b(0X00);

statement prior to resetting and configuring and everything works now.

Go figure.
zcbm2724
Guest







MCP23S17
PostPosted: Sun Dec 31, 2006 5:07 pm     Reply with quote

Hi.
Did not get correlation between the code, and what u did to it.
I am in the similar problem situation

Can you put the significant part (non proprietary) of code to initialize and interface SP including, configuring the registers.

Appreciate your help.

regards
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sun Dec 31, 2006 6:17 pm     Reply with quote

I also use a pair of MCP23S17's in a project, but I don't use the processor's MSSP module to communicate. I instead bit-bang everything. This is with a 18F2480. One IO expander has its address lines all pulled low, the other has them all pulled high. Code is below. Simply call io_init() to initialize the IO expanders. I use each in output mode only.

Code:
#define IO_CS PIN_C0
#define IO_RESET PIN_C1
#define SPI_CLK  PIN_A4
#define SPI_DOUT PIN_A3
#define SPI_DIN  PIN_A2

#define WRITE 0
#define READ 1

#define BANK1 0x80
#define DISABLE_SLEW 0x10
#define ENABLE_HW 0x08

#define IO_1 0x0e
#define IO_2 0x00

#define CONTROL_REG 0x0a
#define DIRECTION_REG 0x00
#define A_BANK 0
#define B_BANK 0x10
#define LATCH_REG 0x0a

int8 control_byte = 0x40;

void io_init(void) {
   int8 readback;

   output_high(IO_CS);
   output_high(SPI_CLK);
   delay_us(100);
   output_low(IO_RESET); // hard reset
   delay_us(50);
   output_high(IO_RESET);
   delay_ms(10);

   // now must set up the io expanders
   write_io(control_byte|IO_1|WRITE, CONTROL_REG, BANK1|ENABLE_HW|DISABLE_SLEW); // sets up IO 1
   write_io(control_byte|IO_2|WRITE, CONTROL_REG, BANK1|ENABLE_HW|DISABLE_SLEW); // sets up IO 2

   // now must first write 0's into their output latches, then change port directions to output
   write_io(control_byte|IO_1|WRITE, LATCH_REG|A_BANK, 0);
   write_io(control_byte|IO_1|WRITE, DIRECTION_REG|A_BANK, 0);
   write_io(control_byte|IO_1|WRITE, LATCH_REG|B_BANK, 0);
   write_io(control_byte|IO_1|WRITE, DIRECTION_REG|B_BANK, 0);

   write_io(control_byte|IO_2|WRITE, LATCH_REG|A_BANK, 0);
   write_io(control_byte|IO_2|WRITE, DIRECTION_REG|A_BANK, 0);
   write_io(control_byte|IO_2|WRITE, LATCH_REG|B_BANK, 0);
   write_io(control_byte|IO_2|WRITE, DIRECTION_REG|B_BANK, 0);
}

void write_io_byte(int8 data) {
   int8 i;

   delay_us(20);

   for (i = 0; i < 8; i++) {
      output_low(SPI_CLK);
      if (bit_test(data, 7 - i)) {
         output_high(SPI_DIN);
      }
      else {
         output_low(SPI_DIN);
      }
      delay_us(6);
      output_high(SPI_CLK);
      delay_us(6);
   }
}

void write_io(int8 control, int8 address, int8 data) {
   delay_us(20);

   output_high(SPI_CLK);
   output_high(SPI_DIN);
   delay_us(20);
   output_low(IO_CS);

   write_io_byte(control);

   write_io_byte(address);

   write_io_byte(data);

   delay_us(20);
   output_high(IO_CS);
}

int8 read_io(int8 control, int8 address) {
   int8 register_state = 0;
   int8 i;

   delay_us(20);

   output_high(SPI_CLK);
   output_high(SPI_DIN);
   delay_us(20);
   output_low(IO_CS);

   write_io_byte(control);

   write_io_byte(address);

   for (i = 0; i < 8; i++) {
      register_state = register_state << 1;
      output_low(SPI_CLK);
      delay_us(6);
      if (input(SPI_DOUT)) {
         register_state = register_state | 0x01;
      }
      output_high(SPI_CLK);
      delay_us(6);
   }

   delay_us(20);
   output_high(IO_CS);

   return(register_state);
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group