天天看点

51单片机——I2C总线驱动程序

为方便移植,采用多文件工程的方式。

void Delay10us()//延时10us
{
	unsigned char a,b;
	for(b=1;b>0;b--)
		for(a=2;a>0;a--);

}
           

起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿

void I2cStart()//为方便与其他函数衔接,起始之后SDA和SCL都为0,虽然这与I2C总线空闲状态不符,但并不影响程序运行
{
	SDA=1;
	Delay10us();
	SCL=1;
	Delay10us();//建立时间是SDA保持时间>4.7us
	SDA=0;
	Delay10us();//保持时间是>4us
	SCL=0;			
	Delay10us();		
}
           

终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿

void I2cStop()//结束之后保持SDA和SCL都为1;表示总线空闲
{
	SDA=0;
	Delay10us();
	SCL=1;
	Delay10us();//建立时间大于4.7us
	SDA=1;
	Delay10us();		
}
           

I2cSendByte(unsigned char dat) : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定

unsigned char I2cSendByte(unsigned char dat)//发送成功返回1,发送失败返回0
{
	unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。		
	for(a=0;a<8;a++)//要发送8位,从最高位开始
	{
		SDA=dat>>7;	 //起始信号之后SCL=0,所以可以直接改变SDA信号
		dat=dat<<1;
		Delay10us();
		SCL=1;
		Delay10us();//建立时间>4.7us
		SCL=0;
		Delay10us();//时间大于4us		
	}
	SDA=1;//¥¥¥
	Delay10us();
	SCL=1;
	while(SDA)//等待应答,也就是等待从设备把SDA拉低
	{
		b++;
		if(b>200)	 //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
		{
			SCL=0;
			Delay10us();
			return 0;
		}
	}
	SCL=0;
	Delay10us();
 	return 1;		
}
           

I2cReadByte() :使用I2c读取一个字节

unsigned char I2cReadByte()
{
	unsigned char a=0,dat=0;
	SDA=1;	//¥¥¥		
	Delay10us();
	for(a=0;a<8;a++)//接收8个字节
	{
		SCL=1;
		Delay10us();
		dat<<=1;
		dat|=SDA;
		Delay10us();
		SCL=0;
		Delay10us();
	}
	return dat;		
}
           

在以上两个函数中,在“¥¥¥”处,都将SDA置为1,这是将SDA线释放。原因如下:

I2C的数据和时钟线上都有一个上拉电阻,电阻的另一端接一个高电平。当I2C工作时,SDA上的电平取决于SDA上的数据。当I2C不工作时,因为集成电路的输入端为高阻状态,SDA上的电压就取决于电阻另一端的高电平了,因此I2C在释放总线后,SDA就等于1了。

对于I2C总线的解释:https://blog.csdn.net/cax1165/article/details/86755169

void At24c02Write(unsigned char addr,unsigned char dat) :往24c02的一个地址写入一个数据

void At24c02Write(unsigned char addr,unsigned char dat)
{
	I2cStart();
	I2cSendByte(0xa0);//发送写器件地址
	I2cSendByte(addr);//发送要写入内存地址
	I2cSendByte(dat);	//发送数据
	I2cStop();
}
           

unsigned char At24c02Read(unsigned char addr) :读取24c02的一个地址的一个数据

unsigned char At24c02Read(unsigned char addr)
{
	unsigned char num;
	I2cStart();
	I2cSendByte(0xa0); //发送写器件地址
	I2cSendByte(addr); //发送要读取的地址
	I2cStart();
	I2cSendByte(0xa1); //发送读器件地址
	num=I2cReadByte(); //读取数据
	I2cStop();
	return num;	
}
           

多文件工程 头文件

#ifndef __I2C_H_
#define __I2C_H_

#include <reg52.h>

sbit SCL=P2^1;
sbit SDA=P2^0;

void I2cStart();
void I2cStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);

#endif
           

继续阅读