NCA9555驱动
nca9555.c
#define MCP23017_I2C_ADDR_WR 0x48
/*Command byte*/
#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
static unsigned int timeCount = 0;
static unsigned char setBuff[4]={0x00,0x00,0xff,0xff};
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;
I2cStart(I2C_TYPE_1);
I2cSendByte(I2C_TYPE_1,address);
I2cWaitAck(I2C_TYPE_1);
I2cSendByte(I2C_TYPE_1,command);
I2cWaitAck(I2C_TYPE_1);
for(i_temp=0;i_temp<(length);i_temp++)
{
I2cSendByte(I2C_TYPE_1,data[i_temp]);
I2cWaitAck(I2C_TYPE_1);
}
I2cStop(I2C_TYPE_1);
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;
I2cStart(I2C_TYPE_1);
I2cSendByte(I2C_TYPE_1,address);
I2cWaitAck(I2C_TYPE_1);
I2cSendByte(I2C_TYPE_1,command);
I2cWaitAck(I2C_TYPE_1);
I2cStart(I2C_TYPE_1);
I2cSendByte(I2C_TYPE_1,(unsigned char)(address|0x01));
I2cWaitAck(I2C_TYPE_1);
for(i_temp=0;i_temp<(length-1);i_temp++)
{
DataTemp = I2cReadByte(I2C_TYPE_1,ACK);
*data++ = DataTemp;
}
DataTemp = I2cReadByte(I2C_TYPE_1,NOACK);;
*data = DataTemp;
I2cStop(I2C_TYPE_1);
}
void NCA9555_int( void )
{
//设置所有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]);
}
/*
按位写输出GPIO寄存器
led:GPIO0-GPIO15
state:0输出低电平,1输出高电平。
*/
void NCA9555_writer_bit( int led ,int state)
{
if(led>=16)
return;
unsigned char readData[2] = {0};
NCA9555_Read_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_OUTPUT_PORT,2,readData);
if(state)
{
if(led>=8)
{
readData[0]= readData[0] ;
readData[1]= readData[1] | (char)(1<<(led-8));
}else{
readData[0]= readData[0] | (char)(1<<(led));
readData[1]= readData[1];
}
}else
{
if(led>=8)
{
readData[0]= readData[0] ;
readData[1]= readData[1] & ~(char)(1<<(led-8));
}else{
readData[0]= readData[0] & ~(char)(1<<(led));
readData[1]= readData[1];
}
}
NCA9555_Write_Data(MCP23017_I2C_ADDR_WR,REGISTER_0_OUTPUT_PORT,2,&readData[0]);
}
//流水灯
void NCA9555_Task( void )
{
timeCount++;
if(timeCount == 10000)//10000次才接近1s
{
NCA9555_writer_bit(2,0);
}
else if(timeCount == 20000)
{
NCA9555_writer_bit(2,1);
NCA9555_writer_bit(1,0);
}
else if(timeCount == 30000)
{
NCA9555_writer_bit(1,1);
NCA9555_writer_bit(0,0);
}
else if(timeCount == 40000)
{
NCA9555_writer_bit(0,1);
NCA9555_writer_bit(15,0);
}
else if(timeCount == 50000)
{
NCA9555_writer_bit(15,1);
NCA9555_writer_bit(14,0);
}
else if(timeCount == 60000)
{
NCA9555_writer_bit(14,1);
NCA9555_writer_bit(13,0);
}
else if(timeCount == 70000)
{
NCA9555_writer_bit(13,1);
NCA9555_writer_bit(9,0);
}
else if(timeCount == 80000)
{
NCA9555_writer_bit(9,1);
NCA9555_writer_bit(8,0);
}
else if(timeCount == 90000)
{
NCA9555_writer_bit(8,1);
NCA9555_writer_bit(5,0);
}
else if(timeCount == 100000)
{
NCA9555_writer_bit(5,1);
NCA9555_writer_bit(4,0);
}
else if(timeCount == 110000)
{
NCA9555_writer_bit(4,1);
NCA9555_writer_bit(3,0);
} else if(timeCount == 120000)
{
timeCount = 0;
NCA9555_writer_bit(3,1);
}
}
I2c.c
#define I2C1_ENABLE
INT8U GLOBLE_START = 0;
/* IO方向设置 */
#if (defined(I2C1_ENABLE) || defined(I2C2_ENABLE) || defined(I2C3_ENABLE) || defined(I2C4_ENABLE))
/* 输入模式 - 浮空输入 */
#define GPIO_DIR_SET_INPUT(GPIOx, GPIO_Pin_Num) { \
GPIO_CTL(GPIOx) &= ~GPIO_MODE_MASK(GPIO_Pin_Num); \
}
/* 输出模式 - 开漏输出 */
#define GPIO_DIR_SET_PPOUT(GPIOx, GPIO_Pin_Num) { \
GPIO_CTL(GPIOx) &= ~GPIO_MODE_MASK(GPIO_Pin_Num); \
GPIO_CTL(GPIOx) |= GPIO_MODE_SET(GPIO_Pin_Num,0x01); \
GPIO_OMODE(GPIOx) |= BIT(GPIO_Pin_Num); \
}
#endif
#if defined(I2C1_ENABLE)
/* I2C1时钟线 */
#define I2C1_SCL_H gpio_bit_set(GPIOC, GPIO_PIN_5)
#define I2C1_SCL_L gpio_bit_reset(GPIOC, GPIO_PIN_5)
/* I2C1数据线 */
#define I2C1_SDA_H gpio_bit_set(GPIOC, GPIO_PIN_4)
#define I2C1_SDA_L gpio_bit_reset(GPIOC, GPIO_PIN_4)
#define I2C1_READ gpio_input_bit_get (GPIOC, GPIO_PIN_4)
#define I2C1_SDA_IN GPIO_DIR_SET_INPUT(GPIOC, 4)
#define I2C1_SDA_OUT GPIO_DIR_SET_PPOUT(GPIOC, 4)
#endif
void I2cInit(E_I2C_TYPE type)
{
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
rcu_periph_clock_enable(RCU_GPIOC);
/* 配置 IIC_SCL --> PA4 引脚为开漏输出 */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_output_options_set(GPIOC, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_4);
/* 配置 IIC_SDA --> PA5 引脚为开漏输出 */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOC, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_5);
/* 拉高通信线 */
I2C1_SCL_H;
I2C1_SDA_H;
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
rcu_periph_clock_enable(RCU_GPIOB);
/* 配置 IIC_SCL --> PB8 引脚为开漏输出 */
gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
/* 配置 IIC_SDA --> PB9 引脚为开漏输出 */
gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_9);
/* 拉高通信线 */
I2C2_SCL_H;
I2C2_SDA_H;
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOC);
/* 拉高通信线 */
I2C3_SCL_H;
I2C3_SDA_H;
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
rcu_periph_clock_enable(RCU_GPIOD);
/* 配置 IIC_SCL --> PD12 引脚为开漏输出 */
gpio_init(GPIOD, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_12);
/* 配置 IIC_SDA --> PD13 引脚为开漏输出 */
gpio_init(GPIOD, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_13);
/* 拉高通信线 */
I2C4_SCL_H;
I2C4_SDA_H;
break;
#endif
default:
break;
}
}
void I2cStart(E_I2C_TYPE type)
{
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
I2C1_SDA_OUT;/* SDA设置为输出 */
I2C1_SCL_H;
I2C1_SDA_H;
DelayUs(4);
I2C1_SDA_L; /* 起始信号:SDA由高变低,SCL为高 */
DelayUs(4);
I2C1_SCL_L; /* 拉低SCL,准备发送或接收数据 */
GLOBLE_START = 1;
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SDA_OUT;/* SDA设置为输出 */
I2C2_SCL_H;
I2C2_SDA_H;
DelayUs(4);
I2C2_SDA_L; /* 起始信号:SDA由高变低,SCL为高 */
DelayUs(4);
I2C2_SCL_L; /* 拉低SCL,准备发送或接收数据 */
I2C2_SDA_IN;//ADD!!!!!!!!!!!
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SDA_OUT;/* SDA设置为输出 */
I2C3_SCL_H;
I2C3_SDA_H;
DelayUs(4);
I2C3_SDA_L; /* 起始信号:SDA由高变低,SCL为高 */
DelayUs(4);
I2C3_SCL_L; /* 拉低SCL,准备发送或接收数据 */
I2C3_SDA_IN;//ADD!!!!!!!!!!!
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SDA_OUT;/* SDA设置为输出 */
I2C4_SCL_H;
I2C4_SDA_H;
DelayUs(4);
I2C4_SDA_L; /* 起始信号:SDA由高变低,SCL为高 */
DelayUs(4);
I2C4_SCL_L; /* 拉低SCL,准备发送或接收数据 */
I2C4_SDA_IN;//ADD!!!!!!!!!!!
break;
#endif
default:
break;
}
}
void I2cStop(E_I2C_TYPE type)
{
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
I2C1_SDA_OUT;/* SDA设置为输出 */
I2C1_SDA_L;
I2C1_SCL_H;
DelayUs(4);
I2C1_SDA_H; /* 结束信号:SDA由低变高,SCL为高 */
DelayUs(4);
I2C1_SCL_H; /* 拉高SCL,不接收数据 */
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SDA_OUT;/* SDA设置为输出 */
I2C2_SDA_L;
I2C2_SCL_H;
DelayUs(4);
I2C2_SDA_H; /* 结束信号:SDA由低变高,SCL为高 */
DelayUs(4);
I2C2_SCL_H; /* 拉高SCL,不接收数据 */
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SDA_OUT;/* SDA设置为输出 */
I2C3_SDA_L;
I2C3_SCL_H;
DelayUs(4);
I2C3_SDA_H; /* 结束信号:SDA由低变高,SCL为高 */
DelayUs(4);
I2C3_SCL_H; /* 拉高SCL,不接收数据 */
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SDA_OUT;/* SDA设置为输出 */
I2C4_SDA_L;
I2C4_SCL_H;
DelayUs(4);
I2C4_SDA_H; /* 结束信号:SDA由低变高,SCL为高 */
DelayUs(4);
I2C4_SCL_H; /* 拉高SCL,不接收数据 */
break;
#endif
default:
break;
}
}
INT8U I2cWaitAck(E_I2C_TYPE type)
{
INT8U err_time = 0;
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
I2C1_SDA_IN;/* SDA设置为输入 */
I2C1_SDA_H;
DelayUs(1);
I2C1_SCL_H;
DelayUs(1);
while(I2C1_READ)
{
err_time++;
if(err_time > 250)
{
I2cStop(I2C_TYPE_1);
return 1;
}
}
I2C1_SCL_L;/* 拉低时钟线 */
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SDA_IN;/* SDA设置为输入 */
I2C2_SDA_H;
DelayUs(1);
I2C2_SCL_H;
DelayUs(1);
while(I2C2_READ)
{
err_time++;
if(err_time > 250)
{
I2cStop(I2C_TYPE_2);
return 1;
}
}
I2C2_SCL_L;/* 拉低时钟线 */
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SDA_IN;/* SDA设置为输入 */
I2C3_SDA_H;
DelayUs(1);
I2C3_SCL_H;
DelayUs(1);
while(I2C3_READ)
{
err_time++;
if(err_time > 250)
{
I2cStop(I2C_TYPE_3);
return 1;
}
}
I2C3_SCL_L;/* 拉低时钟线 */
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SDA_IN;/* SDA设置为输入 */
I2C4_SDA_H;
DelayUs(1);
I2C4_SCL_H;
DelayUs(1);
while(I2C4_READ)
{
err_time++;
if(err_time > 250)
{
I2cStop(I2C_TYPE_4);
return 1;
}
}
I2C4_SCL_L;/* 拉低时钟线 */
break;
#endif
default:
break;
}
return 0;
}
static void I2cAck(E_I2C_TYPE type)
{
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
I2C1_SCL_L;
I2C1_SDA_OUT;/* SDA设置为输出 */
I2C1_SDA_L;
DelayUs(2);
I2C1_SCL_H;
DelayUs(2);
I2C1_SCL_L;
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SCL_L;
I2C2_SDA_OUT;/* SDA设置为输出 */
I2C2_SDA_L;
DelayUs(2);
I2C2_SCL_H;
DelayUs(2);
I2C2_SCL_L;
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SCL_L;
I2C3_SDA_OUT;/* SDA设置为输出 */
I2C3_SDA_L;
DelayUs(2);
I2C3_SCL_H;
DelayUs(2);
I2C3_SCL_L;
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SCL_L;
I2C4_SDA_OUT;/* SDA设置为输出 */
I2C4_SDA_L;
DelayUs(2);
I2C4_SCL_H;
DelayUs(2);
I2C4_SCL_L;
break;
#endif
default:
break;
}
}
static void I2cNotAck(E_I2C_TYPE type)
{
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
I2C1_SCL_L;
I2C1_SDA_OUT;/* SDA设置为输出 */
I2C1_SDA_H;
DelayUs(2);
I2C1_SCL_H;
DelayUs(2);
I2C1_SCL_L;
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SCL_L;
I2C2_SDA_OUT;/* SDA设置为输出 */
I2C2_SDA_H;
DelayUs(2);
I2C2_SCL_H;
DelayUs(2);
I2C2_SCL_L;
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SCL_L;
I2C3_SDA_OUT;/* SDA设置为输出 */
I2C3_SDA_H;
DelayUs(2);
I2C3_SCL_H;
DelayUs(2);
I2C3_SCL_L;
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SCL_L;
I2C4_SDA_OUT;/* SDA设置为输出 */
I2C4_SDA_H;
DelayUs(2);
I2C4_SCL_H;
DelayUs(2);
I2C4_SCL_L;
break;
#endif
default:
break;
}
}
void I2cSendByte(E_I2C_TYPE type, INT8U txd)
{
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
// I2C1_SDA_OUT;/* SDA设置为输出 */
if(GLOBLE_START == 0) //qiang 为了阻止start信号后产生尖刺
{
I2C1_SDA_OUT;/* SDA设置为输出 */
}
else
{
GLOBLE_START = 0;
}
I2C1_SCL_L;/* 拉低时钟开始数据传输 */
for(INT8U i = 0; i < 8; i++)
{
if((txd & 0x80) >> 7)
{
I2C1_SDA_H;
}
else
{
I2C1_SDA_L;
}
txd <<= 1;
DelayUs(2);
I2C1_SCL_H;
DelayUs(2);
I2C1_SCL_L;
DelayUs(2);
}
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SDA_OUT;/* SDA设置为输出 */
I2C2_SCL_L;/* 拉低时钟开始数据传输 */
for(INT8U i = 0; i < 8; i++)
{
if((txd & 0x80) >> 7)
{
I2C2_SDA_H;
}
else
{
I2C2_SDA_L;
}
txd <<= 1;
DelayUs(2);
I2C2_SCL_H;
DelayUs(2);
I2C2_SCL_L;
DelayUs(2);
}
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SDA_OUT;/* SDA设置为输出 */
I2C3_SCL_L;/* 拉低时钟开始数据传输 */
for(INT8U i = 0; i < 8; i++)
{
if((txd & 0x80) >> 7)
{
I2C3_SDA_H;
}
else
{
I2C3_SDA_L;
}
txd <<= 1;
DelayUs(2);
I2C3_SCL_H;
DelayUs(2);
I2C3_SCL_L;
DelayUs(2);
}
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SDA_OUT;/* SDA设置为输出 */
I2C4_SCL_L;/* 拉低时钟开始数据传输 */
for(INT8U i = 0; i < 8; i++)
{
if((txd & 0x80) >> 7)
{
I2C4_SDA_H;
}
else
{
I2C4_SDA_L;
}
txd <<= 1;
DelayUs(2);
I2C4_SCL_H;
DelayUs(2);
I2C4_SCL_L;
DelayUs(2);
}
break;
#endif
default:
break;
}
}
INT8U I2cReadByte(E_I2C_TYPE type, INT8U ack)
{
INT8U receive = 0;
switch(type)
{
#if defined(I2C1_ENABLE)
case I2C_TYPE_1:
I2C1_SDA_IN;/* SDA设置为输入 */
for(INT8U i = 0; i < 8; i++)
{
I2C1_SCL_L;
DelayUs(2);
I2C1_SCL_H; //拉高时钟线-读数据
receive <<= 1;
if(I2C1_READ)
{
receive++;
}
DelayUs(1);
}
if(!ack)
{
I2cNotAck(I2C_TYPE_1);/* 发送NotACK */
}
else
{
I2cAck(I2C_TYPE_1); /* 发送ACK */
}
break;
#endif
#if defined(I2C2_ENABLE)
case I2C_TYPE_2:
I2C2_SDA_IN;/* SDA设置为输入 */
for(INT8U i = 0; i < 8; i++)
{
I2C2_SCL_L;
DelayUs(2);
I2C2_SCL_H;
receive <<= 1;
if(I2C2_READ)
{
receive++;
}
DelayUs(1);
}
if(!ack)
{
I2cNotAck(I2C_TYPE_2);/* 发送NotACK */
}
else
{
I2cAck(I2C_TYPE_2); /* 发送ACK */
}
break;
#endif
#if defined(I2C3_ENABLE)
case I2C_TYPE_3:
I2C3_SDA_IN;/* SDA设置为输入 */
for(INT8U i = 0; i < 8; i++)
{
I2C3_SCL_L;
DelayUs(2);
I2C3_SCL_H;
receive <<= 1;
if(I2C3_READ)
{
receive++;
}
DelayUs(1);
}
if(!ack)
{
I2cNotAck(I2C_TYPE_3);/* 发送NotACK */
}
else
{
I2cAck(I2C_TYPE_3); /* 发送ACK */
}
break;
#endif
#if defined(I2C4_ENABLE)
case I2C_TYPE_4:
I2C4_SDA_IN;/* SDA设置为输入 */
for(INT8U i = 0; i < 8; i++)
{
I2C4_SCL_L;
DelayUs(2);
I2C4_SCL_H;
receive <<= 1;
if(I2C4_READ)
{
receive++;
}
DelayUs(1);
}
if(!ack)
{
I2cNotAck(I2C_TYPE_4);/* 发送NotACK */
}
else
{
I2cAck(I2C_TYPE_4); /* 发送ACK */
}
break;
#endif
default:
break;
}
return receive;
}
#endif