1.引脚配置:
2.设备地址:
根据原理图可以算出设备的读写地址分别为:0x43、0x42
3.指令:
代码实现:
#include "hal.h"
#include "vbus.h"
#include "LedTask.h"
#include "Lib.h"
#define MCP23017_I2C_ADDR_WR 0x42
#define MCP23017_I2C_ADDR_RD 0x43
#define GPIO_MODE_INPUT 0x00000000u /*!< Input Floating Mode */
#define GPIO_MODE_OUTPUT_PP 0x00000001u /*!< Output Push Pull Mode */
#define GPIO_MODE_OUTPUT_OD 0x00000011u /*!< Output Open Drain Mode */
#define GPIO_MODE_AF_PP 0x00000002u /*!< Alternate Function Push Pull Mode */
#define GPIO_MODE_AF_OD 0x00000012u /*!< Alternate Function Open Drain Mode */
#define GPIO_MODE_AF_INPUT GPIO_MODE_INPUT /*!< Alternate Function Input Mode */
#define GPIO_MODE_ANALOG 0x00000003u /*!< Analog Mode */
#define REGISTER_0_INPUT_PORT 0X00
#define REGISTER_1_INPUT_PORT 0X01
#define REGISTER_0_OUTPUT_PORT 0X02
#define REGISTER_1_OUTPUT_PORT 0X03
#define REGISTER_0_POLARITY_INVERSION_PORT 0X04
#define REGISTER_1_POLARITY_INVERSION_PORT 0X05
#define REGISTER_0_CONFIGURATION_PORT 0X06
#define REGISTER_1_CONFIGURATION_PORT 0X07
#define NCA9555_SET_ALL_PIN 0
unsigned char Output_HL[16][2]={
//gpio a
{0x80,0x00},//PA7
{0x40,0x00},//PA6
{0x20,0x00},//PA5
{0x10,0x00},//PA4
{0x08,0x00},//PA3
{0x04,0x00},//PA2
{0x02,0x00},//PA1
{0x01,0x00},//PA0
//gpio b
{0x00,0x01}, //PB0
{0x00,0x02}, //PB1
{0x00,0x04}, //PB2
{0x00,0x08}, //PB3
{0x00,0x10}, //PB4
{0x00,0x20}, //PB5
{0x00,0x40}, //PB6
{0x00,0x80}, //PB7
};
static unsigned char timeCount = 0;
static unsigned char setBuff[4]={0x00,0x00,0xff,0xff};
unsigned char I2C_Start(void)
{
unsigned char i_temp = 0;
HalCall.SetSoftIIC_SCLInOutMode(GPIO_MODE_OUTPUT_PP);//设置SCL输出模式
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_PP);//设置SDA输出模式
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(1);//设置SDA脚高电平
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);//设置SCL脚高电平
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_INPUT);//设置SDA输入模式
Wait1us(5);
if( HalCall.SetSoftIIC_SDAInput() )//读取SDA脚电平高低
{
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_PP);
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(0);//设置SCL脚低高电平
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);//设置SCL脚低电平
Wait1us(5);
//OK
return(1);
}
else
{
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_PP);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
Wait1us(5);
for (i_temp = 0; i_temp < 9; i_temp++)
{
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
}
E2romI2CStop( );
//ERROR
return(0);
}
}
void I2C_Stop( )
{
HalCall.SetSoftIIC_SCLInOutMode(GPIO_MODE_OUTPUT_PP);
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_PP);
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(0);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_INPUT);
HalCall.SetSoftIIC_SCLInOutMode(GPIO_MODE_INPUT);
}
unsigned char I2C_Send_Byte(unsigned char i2c_data)
{
unsigned char i_temp = 0;
HalCall.SetSoftIIC_SCLInOutMode(GPIO_MODE_OUTPUT_PP);
Wait1us(5);
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_OD);
Wait1us(5);
for (i_temp = 0; i_temp < 8; i_temp++)
{
if (i2c_data & 0x80)
{
HalCall.SetSoftIIC_SDAOutput(1);
}
else
{
HalCall.SetSoftIIC_SDAOutput(0);
}
i2c_data <<= 1;
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
Wait1us(5);
}
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_INPUT);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
for (i_temp=0;(i_temp<1500)&& HalCall.SetSoftIIC_SDAInput() ;i_temp++)
NOP;
if( HalCall.SetSoftIIC_SDAInput() )
{
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_OD);
HalCall.SetSoftIIC_SCLOutput(0);
Wait1us(5);
E2romI2CStop( );
//ERROR
return(0);
}
else
{
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_OD);
HalCall.SetSoftIIC_SCLOutput(0);
Wait1us(5);
//OK
return(1);
}
}
unsigned char I2C_Read_Byte()
{
unsigned char i_temp = 0;
unsigned char result = 0;
HalCall.SetSoftIIC_SCLInOutMode(GPIO_MODE_OUTPUT_PP);
Wait1us(5);
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_INPUT);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
for (i_temp=0; i_temp<8; i_temp++)
{
result <<= 1;
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
if( HalCall.SetSoftIIC_SDAInput() )
result |=0x01;
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
}
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_OD);
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(0);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(1);
return result;
}
unsigned char I2C_Read_Last_Byte (void)
{
unsigned char i_temp = 0;
unsigned char result = 0;
HalCall.SetSoftIIC_SCLInOutMode(GPIO_MODE_OUTPUT_PP);
Wait1us(5);
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_INPUT);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
for (i_temp=0; i_temp<8; i_temp++)
{
result <<= 1;
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
if( HalCall.SetSoftIIC_SDAInput() )
result |=0x01;
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
}
HalCall.SetSoftIIC_SDAInOutMode(GPIO_MODE_OUTPUT_OD);
Wait1us(5);
HalCall.SetSoftIIC_SDAOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(1);
Wait1us(5);
HalCall.SetSoftIIC_SCLOutput(0);
Wait1us(5);
return result;
}
unsigned char NCA9555_Write_Data(unsigned char address,unsigned char command,unsigned short int length,unsigned char *data)
{
unsigned char ret = 0;
unsigned char i_temp = 0;
ret = I2C_Start();
if (ret)
{
ret = I2C_Send_Byte(address);
}
if (ret)
{
ret = I2C_Send_Byte(command);
}
for(i_temp=0;i_temp<(length);i_temp++)
{
if (ret)
{
I2C_Send_Byte(data[i_temp]);
}
}
if (ret)
{
I2C_Stop();
}
return(0);
}
void NCA9555_Read_Data(unsigned char address,unsigned char command,unsigned short int length,unsigned char *data)
{
unsigned char ret = 0;
unsigned char i_temp = 0;
unsigned char DataTemp = 0;
ret = I2C_Start();
if (ret)
{
ret = I2C_Send_Byte(address);
}
if (ret)
{
ret = I2C_Send_Byte(command);
}
if (ret)
{
ret = I2C_Start();
}
if (ret)
{
ret = I2C_Send_Byte((unsigned char)(address|0x01));
}
for(i_temp=0;i_temp<(length-1);i_temp++)
{
DataTemp = I2C_Read_Byte();
*data++ = DataTemp;
}
DataTemp = I2C_Read_Last_Byte();
*data = DataTemp;
if (ret)
{
I2C_Stop();
}
}
//10ms call
void NCA9555_Task( void )
{
unsigned char readData[2] = {0x01,0x02};
unsigned char writeData[2] = {0};
timeCount++;
if(timeCount == 100)
{
#if NCA9555_SET_ALL_PIN
//设置所有pin
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_CONFIGURATION_PORT,2,&setBuff[0]);
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_OUTPUT_PORT,2,&setBuff[0]);
NCA9555_Read_Data(MCP23017_I2C_ADDR_RD,REGISTER_0_INPUT_PORT,2,readData);
#else
//设置PA7
writeData[0] |= Output_HL[0][0];
writeData[1] |= Output_HL[0][1];
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_CONFIGURATION_PORT,2,&setBuff[0]);
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_OUTPUT_PORT,2,&writeData[0]);
#endif
}
else if(timeCount == 200)
{
timeCount = 0;
#if NCA9555_SET_ALL_PIN
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_CONFIGURATION_PORT,2,&setBuff[0]);
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_OUTPUT_PORT,2,&setBuff[2]);
NCA9555_Read_Data(MCP23017_I2C_ADDR_RD,REGISTER_0_INPUT_PORT,2,readData);
#else
writeData[0] &= ~(Output_HL[0][0]);
writeData[1] &= ~(Output_HL[0][1]);
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_CONFIGURATION_PORT,2,&setBuff[0]);
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_OUTPUT_PORT,2,&writeData[0]);
#endif
}
}
此代码中,SCL、SDA脚的GPIO口配置代码被封装起来了;如需实现,替换对应的SCL、SDA脚位配置即可。