GPIO口模拟iic读取数据
iic协议因简单而常常被用作芯片与外围器件之间的通信,当芯片因iic资源不足时,经常使用gpio口模仿iic通信。近日做了一个gpio口模拟iic读取数据的功能,遂记录之:
话不多说,直接上代码:
1.主代码。
//功能,读取数据到data数组
u8 get_data(uint8_t* data)
{
u32 i=0;
START_I2C();
if(SendByte_I2C(WRITE_SLAVE_ADDRESS)) Error_I2C();
if(SendByte_I2C(Master_Tx_Buffer[0])) Error_I2C(); //Master_Tx_Buffer[0]为寄存器地址
STOP_I2C();
START_I2C();
if(SendByte_I2C(READ_SLAVE_ADDRESS)) Error_I2C();
for(i = 0; i < BufferSize; i++)
{
if (i < BufferSize-1)
Master_Rx_Buffer[i] = ReadByte_I2C(0);
else
Master_Rx_Buffer[i] = ReadByte_I2C(1); //数据保存到此数组中
}
STOP_I2C();
}
2.各功能代码。
//iic开始信号
void START_I2C()
{
SET_SDA_ON();
Delay();
SET_SCL_ON();
Delay();
SET_SDA_OFF();
Delay();
SET_SCL_OFF();
Delay();
}
//iic停止信号
void STOP_I2C()
{
SET_SDA_OFF();
Delay();
SET_SCL_ON();
Delay();
SET_SDA_ON();
Delay();
}
//iic发送数据
u8 SendByte_I2C(u8 byte)
{
u8 bit_count, ACK;
for(bit_count = 0; bit_count < 8; bit_count++)
{
if((byte << bit_count) & 0x80)
SET_SDA_ON();
else
SET_SDA_OFF();
Delay();
SET_SCL_ON();
Delay();
SET_SCL_OFF();
}
SET_SDA_ON();
Delay();
SET_SCL_ON();
Delay();
ACK=GET_SDA();
SET_SCL_OFF();
Delay();
return ACK;
}
//iic读取数据
u8 ReadByte_I2C(u8 ACK_bit)
{
u8 bit_count, tmp = 0;
SET_SDA_ON();
for(bit_count = 0; bit_count < 8; bit_count++)
{
SET_SCL_OFF();
Delay();
SET_SCL_ON();
Delay();
tmp = tmp << 1;
if(GET_SDA()) tmp = tmp + 1;
}
SET_SCL_OFF();
if(ACK_bit)
{
SET_SDA_ON();
}
else
{
SET_SDA_OFF();
}
Delay();
SET_SCL_ON();
Delay();
SET_SCL_OFF();
return tmp;
}
//iic错误
void Error_I2C()
{
while(1)
;
}