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

📄 i2c.c

📁 I2C总线驱动程序(用两个普通IO模拟I2C总线)
💻 C
字号:
/* 〖说明〗I2C总线驱动程序(用两个普通IO模拟I2C总线)****************************************
包括100Khz(T=10us)的标准模式(慢速模式)选择和400Khz(T=2.5us)的快速模式选择,默认11.0592Mhz的晶振.
*************************************************************************************/
//#include	<reg51.h>
//#include	<intrins.h>
#include	"config.h"
#define 	SomeNOP();	 _nop_();_nop_();_nop_();_nop_();

#if 0
/*****************************************************
功能:延时nx1ms子程序	晶振4MHz
入口:n
*****************************************************/
void delay1ms(uint16 n)
{
	uint8 i;

	while(n--)
	{
		i=54;
		while(--i);
	}
}
#endif

/*********************************************************************************
调用方式:void I2CStart(void) 	2001/07/0 4
函数说明:私有函数,I2C专用
*********************************************************************************/
void I2CStart(void)
{
	OS_ENTER_CRITICAL();
	SDA=1;
	SCL=1;
	SomeNOP();		//INIT
	SDA=0;
	SomeNOP(); 		//START
	SCL=0;
}


/*********************************************************************************
调用方式:void I2CStop(void)	2001/07/0 4
函数说明:私有函数,I2C专用
*********************************************************************************/
void I2CStop(void)
{
	SCL=0;
	SDA=0;
	SomeNOP(); 		//INI
	SCL=1;
	SomeNOP();
	SDA=1; 			//STOP
	OS_EXIT_CRITICAL();
}

/*********************************************************************************
调用方式:bit I2CAck(void) 		2001/07/0 4
函数说明:私有函数,I2C专用,等待从器件接收方的应答
*********************************************************************************/
bit WaitAck(void)
{
	uint8 errtime=255;	//因故障接收方无ACK,超时值为255。

	SDA=1;
	SomeNOP();
	SCL=1;
	SomeNOP();
	while(SDA)
	{
		errtime--;
		if (!errtime)
		{
			I2CStop();
			return (FALSE);
		}
	}
	SCL=0;
	return (TRUE);
}


/*********************************************************************************
调用方式:void SendAck(void)	2001/07/0 4
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
*********************************************************************************/
void SendAck(void)
{
	SDA=0;
	SomeNOP();
	SCL=1;
	SomeNOP();
	SCL=0;
}


/*********************************************************************************
调用方式:void SendAck(void)		2001/07/0 4
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
**-------------------------------------------------------------------------------*/
void SendNotAck(void)
{
	SDA=1;
	SomeNOP();
	SCL=1;
	SomeNOP();
	SCL=0;
}


/*********************************************************************************
调用方式:void I2CSend(uint8 ch)		2001/07/0 5
函数说明:私有函数,I2C专用
*********************************************************************************/
void I2CSendByte(uint8 ch)
{
	uint8 i=8;

	while (i--)
	{
		SCL=0;
		_nop_();
		SDA=(bit)(ch&0x80);
		ch<<=1;
		SomeNOP();
		SCL=1;
		SomeNOP();
	}
	SCL=0;
}


/*********************************************************************************
调用方式:uchar I2CReceive(void)	2001/07/0 5
函数说明:私有函数,I2C专用
*********************************************************************************/
uint8 I2CReceiveByte(void)
{
	uint8 i=8;
	uint8 ddata=0;

	SDA=1;
	while (i--)
	{
		ddata<<=1;
		SCL=0;
		SomeNOP();
		SCL=1;
		SomeNOP();
		ddata|=SDA;
	}
	SCL=0;
	return (ddata);
}


#if 0
/*********************************************************************************
函数说明;测试主函数
*********************************************************************************/
void main(void)
{
	uint8	i;
	uint8 	arr[16];

	while (1)
	{
		readEeprom(0xa0, 0x00, arr, 16);
		for (i=0; i<16; i++)
			arr[i]=i*2;

		writeEeprom(0xa0, 0x00, arr, 16);
		readEeprom(0xa0, 0x00, arr, 16);
	}
}



/*********************************************************************************
调用方式:void GetPCF8563(uint8 firsttype,uint8 count,uint8 *buff)		2001/08/0 7
函数说明:读取时钟芯片PCF8563的时间,设置要读的第一个时间类型firsttype,并设置读取
的字节数,则会一次把时间读取到buff中。顺序是:
0x02:秒/0x03:分/0x04:小时/0x05:日/0x06:星期/0x07:月(世纪)/0x08:年
*********************************************************************************/
void GetPCF8563(uint8 firsttype, uint8 count, uint8 *buff)
{
	uint8 i;

	I2CStart();
	I2CSendByte(0xA2);
	WaitAck();
	I2CSendByte(firsttype);
	WaitAck();

	I2CStart();
	I2CSendByte(0xA3);
	WaitAck();

	for (i=0;i<count;i++)
	{
		buff[i]=I2CReceiveByte();
		if (i!=count-1)
			SendAck();		//除最后一个字节外,其他都要从MASTER发应答。
	}

	SendNotAck();
	I2CStop();
}


