I2C:
串行的8位双向数据传输位速率,在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。
特点:
1.通信线少,布线简单
2.总线可以并联多个设备,不需要增加通信线,扩展性好
3.协议简单,通信速度中等,还可以用IO口模拟
模拟I2C:
STM32F1模拟标准I2C
//初始化i2c两个引脚
void MYI2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructing;
RCC_APB2PeriphClockCmd(I2C_SDA_RCC , ENABLE);
RCC_APB2PeriphClockCmd(I2C_SCL_RCC , ENABLE);
GPIO_InitStructing.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructing.GPIO_Pin = SDA_PIN;
GPIO_InitStructing.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(SDA_PORT, &GPIO_InitStructing);
GPIO_InitStructing.GPIO_Pin = SCL_PIN;
GPIO_Init(SCL_PORT, &GPIO_InitStructing);
}
//配置为输入模式
void GPIO_SDA_INPUT(void)
{
GPIO_InitTypeDef GPIO_InitStructing;
RCC_APB2PeriphClockCmd(I2C_SDA_RCC , ENABLE);
GPIO_InitStructing.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructing.GPIO_Pin = SDA_PIN;
GPIO_InitStructing.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(SDA_PORT, &GPIO_InitStructing);
}
//配置为输出模式
void GPIO_SDA_OUTPUT(void)
{
GPIO_InitTypeDef GPIO_InitStructing;
RCC_APB2PeriphClockCmd(I2C_SDA_RCC , ENABLE);
GPIO_InitStructing.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructing.GPIO_Pin = SDA_PIN;
GPIO_InitStructing.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(SDA_PORT, &GPIO_InitStructing);
}
//输出0/1
void SDA_OUT(bool num)
{
if(num)
{
GPIO_SetBits(SDA_PORT, SDA_PIN);
}
else
{
GPIO_ResetBits(SDA_PORT, SDA_PIN);
}
}
//读取引脚高低
bool SDA_IN(void)
{
bool flag = 1;
uint32_t count = 0;
GPIO_SDA_INPUT();
while(count < 80)
{
count++;
flag &= GPIO_ReadInputDataBit(SDA_PORT, SDA_PIN);
}
delay();
GPIO_SDA_OUTPUT();
return flag;
}
//时钟输出
void SCL_OUT(bool num)
{
if(num){
GPIO_SetBits(SCL_PORT, SCL_PIN);
}
else{
GPIO_ResetBits(SCL_PORT, SCL_PIN);
}
}
//开始
void IIC_start(void)
{
SDA_OUT(1);
SCL_OUT(1);
delay();
SDA_OUT(0);
delay();
SCL_OUT(0);
}
//停止
void IIC_Stop(void)
{
SCL_OUT(0);
SDA_OUT(0);
SCL_OUT(1);
delay();
SDA_OUT(1);
}
//应答
void IIC_Ack(unsigned char ackbit)
{
SCL_OUT(0);
if(ackbit)
{
SDA_OUT(0);
}
else
{
SDA_OUT(1);
}
delay();
SCL_OUT(1);
delay();
SCL_OUT(0);
}
//等待应答
bool IIC_WaitAck(void)
{
SDA_OUT(1);
delay();
SCL_OUT(1);
delay();
while(SDA_IN())
{
SCL_OUT(0);
IIC_Stop();
return 0;
}
SCL_OUT(0);
return 1;
}
//发送一个字节
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA_OUT(1);
}
else
{
SDA_OUT(0);
}
delay();
SCL_OUT(1);
byt <<= 1;
delay();
SCL_OUT(0);
}
}
//读取一个字节
unsigned char IIC_RecByte(void)
{
unsigned char da = 0;
unsigned char i;
for(i=0;i<8;i++)
{
SCL_OUT(1);
delay();
da <<= 1;
if(SDA_IN())
da |= 0x01;
SCL_OUT(0);
delay();
}
return da;
}
针对AT24C02的一个应用
void AT24_write(uint8_t adr,uint8_t data)
{
IIC_start();
IIC_SendByte(0xa0);//0xa0 + AT24C02器件地址 0xa0表示写
IIC_WaitAck();
IIC_SendByte(adr);//写入的地址
IIC_WaitAck();
IIC_SendByte(data);//写入的数据
IIC_WaitAck();
IIC_Stop();
delay();
}
uint8_t AT24_read(uint8_t adr)
{
uint8_t data;
IIC_start();
IIC_SendByte(0xa0);//0xa0 + AT24C02器件地址 0xa0表示写
IIC_WaitAck();
IIC_SendByte(adr);//想要读取的地址
IIC_WaitAck();
IIC_start();
IIC_SendByte(0xa1);//0xa1 + AT24C02器件地址 0xa1表示读
IIC_WaitAck();
data = IIC_RecByte();//读取的数据
IIC_Ack(0);
IIC_Stop();
delay();
return data;
}
硬件I2C:
采用的是STM32F1的硬件I2C
配置硬件:
//配置引脚
void I2C_GPIO_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//初始化
void I2C1_Init(void)
{
I2C_InitTypeDef I2C_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//I2C主机模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//I2C快速模式
I2C_InitStructure.I2C_OwnAddress1 = 0xff;//自身地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//定义从机地址位数7bit
I2C_InitStructure.I2C_ClockSpeed = 10000;//I2C通信速率10k
I2C_Init(I2C1, &I2C_InitStructure);//初始化
I2C_Cmd(I2C1, ENABLE);//使能
}
对AT24C2的应用:
//I2C写入
void I2C1_Write(u8 addr, u8 data) //写入的地址 写入的数据
{
I2C_AcknowledgeConfig(I2C1,ENABLE);
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;}//
I2C_Send7bitAddress(I2C1,0xa0,I2C_Direction_Transmitter); //0xa0 + AT24C02器件地址 0xa0表示写
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){;}
I2C_SendData(I2C1,addr);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;}
I2C_SendData(I2C1,data);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;}
I2C_GenerateSTOP(I2C1,ENABLE);
}
//读取I2C
u8 I2C1_Read(u8 nAddr)//读取的地址
{
I2C_AcknowledgeConfig(I2C1,ENABLE);
I2C_GenerateSTART(I2C1,ENABLE); //开始
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;} //在高速率下,可能会卡在这
I2C_Send7bitAddress(I2C1,0xa0,I2C_Direction_Transmitter); //0xa0 + AT24C02器件地址 0xa0表示写
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){;}//EV6
I2C_SendData(I2C1,nAddr);//
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;}
I2C_GenerateSTART(I2C1,ENABLE); //
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;}
I2C_Send7bitAddress(I2C1,0xa1,I2C_Direction_Receiver); //0xa1 + AT24C02器件地址 0xa1表示读
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){;}
I2C_AcknowledgeConfig(I2C1,DISABLE); //
I2C_GenerateSTOP(I2C1,ENABLE); //
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){;}
return I2C_ReceiveData(I2C1); //
}