For friends who are engaged in embedded development, the I2C protocol is really familiar. Many chips use I2C for corresponding configuration. Today, we will just talk about this I2C protocol, and implement an i2c driver through the ordinary GPIO port.
In addition to GND, the communication of i2c is mainly completed by two wires, SDA and SCL, and the external chip can be connected to these two wires to realize communication;
#define SETSCL1() GPIO_OutputCtr(GPIO_Pin_3,SET) //拉高SCL管脚
#define CLRSCL1() GPIO_OutputCtr(GPIO_Pin_3,RESET) //拉低SCL管脚
#define SETSDA1() GPIO_OutputCtr(GPIO_Pin_4,SET) //拉高SDA管脚
#define CLRSDA1() GPIO_OutputCtr(GPIO_Pin_4,RESET) //拉低SDA管脚
#define GET_SDA1_STATUAS() GPIO_GetInputLevel(GPIO_Pin_4) //获取SDA管脚的高低电平
#define GET_SCL1_STATUAS() GPIO_GetInputLevel(GPIO_Pin_3) //获取SCL管脚的高低电平
static unsigned char F1;
void myIIC1_Init(void)
{
/*将SDA和SCl配置成输入。因为平台不一致,就不具体写了*/
}
/**将SDA设置为输入功能*/
void sda1_in_set(void)
{
}
/**将SDA设置为输出功能,并且根据之前的输入状态来判断是否要拉高,还是拉低*/
void sda1_out_set(void)
{
}
/**将SCL设置为输出功能,并且拉高*/
void scl1_out_set(void)
{
}
/**将SCL设置为输入功能*/
void scl1_in_set(void)
{
}
/**起始条件:当SCL高电平时,SDA由高电平向低电平转换;*/
void iic1_start(void)
{
uint8_t temp=5;
SETSDA1(); //sda 1
SETSCL1(); //sck 1
sda1_out_set();
scl1_out_set();
CLRSDA1(); //sda 0
while(temp--);
CLRSCL1(); //sck 0
}
/**停止条件:当SCL高电平时,SDA由低电平向高电平转换。*/
void iic1_stop(void)
{
uint16_t i;
CLRSDA1(); //sda 0
SETSCL1(); //sck 1
SETSCL1(); //sck 1
SETSDA1(); //sda 1
if(F1 == 1)
{
for(i=0;i<100;i++);
}
myIIC1_Init();
}
/*数据接收方收到传输的一个字节数据后,需要给出响应,此时处在第九个时钟,发送端释放SDA线控制权,将SDA电平拉高,
由接收方控制。若希望继续,则给出“应答(ACK)”信号,即SDA为低电平;反之给出“非应答(NACK)”信号,
即SDA为高电平。*/
void check_ACK1(void)
{
uint16_t i;
sda1_in_set(); //sda in
scl1_in_set(); //scl in
F1 = 0;
i = 0;
while((GET_SDA1_STATUAS() != RESET)&&(i<200))
{
i++;
}
if(i>= 200)
{
F1 = 1;
}
CLRSCL1(); //sck 0
sda1_out_set(); //sda out
scl1_out_set();
CLRSCL1(); //sck 1
for(int j = 0; j< 160; j++); //这地方加个延时是因为实际测试过程中,有个外部芯片,会将SCL拉高;
}
void send_ACK1(void)
{
uint16_t i;
sda1_out_set(); //sda out
CLRSDA1();
SETSCL1(); //sck 1
for(i=2;i>0;i--); //short delay
CLRSCL1(); //sck 0
sda1_in_set(); //sda in
}
void send_NOACK1(void)
{
SETSDA1(); //sda 1
SETSCL1(); //sck 1
CLRSCL1(); //sck 0
}
/*发送data数据*/
void IIC1SendByte(unsigned char ch)
{
unsigned char n=8;
while(n--)
{
if((ch&0x80) == 0x80) //
{
SETSDA1(); //sda 1
SETSCL1(); //sck 1
SETSCL1();
CLRSCL1(); //sck 0
}
else
{
CLRSDA1(); //sda 0 //
SETSCL1(); //sck 1
SETSCL1();
CLRSCL1(); //sck 0
}
ch = ch<<1; //
}
}
/*接收数据*/
unsigned char IIC1receiveByte(void)
{
unsigned char n=8;
unsigned char tdata=0;
sda1_in_set(); //sda in
while(n--)
{
SETSCL1(); //sck 1
tdata = tdata<<1; //
if(GET_SDA1_STATUAS() != RESET)
{
tdata = tdata|0x01;
}
else
{
tdata = tdata&0xfe;
}
CLRSCL1(); //sck 0
}
sda1_out_set(); //sda out
return(tdata);
}
unsigned char IIC1_write_Nbytes(unsigned char devAddr,unsigned char reg_add,unsigned char *buf,unsigned char len)
{
uint8_t i;
iic1_start(); //
IIC1SendByte(devAddr); //
check_ACK1();
if(F1 == 1)
{
for(i=0;i<100;i++);
myIIC1_Init();
return 1;
}
IIC1SendByte(reg_add); //
check_ACK1(); //
if(F1 == 1)
{
for(i=0;i<100;i++);
myIIC1_Init();
return 1;
}
for(i=0;i<len;i++)
{
IIC1SendByte(buf[i]); //
check_ACK1(); //
if(F1 == 1)
{
for(i=0;i<100;i++);
myIIC1_Init();
return 1;
}
}
iic1_stop();
myIIC1_Init();
if(F1 == 1)
{
return 1;
}
return 0;
}
unsigned char IIC1_receive_Nbytes(unsigned char devAddr,unsigned char reg_add,unsigned char *buf,unsigned char len)
{
unsigned char i;
uint16_t temp=0;
iic1_start();
IIC1SendByte(devAddr); //
check_ACK1();
if(F1 == 1)
{
for(i=0;i<100;i++);
myIIC1_Init();
return 1;
}
IIC1SendByte(reg_add);
check_ACK1();
if(F1 == 1)
{
iic1_stop();
myIIC1_Init();
return 1;
}
iic1_start();
IIC1SendByte(devAddr+1);
check_ACK1();
if(F1 == 1)
{
iic1_stop();
myIIC1_Init();
return 1;
}
for(i=0;i<len;i++)
{
temp=150;
while(temp--);
buf[i]=IIC1receiveByte();
if(i!=(len-1))
{
send_ACK1();
}
}
send_NOACK1();
iic1_stop();
myIIC1_Init();
if(F1 == 1)
{
for(i=0;i<100;i++);
return 1;
}
return 0;
}
i2C normal writing sequence;
the writing sequence realized by the above code
i2C normal reading sequence;
the reading sequence realized by the above code