Search code examples
cstm32microchip

Why don't I get HIGH on output pins of MCP23S17?


I use a STM32 connected with SPI to a MCP23S17 16 bit I/O port expander.

I want to make all 16 I/0 pins as output and just making them all LOW or HIGH.

I used an oscilloscope to check is SPI transmit the signals right, and it does. The only thing is that on the I/O pins I get around 0.4V. Not 5V.

Sometimes I get a value of 1.4V but it goes away, weird thing...

Can somebody check my code and tell me where is my mistake? I am pretty sure I did the code wrong somewhere.

MCP23S17.h:

#ifndef INC_MCP23S17_H_
#define INC_MCP23S17_H_

#include "stm32f1xx_hal_conf.h"

extern SPI_HandleTypeDef hspi2;

void MCP23S17_SPI_Write(uint8_t reg_addr, uint8_t data);
uint8_t MCP23S17_SPI_Read(uint8_t data);

#define CS_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
#define CS_LOW() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);




#define MCP23S17_AAA        ((uint8_t)0x0E)
#define MCP23S17_ADDRESS    ((uint8_t)0x40)

#define MCP23S17_W          ((uint8_t)0x00)
#define MCP23S17_R          ((uint8_t)0x01)

#define MCP23S17_IODIRA     ((uint8_t)0x00)
#define MCP23S17_IPOLA      ((uint8_t)0x02)
#define MCP23S17_GPINTENA   ((uint8_t)0x04)
#define MCP23S17_DEFVALA    ((uint8_t)0x06)
#define MCP23S17_INTCONA    ((uint8_t)0x08)
#define MCP23S17_IOCONA     ((uint8_t)0x0A)
#define MCP23S17_GPPUA      ((uint8_t)0x0C)
#define MCP23S17_INTFA      ((uint8_t)0x0E)
#define MCP23S17_INTCAPA    ((uint8_t)0x10)
#define MCP23S17_GPIOA      ((uint8_t)0x12)
#define MCP23S17_OLATA      ((uint8_t)0x14)


#define MCP23S17_IODIRB     ((uint8_t)0x01)
#define MCP23S17_IPOLB      ((uint8_t)0x03)
#define MCP23S17_GPINTENB   ((uint8_t)0x05)
#define MCP23S17_DEFVALB    ((uint8_t)0x07)
#define MCP23S17_INTCONB    ((uint8_t)0x09)
//#define MCP23S17_IOCONB   ((uint8_t)0x0B)
#define MCP23S17_GPPUB      ((uint8_t)0x0D)
#define MCP23S17_INTFB      ((uint8_t)0x0F)
#define MCP23S17_INTCAPB    ((uint8_t)0x11)
#define MCP23S17_GPIOB      ((uint8_t)0x13)
#define MCP23S17_OLATB      ((uint8_t)0x15)




//#define MCP23S17_INT_ERR  ((uint8_t)255)

//#define BANK              ((uint8_t)0x80) //bit 7  of IOCON
//#define MIRROR                ((uint8_t)0x40) //bit 6  of IOCON
//#define SEQOP                 ((uint8_t)0x20) //bit 5  of IOCON
//#define DISSLW                ((uint8_t)0x10) //bit 4  of IOCON
//#define HAEN              ((uint8_t)0x08) //bit 3  of IOCON
//#define ODR                   ((uint8_t)0x04) //bit 2  of IOCON
//#define INTPOL                ((uint8_t)0x02) //bit 1  of IOCON
//#define unused                ((uint8_t)0x00) //bit 0  of IOCON


//-----------------------

#define MCP23S17_MODERA_W(x) MCP23S17_SPI_Write(MCP23S17_IODIRA, ((uint8_t)x))
#define MCP23S17_MODERA_R() MCP23S17_SPI_Read(MCP23S17_IODIRA)

#define MCP23S17_IPOLA_W(x) MCP23S17_SPI_Write(MCP23S17_IPOLA, ((uint8_t)x))


