Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
149 views
in Technique[技术] by (71.8m points)

c - 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)
  {

  }

question from:https://stackoverflow.com/questions/65626315/why-dont-i-get-high-on-output-pins-of-mcp23s17

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The only thing is that on the I/O pins I get around 0.4V

This is likely because GPIOs are not initialized.

You also have a different problem to deal with.

for(uint32_t i = 0; i < 85; i++)    //delay
{}

This loop is very likely to be optimize away by the compiler. This is because, it doesn't do anything.

There are more sophisticated ways of generating delays in a microcontroller. The best possible solution would be to use a timer module.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...