链接:https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd=1688
提取码:1688
教学内容:
1、I2C总线:
I2C(Inter-Integrated Circuit),PHILIPS公司开发的两线式半双工同步串行总线;可以用来连接存储器(EEPROM、FLASH)、A/D、D/A转换器、LCD驱动器、传感器等等。
I2C总线有两根信号线:双向数据线(SDA)、时钟线(SCL)。均为双向I/O线,通过上拉电阻接正电源;I2C总线可以连接多个设备,各设备的数据和时钟线均连到SDA、SCL信号线上,主机通过设备地址来区分具体的设备,每个设备有唯一的地址(7位或10位)。
起始和终止信号:
SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;
SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。对于不具备I2C总线硬件接口的有些单片机来说,为了检测起始和终止信号,必须保证在每个时钟周期内对数据线SDA采样两次。接收器件收到一个完整的数据字节后,有可能需要完成一些其它工作,如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平,从而使主机处于等待状态。直到接收器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。
在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。
a、主机向从机发送数据,数据传送方向在整个传送过程中不变:
注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。
A表示应答, 表示非应答(高电平)。S表示起始信号,P表示终止信号。。
b、主机在第一个字节后,立即由从机读数据
c、在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相。
模拟过程:(以AT24C02为外接设备)
//*************************************************
#define IIC_CLK_SET()
#define IIC_CLK_CLR()
#define IIC_DAT_SET()
#define IIC_DAT_CLR()
#define IIC_DAT_GET()
//IIC启动信号,CLK为高电平的时,DAT由高变低
void I2CStart()
{
IIC_DAT_SET();
I2CDelay();
IIC_CLK_SET();
I2CDelay();
IIC_DAT_CLR();
I2CDelay();
IIC_CLK_CLR();
I2CDelay();
}
//停止信号,CLK为高电平时,DAT信号由低变高
void I2CStop()
{
IIC_DAT_CLR();
I2CDelay();
IIC_CLK_SET();
I2CDelay();
IIC_DAT_SET();
I2CDelay();
IIC_CLK_CLR();
I2CDelay();
}
//IIc初始化函数 CLK信号置低,发送停止信号
void I2CInit()
{
IIC_CLK_CLR();
I2CStop();
}
//在CLK为高电平时读取1位总线数据与应答信号
bit I2CClock() //return SDA while SCL is HIGH
{
unsigned char sample;
IIC_CLK_SET();
I2CDelay();
sample = IIC_DAT_GET();
IIC_CLK_CLR();
I2CDelay();
return sample;
}
// 发送一个字节的数据,并返回应答信号(1表示接收正常,0表示接收器件无应答或损坏)
unsigned int I2CSend(BYTE I2CData)
{
BYTE i;
for(i=0;i<8;i++)
{
if( (I2CData & 0x80) == 0x80 )
IIC_DAT_SET();
else
IIC_DAT_CLR();
I2CData=I2CData << 1;
IIC_CLK_SET();
I2C_Delay();
IIC_CLK_CLR();
I2C_Delay();
}
IIC_DAT_SET();
return (~I2CClock());
}
//主机应答信号,a=1时表示应答信号, a=0时表示非应答信号
void I2CAck(unsigned int a)
{
if(a==0)
IIC_DAT_CLR();
else
IIC_DAT_SET();
IIC_CLK_SET();
I2C_Delay();
IIC_CLK_CLR();
I2C_Delay();
}
//延时程序
void I2CDelay()
{
BYTE ll;
for(ll=0;ll<100;ll++)
{
;
}
}
//IIC总线器件接受一个字节的数据
BYTE I2CReceive()
{
BYTE I2CData=0;
BYTE kk;
for(kk=0;kk<8;kk++)
{
I2CData = I2CData <<1;
if(I2CClock())
{
I2CData= I2CData + 0x01;
}
}
return I2CData;
}
//向指定器件发送指定字节的数据,包含子设备地址
int SendByte(unsigned char sla,unsigned char c ,int num )
{
//启动IIC设备
//发送器件地址,
//检查应答信号
//发送一个字节数据
//结束总线
}
//想从指定的器件接收指定字节的数据,返回0代表失败,返回1代表成功
unsigned int RevByte(unsigned char sla, char *c ,int num)
{
//启动IIC设备
//发送器件地址
//检查应答信号
//接收一个字节数据
//发送应答信号
//结束总线
}
//***************************************************