#define MCP23S17_ODRA_W(x) MCP23S17_SPI_Write(MCP23S17_OLATA, ((uint8_t)x))
#define MCP23S17_ODRA_R() MCP23S17_SPI_Read(MCP23S17_OLATA)

#define MCP23S17_IDRA_R() MCP23S17_SPI_Read(MCP23S17_GPIOA)     // Reflect the value of the port A

#define MCP23S17_PUDA_W(x) MCP23S17_SPI_Write(MCP23S17_GPPUA, ((uint8_t)x))
#define MCP23S17_PUDA_R() MCP23S17_SPI_Read(MCP23S17_GPPUA)

#define MCP23S17_SETUP_W(x) MCP23S17_SPI_Write(MCP23S17_IOCONA, ((uint8_t)x))
#define MCP23S17_SETUP_R() MCP23S17_SPI_Read(MCP23S17_IOCONA))

#define MCP23S17_MODERB_W(x) MCP23S17_SPI_Write(MCP23S17_IODIRB, ((uint8_t)x))
#define MCP23S17_MODERB_R() MCP23S17_SPI_Read(MCP23S17_IODIRB)

#define MCP23S17_IPOLB_W(x) MCP23S17_SPI_Write(MCP23S17_IPOLB, ((uint8_t)x))


#define MCP23S17_ODRB_W(x) MCP23S17_SPI_Write(MCP23S17_OLATB, ((uint8_t)x))
#define MCP23S17_ODRB_R() MCP23S17_SPI_Read(MCP23S17_OLATB)

#define MCP23S17_IDRB_R() MCP23S17_SPI_Read(MCP23S17_GPIOB)     // Reflect the value of the port B

#define MCP23S17_PUDB_W(x) MCP23S17_SPI_Write(MCP23S17_GPPUB, ((uint8_t)x))
#define MCP23S17_PUDB_R() MCP23S17_SPI_Read(MCP23S17_GPPUB)

//-----------------------

void GPIO_Write_Pins(uint16_t);
void GPIO_Expander_Init();
void MCP23S17_SPI_Write(uint8_t reg_addr, uint8_t data);
#endif /* INC_MCP23S17_H_ */

MCP23S17.c

#include "main.h"
#include "MCP23S17.h"

void MCP23S17_SPI_Write(uint8_t reg_addr, uint8_t data)
{
    uint8_t pBuff[3];
    pBuff[0] = MCP23S17_ADDRESS|MCP23S17_AAA|MCP23S17_W;    //optocode that contain 0100 + 111 + 0 (read command)
    pBuff[1] = reg_addr;  // register address
    pBuff[2] = data;      // the value that is modified on the register, check datasheet

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

    HAL_SPI_Transmit_IT(&hspi2, pBuff, 3);  //transmit on the spi2 the optocode, register adress and the value for the register
    for(uint32_t i = 0; i < 85; i++)    //delay
        {}

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
}
void GPIO_Expander_Init()
{
    MCP23S17_SETUP_W(0x00);
    MCP23S17_MODERA_W(0x00);
    MCP23S17_MODERB_W(0x00);
    MCP23S17_PUDA_W(0x00);
    MCP23S17_PUDB_W(0x00);
    //MCP23S17_IPOLA_W(0x00);
    //MCP23S17_IPOLB_W(0x00);

}
void GPIO_Write_Pins(uint16_t dataspi)
{
    //16 to 8 and 8
    uint8_t data_half[2];

    data_half[0]=*((uint8_t*)&(dataspi)+1);     //split the first half of the data
    data_half[1]=*((uint8_t*)&(dataspi)+0);     //split the second half of the data

    MCP23S17_ODRA_W(data_half[0]);  //first half
    MCP23S17_ODRB_W(data_half[1]);  //second half

}

and in main.c

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);


  GPIO_Expander_Init();

  GPIO_Write_Pins(0xFFFF);
  while(1)
  {

  }


Solution

  • So coming back with the solution, the code was good, 2 first gpio expanders that I tried were purely burned. For a much shorter working code just comment here asking for it. Thank everyone for advices cause I took them in consideration in the final form of code.