这点在开头已经说过这里再说一下:
由于I2C总线占用的I/O仅需要2根,在很多的实际使用过程中,会使用GPIO引脚来模拟I2C的SDA引脚和SCL引脚,并使用程序来实现I2C协议时序。
软件模拟I2C协议的优点如下。
(1)不需要专门的硬件I2C的控制器。
(2)引脚可以任意分配,方便PCB布线。
(3)软件修改灵活。
缺点:由于采用软件指令会产生时间的延时,不能用于一些时间要求较高的场合。
说明:I2C引脚配置和普通IO配置的过程是一样的。
1.引脚工作模式初始化将SDA设置为输出模式
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_Init(GPIOH, &GPIO_InitStructure);
}
对于IIC主机来说,SCL在整个通信过程中都是作为输出模式的、
//将SCL设置为输出模式
void SCL_OUT(void)//PA1
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(EEPROM_I2C_SCL_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_Init(EEPROM_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
}
对IIC主机,SDA在整个通信过程中,输出数据的时候位输出模式,接収数据或检查ACK信号时为输入模式。
//将SDA设置为输入模式
void SDA_IN(void) //PA0
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(EEPROM_I2C_SDA_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(EEPROM_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
}
//将SDA设置为输出模式
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(EEPROM_I2C_SDA_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_Init(EEPROM_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
}
//初始化IIC
void IIC_Init(void)
{
SDA_OUT();
SCL_OUT();
IIC_SCL_Hi ;
IIC_SDA_Hi;
}
2.I2C引脚读写控制
IO操作函数
#define IIC_SCL_ Hi GPIO_SetBits(GPIOH,GPIO_Pin_4) //SCL输出高电平
#define IIC_SCL_ Lo GPIO_ResetBits(GPIOH,GPIO_Pin_4) //SCL输出低电平
#define IIC_SDA_ Hi GPIO_SetBits(GPIOH,GPIO_Pin_5) //SDA输出高电平
#define IIC_SDA_ Lo GPIO_ResetBits(GPIOH,GPIO_Pin_5) //SDA输出低电平
#define IIC_SDA_In GPIO_ReadInputDataBit (GPIOH,GPIO_Pin_5) //输入SDA状态
主机产生IIC起始信号
起始信号:当SCL为高电平时,SDA由高电平转向低电平,开始进行数据的传输工作。开始信号由主机产生。
停止信号:当SCL为高电平时,SDA由低电平转高向电平,结束数据的传输工作。停止信号由主机产生。
主机每发送一个数据到总线,而且从机每成功收到数据后,都会有一个响应(ACK信号0)给主机,主机根据检测到的总线上的电平,判断通信是否成功(0成功,1失败)。
当主机成功接收到从机发送过来的数据,若主机需要接収继续接收数据,则主机需要返回给从机一个应答信号,若接収的是最后一个数据,主机会返回给从机一个非应答信号。