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

📄 i2c_soft.c

📁 《8051系列单片机C程序设计完全手册》的光盘中的所有源代码
💻 C
字号:
/* 单主器件I2C总线模拟子程序 */

#include <At89x51.h>
#include <intrins.h>

#define uchar unsigned char
#define DELAY5US _nop_();_nop_();_nop_();_nop_();    // 需要根据晶振频率调整

sbit VSDA=P1^0;    // 将p1.0口模拟数据口
sbit VSCL=P1^1;    // 将p1.1口模拟时钟口

uchar idata SLA;    // 从器件地址
uchar idata SLAW;    // 从器件写地址
uchar idata SLAR;    // 从器件读地址
uchar idata NUMBYT;    // 数据传送字节
uchar idata MTD[10];    // 数据发送缓冲区
uchar idata MRD[10];    // 数据接收缓冲区
bit   bdata NACK;    // 器件坏或错误标志位

/* 启动I2C总线子程序 */
void STA(void)
{ 
	VSDA = 1;    // 启动I2C总线
	VSCL = 1;
	DELAY5US    // 延时4.7us,根据晶振频率调整空操作个数,这里以fosc=12MHz,下同
	VSDA = 0;
	DELAY5US
	VSCL = 0;
}

/* 停止I2C总线数据传送子程序 */
void STOP(void)
{ 
	VSDA = 0;    // 停止I2C总线数据传送
	VSCL = 1;
	DELAY5US
	VSDA = 1;
	DELAY5US
	VSCL = 0;
}

/* 发送应答位子程序 */
void MACK(void)
{
	VSDA = 0;    // 发送应答位
	VSCL = 1;
	DELAY5US
	VSDA = 1;
	VSCL = 0;
}

/* 发送非应答位子程序 */
void MNACK(void)
{ 
	VSDA = 1;    // 发送非应答位
	VSCL = 1;
	DELAY5US
	VSDA = 0;
	VSCL = 0;
}

/* 应答位检查子程序 */
void CACK(void)
{ 
	VSDA = 1;    // 应答位检查(将p1.0设置成输入,必须先向端口写1)
	VSCL = 1;
	F0 = 0;
	if(VSDA == 1)    // 若VSDA=1表明非应答,置位非应答标志F0
		F0 = 1;
	VSCL = 0;
}

/* 发送一个字节数据子程序,程序入口p为发送缓冲区地址 */
void WRBYT(uchar idata *p)
{ 
	uchar idata n=8;     // 向VSDA上发送一位数据字节,共八位
	uchar idata temp;
	temp=*p;
	while(n--)
	{ 
		if((temp&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1
		{
			VSDA = 1;    // 传送位1
			VSCL = 1;
			DELAY5US
			VSDA = 0;
			VSCL = 0;    
		}
		else
		{  
			VSDA = 0;    // 否则传送位0
			VSCL = 1;
			DELAY5US
			VSCL = 0;  
		}
		temp = temp<<1;    // 数据左移一位,或_crol_(*p,1)
	}
}

/* 接收一字节子程序,入口参数p为接收缓冲区地址 */
void RDBYT(uchar idata *p)
{
	uchar idata n=8;    // 从VSDA线上读取一上数据字节,共八位
	uchar idata temp=0;
	while(n--)
	{
		VSDA = 1;
		VSCL = 1;
		temp = temp<<1;    // 左移一位,或_crol_(temp,1)
		if(VSDA == 1)
			temp = temp|0x01;    // 若接收到的位为1,则数据的最后一位置1
		else 
			temp = temp&0xfe;    // 否则数据的最后一位置0
		VSCL=0;
	}
	*p=temp;
}

/* 发送n位数据子程序 */
void WRNBYT(uchar *sla, uchar n)
{          
	uchar idata *p;
	STA();    // 启动I2C
	WRBYT(sla);    // 发送一上位数据
	CACK();    // 检查应答位
    if(F0 == 1)
	{ 
		NACK = 1;
		return;    // 若非应答表明器件错误或已坏,置错误标志位NACK
	}
	p = MTD;
	while(n--)
	{ 
		WRBYT(p);
		CACK();    // 检查应答位
		if (F0 == 1)
		{
			NACK=1;
			return;    // 若非应答表明器件错误或已坏,置错误标志位NACK
		}
		p++;
	}
	STOP();    // 全部发完则停止
}

/* 接收n位数据子程序 */
void RDNBYT(uchar idata *sla, uchar n)
{ 
	uchar idata *p;
	STA();
	WRBYT(sla);
	CACK();
	if(F0 == 1)
	{
		NACK = 1;
		return;
	}
	p = MRD;
	while(n--)
	{ 
		RDBYT (p);
		MACK();    // 收到一个字节后发送一个应答位
		p++;
	}
	MNACK();    // 收到最后一个字节后发送一个非应答位
	STOP();
}

⌨️ 快捷键说明

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