IIC简介
IIC(Inter-IntegratedCircuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。总的来说,就是IIC是通过SDA数据线和SCL时钟线来进行数据传输的
接下来就结合时序图更方便理解IIC俩条线如何运行来进行数据传输的
前提:I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。
1.开始信号和结束信号
数据的传输必须有开始信号!
如果怕记不下来就交个秘诀:在SCL拉高位时 若SDA电平发生变化则代表开始或者结束信号。 SCL=1 SDA=0 开始 SCL=1 SDA=1 结束
2.应答信号
应答信号:就是你发送数据出去对方可能不知道,所以我们会发送一个应答信号,对面只有接受到应答信号就知道你发送数据了,可以准备接收了。 所以我们就要创建3个函数:
1.产生应答信号函数
2.不产生应答信号函数
3.接收应答信号函数
应答信号产生就是当SCL拉高的时候,SDA拉低
应答信号不产生就是当SCL拉高的时候,SDA拉高
那么接受应答信号就是判断SDA是否拉低
所以我们就要创建3个函数:
1.产生应答信号函数
2.不产生应答信号函数
3.接收应答信号函数
应答信号产生就是当SCL拉高的时候,SDA拉低
应答信号不产生就是当SCL拉高的时候,SDA拉高
那么接受应答信号就是判断SDA是否拉低
3.有效数据
有效数据呢,就是SCL拉高的时候,SDA必须为拉高数据才有效。 所以我们创建写数据函数时,就要SDA拉低的时候传输出去
创建读数据函数时,就要SDA拉高的时候传输出去
所以我们创建写数据函数时,就要SDA拉低的时候传输出去
创建读数据函数时,就要SDA拉高的时候传输出去
4.EEPROM的写入数据
5.EEPROM的读取数据
接下来就是代码附上:
#include "myiic.h"
#include "delay.h"
//IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//RCC->APB2ENR|=1<<4;//ÏÈʹÄÜÍâÉèIO PORTCʱÖÓ
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //ÍÆÍìÊä³ö
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
void IIC_Start(void)
{
SDA_OUT(); //sdaÏßÊä³ö
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//ǯסI2C×ÜÏߣ¬×¼±¸·¢ËÍ»ò½ÓÊÕÊý¾Ý
}
void IIC_Stop(void)
{
SDA_OUT();//sdaÏßÊä³ö
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//·¢ËÍI2C×ÜÏß½áÊøÐźÅ
delay_us(4);
}
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDAÉèÖÃΪÊäÈë
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//ʱÖÓÊä³ö0
return 0;
}
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//²»²úÉúACKÓ¦´ð
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//ÀµÍʱÖÓ¿ªÊ¼Êý¾Ý´«Êä
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us(2); //¶ÔTEA5767ÕâÈý¸öÑÓʱ¶¼ÊDZØÐëµÄ
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDAÉèÖÃΪÊäÈë
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//·¢ËÍnACK
else
IIC_Ack(); //·¢ËÍACK
return receive;
}