/*********************************************************************************
调用方式:void SetPCF8563(uint8 timetype,uint8 value)		2001/08/0 7
函数说明:调整时钟。timetype是要改的时间类型,value是新设置的时间值(BCD格式)。
0x02:秒/0x03:分/0x04:小时/0x05:日/0x06:星期/0x07:月(世纪)/0x08:年
*********************************************************************************/
void SetPCF8563(uint8 timetype,uint8 value)
{
	I2CStart();
	I2CSendByte(0xA2);
	WaitAck();
	I2CSendByte(timetype);
	WaitAck();
	I2CSendByte(value);
	WaitAck();
	I2CStop();
}

/*********************************************************************************
调用方式:void SetAlarmHour(uint8 count)		2001/08/0 7
函数说明:设置报警闹钟在一天的第count点报警。例如:count=23,则在晚上11点报警。
*********************************************************************************/
void SetAlarm(uint8 alarmtype,uint8 count)
{
	SetPCF8563(0x01,0x02);
	SetPCF8563(alarmtype,count);
}


/*********************************************************************************
调用方式:void CleanAlarm(void)		2001/08/0 7
函数说明:清除所有报警设置。
*********************************************************************************/
void CleanAlarm(void)
{
	SetPCF8563(0x01,0x00);
	SetPCF8563(0x09,0x80);
	SetPCF8563(0x0A,0x80);
	SetPCF8563(0x0B,0x80);
	SetPCF8563(0x0C,0x80);
	// SetPCF8563(0x0D,0x00);
	// SetPCF8563(0x0E,0x03);
}


/*--------------------------------------------------------------------------------
调用方式:uchar read1380(uint8 command )
函数说明:read1380()返回当前时间, command指要返回的时间类型。
秒:81H 分钟:83H 小时:85H 日期:87H 星期:89H 星期几:8BH 年:8D H
*********************************************************************************/
uint8 read1380 (uint8 command)
{
	uint8 time;

	GetPCF8563(command,1,&time);
	return (time);
}

/*--------------------------------------------------------------------------------
调用方式:void write1380(uint8 command ,uint8 time )
函数说明:write1380()往HT1380写命令和数据,command是命令字, time是后写入的数据
*********************************************************************************/
void write1380(uint8 command ,uint8 time)
{
	SetPCF8563(command,time);
}


/*--------------------------------------------------------------------------------
调用方式:void time_display(uint8 x0,uint8 y0 )
函数说明:time_display()在指定的x0,y0坐标,以00:00:00格式显示当前时间。
*********************************************************************************/
//uint8 time[]="00:11:11";

void time_display(uint8 x0,uint8 y0,bit type) //液晶时间显示
{
	uint8 time[]="00:00:00";
	uint8 con[3];
	uint8 time_type;

	GetPCF8563(0x02,3,con);
	time[0]=(con[2]>>4)+'0';
	time[1]=(con[2]&0x0f)+'0';
	time[3]=(con[1]>>4)+'0';
	time[4]=(con[1]&0x0f)+'0';
	time[6]=(con[0]>>4)+'0';
	time[7]=(con[0]&0x0f)+'0';

	time[8]=0;
	if(type==1)
	{
		time_type=0xff;
	}
	else
	{
		time_type=0;
	}
}
#endif






/*********************************************************************************
功能:从24c08中读出n字节数据			2001/08/0 7
入口:chipAddr为芯片地址,subAddr为子地址,buff为数据存储指针,n为字节数
出口:无
*********************************************************************************/
void readEeprom(uint8 chipAddr,uint8 subAddr,uint8 *buff, uint8 n)
{
	uint8 i;

	I2CStart();
	I2CSendByte(chipAddr & 0xfe);
	WaitAck();
	I2CSendByte(subAddr);
	WaitAck();

	I2CStart();
	I2CSendByte(chipAddr | 0x01);
	WaitAck();

	for (i=0; i<n; i++)
	{
		buff[i]=I2CReceiveByte();
		if (i!=n-1)
			SendAck();		//除最后一个字节外,其他都要从MASTER发应答。
	}

	SendNotAck();
	I2CStop();
}





/*********************************************************************************
功能:写n字节到24c08			2001/08/0 7
入口:chipAddr为芯片地址,subAddr为子地址,buff为数据指针,n为字节数
出口:无
*********************************************************************************/
void writeEeprom(uint8 chipAddr, uint8 subAddr, uint8 *buff, uint8 n)
{
	uint8 i;

	I2CStart();
	I2CSendByte(chipAddr & 0xfe);
	WaitAck();
	I2CSendByte(subAddr);
	WaitAck();

	for (i=0; i<n; i++)
	{
		I2CSendByte(*(buff + i));
		WaitAck();
		if ((i+1) % PAGE_SIZE == 0 && (i+1) < n)
		{
			I2CStop();
//			delay1ms(10);
			OSWait(K_TMO,2);
			I2CStart();
			I2CSendByte(chipAddr & 0xfe);
			WaitAck();
			I2CSendByte(subAddr+i+1);
			WaitAck();
		}
	}
	I2CStop();
//	delay1ms(10);
	OSWait(K_TMO,2);
}

⌨️ 快捷键说明

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