同步串行数据传输总线I2C :十分完善的总线协议。只有两根信号线(双向数据线SDA和时钟线SCL),可构成多机系统.
我测试了硬件I2C,总感觉哪里有点问题。索性就选择了模拟I2C来做
这里用到了两个I2C 一个用于控制时钟芯片,一个用于控制铁电
[code]
/****************************************************************
// Summary: 使DA的引脚为输出状态
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
static void SetI2CDAOut(u8 I2Cx)
{
GPIO_InitTypeDef GPIO_InitStructure;
if(SIM_I2C1 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = RXSDA; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_RX8025, &GPIO_InitStructure);
}
else if(SIM_I2C2 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = FM24SDA; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_FM24, &GPIO_InitStructure);
}
}
/****************************************************************
// Summary: 使DA的引脚为输入状态
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
static void SetI2CDAIn(u8 I2Cx)
{
GPIO_InitTypeDef GPIO_InitStructure;
if(SIM_I2C1 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = RXSDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_RX8025, &GPIO_InitStructure);
}
else if(SIM_I2C2 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = FM24SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_FM24, &GPIO_InitStructure);
}
}
/****************************************************************
// Summary: 产生I2C START信号
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_Start(u8 I2Cx)
{
SetI2CDAOut(I2Cx); //sda输出
if(SIM_I2C1 == I2Cx)
{
I2C1_SDA_1;
I2C1_SCL_1;
Delay_us(4);
I2C1_SDA_0; //CLK is high, DATA change form high to low
Delay_us(4);
I2C1_SCL_0; //钳住I2C总线, 准备发送或接收数据
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SDA_1;
I2C2_SCL_1;
Delay_us(4);
I2C2_SDA_0;
Delay_us(4);
I2C2_SCL_0;
}
}
/****************************************************************
// Summary: 产生I2C STOP信号
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_Stop(u8 I2Cx)
{
SetI2CDAOut(I2Cx);
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0;
I2C1_SDA_0; //CLK is high DATA change form low to high
Delay_us(4);
I2C1_SCL_1;
I2C1_SDA_1; //发送I2C总线结束信号
Delay_us(4);
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
I2C2_SDA_0; //CLK is high DATA change form low to high
Delay_us(4);
I2C2_SCL_1;
I2C2_SDA_1; //发送I2C总线结束信号
Delay_us(4);
}
}
/****************************************************************
// Summary: 等待应答信号
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [out/u8] 成功与否
****************************************************************/
u8 I2C_WaitAck(u8 I2Cx)
{
u8 u8ErrTime = 0;
SetI2CDAIn(I2Cx); //SDA设置为输入
if(SIM_I2C1 == I2Cx)
{
I2C1_SDA_1;
Delay_us(1);
I2C1_SCL_1;
Delay_us(1);
ResetWatchDog();
while(READ_I2C1SDA)
{
u8ErrTime ++;
if(u8ErrTime > 250)
{
I2C_Stop(I2Cx);
return 0;
}
}
I2C1_SCL_0;
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SDA_1;
Delay_us(1);
I2C2_SCL_1;
Delay_us(1);
ResetWatchDog();
while(READ_I2C2SDA)
{
u8ErrTime ++;
if(u8ErrTime > 250)
{
I2C_Stop(I2Cx);
return 0;
}
}
I2C2_SCL_0;
}
return 1;
}
/****************************************************************
// Summary: 主机产生ACK应答
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_Ack(u8 I2Cx)
{
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0;
SetI2CDAOut(I2Cx);
I2C1_SDA_0;
Delay_us(2);
I2C1_SCL_1;
Delay_us(2);
I2C1_SCL_0;
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
SetI2CDAOut(I2Cx);
I2C2_SDA_0;
Delay_us(2);
I2C2_SCL_1;
Delay_us(2);
I2C2_SCL_0;
}
}
/****************************************************************
// Summary: 主机不产生ACK应答
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_NAck(u8 I2Cx)
{
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0;
SetI2CDAOut(I2Cx);
I2C1_SDA_1;
Delay_us(2);
I2C1_SCL_1;
Delay_us(2);
I2C1_SCL_0;
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
SetI2CDAOut(I2Cx);
I2C2_SDA_1;
Delay_us(2);
I2C2_SCL_1;
Delay_us(2);
I2C2_SCL_0;
}
}
/****************************************************************
// Summary: I2C发送一个字节
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
// [in/u8]u8Data 发送的字节
//
// return: [void]
****************************************************************/
void I2C_SendByte(u8 I2Cx, u8 u8Data)
{
u8 t;
SetI2CDAOut(I2Cx);
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0; //拉低时钟开始数据传输
for(t = 0; t < 8; t ++)
{
if((u8Data & 0x80) >> 7)
I2C1_SDA_1;
else
I2C1_SDA_0;
u8Data <<= 1;
Delay_us(2);
I2C1_SCL_1;
Delay_us(2);
I2C1_SCL_0;
Delay_us(2);
}
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
for(t = 0; t < 8; t ++)
{
if((u8Data & 0x80) >> 7)
I2C2_SDA_1;
else
I2C2_SDA_0;
u8Data <<= 1;
Delay_us(2);
I2C2_SCL_1;
Delay_us(2);
I2C2_SCL_0;
Delay_us(2);
}
}
}
/****************************************************************
// Summary: 读一个字节
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
// [in/u8]ack ack=1时,发送ACK; ack=0,发送nACK
//
// return: [out/u8]返回得到的字节
****************************************************************/
u8 I2C_ReadByte(u8 I2Cx, u8 ack)
{
u8 i, receive = 0;
SetI2CDAIn(I2Cx); //SDA设置为输入
if(SIM_I2C1 == I2Cx)
{
for(i = 0; i < 8; i ++)
{
I2C1_SCL_0;
Delay_us(2);
I2C1_SCL_1;
receive <<= 1;
if(READ_I2C1SDA)
receive ++;
Delay_us(1);
}
if(!ack)
I2C_NAck(I2Cx); //发送nACK
else
I2C_Ack(I2Cx); //发送ACK
}
else if(SIM_I2C2 == I2Cx)
{
for(i = 0; i < 8; i ++)
{
I2C2_SCL_0;
Delay_us(2);
I2C2_SCL_1;
receive <<= 1;
if(READ_I2C2SDA)
receive ++;
Delay_us(1);
}
if(!ack)
I2C_NAck(I2Cx); //发送nACK
else
I2C_Ack(I2Cx); //发送ACK
}
return receive;
}
[/code]