⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 AT89C51 I2C接口通信程序例程.rar
💻 C
字号:
/***********************************************************************/
/* 文件名  :I2C.c
/* 芯片    :Atmel AT89C51
/* 作者	   :Ericson
/* 日期	   :2007.11.15
/* 功能描述:本文件为I2C串行通信协议提供支持,通过AT89C51的P00和P01口模拟
      		 实现I2C协议规范,并通过I2C通信协议实现对EEPROM AT24C32的写入
			 和读出操作。
			 
/***********************************************************************/

//***********************************************************************
//包含头文件
#include "I2C.h"

//***********************************************************************
//端口定义
sbit SCL = P0^0;			//I2C编程端口--SCL
sbit SDA = P0^1;			//I2C编程端口--SDA
	
//***********************************************************************
//I2C串行通信启动函数
void I2C_Start(void)
{
	SDA	= 1;
	_nop_();
	SCL = 1;
	SomeNOP();			
	SDA = 0;			//数据线保持高电平5个指令周期后变为低电平,I2C通信开始
	SomeNOP();			//SDA:5(高)+4(低)
	SCL = 0;			//SCL: 9(高)
	_nop_();
	_nop_();
}

//***********************************************************************
//I2C串行通信结束函数
void I2C_Stop(void)
{
	SDA	= 0;
	_nop_();
	_nop_();
	SCL = 1;
	SomeNOP();
	SDA	= 1;
	SomeNOP();
}

//***********************************************************************
//I2C串行通信发送应答位函数
void I2C_ACK(void)
{
	SDA = 0;
	_nop_();
	_nop_();
	SCL = 1;
	SomeNOP();
	SCL	= 0;
    _nop_();
	_nop_();
}


//**********************************************************************
//I2C串行通信发送非应答位函数
void I2C_NoACK(void)
{
	SDA = 1;
	_nop_();
	_nop_();
	SCL	= 1;
	SomeNOP();
	SCL	= 0;
	_nop_();
	_nop_(); 
}

//***********************************************************************
//I2C串行通信写入一个字节函数
void I2C_WriteByte(uchar ch)
{
	uchar index = 8;
	while(index--)
	{
		SCL = 0;
		_nop_();
		_nop_();
		SDA	= (bit)(ch&0x80);
		SomeNOP();
		SCL = 1;
		SomeNOP();
		ch <<= 1;
	}
	SCL = 0;
	_nop_();
	_nop_();
	SDA = 1;
	_nop_();
	_nop_();
	SCL = 1;
	_nop_();
	_nop_();
	_nop_();
	if(SDA == 1)	ACK = 0;
	else	ACK	= 1;
	SCL = 0;
	_nop_();
	_nop_();
}

//***********************************************************************
//I2C串行通信读出一个字节函数
uchar I2C_ReadByte(void)
{
	uchar index = 8;
	uchar Data = 0;
	SDA = 1;
	while(index--)
	{
		Data <<= 1;
		_nop_();
		SCL = 0;
		SomeNOP();
		SCL = 1;
		_nop_();
		_nop_();
		if(SDA == 1)	Data += 1;	
	}
	SCL = 0;
	_nop_();
	_nop_();
	return Data;
}


//***********************************************************************
//通过I2C接口向EEPROM写入一个字节数据函数
//参数说明:sla  -- 待写入数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
//			addr -- 待写入数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
//			ch   -- 待写入EEPROM的数据
bit	NVM_WriteB(uchar sla,uint addr,uchar ch)
{
	uchar haddr,laddr;
	laddr = (uchar)(addr&0xFF);				//存储单元低字节地址
	haddr = (uchar)((addr>>8)&0xFF);		//存储单元高字节地址
	I2C_Start();
	I2C_WriteByte(sla);
	if(ACK == 0)	return(0);
	I2C_WriteByte(haddr);
	if(ACK == 0)	return(0);
	I2C_WriteByte(laddr);
	if(ACK == 0)	return(0);
	I2C_WriteByte(ch);
	if(ACK == 0)	return(0);
	I2C_Stop();
	return(1);
}


//***********************************************************************
//通过I2C接口从EEPROM读出一个字节数据函数,结果放在ch指向的地址单元中
//参数说明:sla  -- 待读出数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
//			addr -- 待读出数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
//			ch   -- 用于保存从EEPROM读出的数据
bit NVM_ReadB(uchar sla,uint addr,uchar *ch)
{
	uchar haddr,laddr;
	laddr = (uchar)(addr&0xFF);				//存储单元低字节地址
	haddr = (uchar)((addr>>8)&0xFF);		//存储单元高字节地址
	I2C_Start();
	I2C_WriteByte(sla);
	if(ACK == 0)	return(0);
	I2C_WriteByte(haddr);
	if(ACK == 0)	return(0);
	I2C_WriteByte(laddr);
	if(ACK == 0)	return(0);
	I2C_Start();
	I2C_WriteByte(sla+1);
	if(ACK == 0)	return(0);
	*ch = I2C_ReadByte();
	I2C_NoACK();
	I2C_Stop();
	return(1);
}

//***********************************************************************
//通过I2C接口向EEPROM写入一个字符串函数
//参数说明:sla   -- 待写入数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
//			addr  -- 待写入数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
//			str   -- 待写入EEPROM的数据数组的首地址
//			length-- 待写入EEPROM的数据数组长度        
bit	NVM_WriteStr(uchar sla,uint addr,uchar *str,uchar length)
{
	uchar index,temp;
	uchar haddr,laddr;
	laddr = (uchar)(addr&0xFF);				//存储单元低字节地址
	haddr = (uchar)((addr>>8)&0xFF);		//存储单元高字节地址
	I2C_Start();
	I2C_WriteByte(sla);
	if(ACK == 0)	return(0);
	I2C_WriteByte(haddr);
	if(ACK == 0)	return(0);
	I2C_WriteByte(laddr);
	if(ACK == 0)	return(0);
	for(index=0;index<length;index++)
	{
		temp = *(str+index);
		I2C_WriteByte(temp);
		if(ACK == 0)	return(0);
	}
	I2C_Stop();
	return(1);
}

//***********************************************************************
//通过I2C接口从EEPROM读出一个字符串函数,结果放在ch指向的地址单元中
//参数说明:sla   -- 待读出数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
//			addr  -- 待读出数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
//			str   -- 待写入EEPROM的数据数组的首地址
//			length-- 待写入EEPROM的数据数组长度
bit NVM_ReadStr(uchar sla,uint addr,uchar *str,uchar length)
{
	uchar index;
	uchar haddr,laddr;
	laddr = (uchar)(addr&0xFF);				//存储单元低字节地址
	haddr = (uchar)((addr>>8)&0xFF);		//存储单元高字节地址
	I2C_Start();
	I2C_WriteByte(sla);
	if(ACK == 0)	return(0);
	I2C_WriteByte(haddr);
	if(ACK == 0)	return(0);
	I2C_WriteByte(laddr);
	if(ACK == 0)	return(0);
	I2C_Start();
	I2C_WriteByte(sla+1);
	if(ACK == 0)	return(0);
	for(index=0;index<length;index++)
	{
		*(str+index) = I2C_ReadByte();
		I2C_ACK();
	}
	I2C_NoACK();
	I2C_Stop();
	return(1);
}

//结束







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -