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

📄 tt.c

📁 此为I2C串行通信C程序,用8051单片机实现,并附有仿真电路
💻 C
字号:
/*
2.1 接口特性
  I2C总线接口的数据线SDA和时钟线SCL必须经过上拉电阻接到正电源VDD上,各个I2C接口电路输出端必须是漏极开路或集电极
开路,以便完成“线与”的功能。I2C的SDA和SCL都是双向传输线,当总线空闲时,此两线都是“1”(高电平)。由于不同的器
件都会接到I2C总线,逻辑的“0”(低)及“1”(高)的信号电平取决于VDD的电压。总线上能连接的最大器件数取决于其电容
容限400PF。
2.2 I2C总线上的传输时序
  I2C总线上每传输一位数据都有一个时钟脉冲相对应,在标准模式下可达100 kbit/s,高速模式下可达400kbit/s,总线上
依据器件功能不同可建立简单的主/从关系(master/slave),只有带CPU的器件才可成主控器。图1为I2C总线一次完整的数据
传输。SCL为高期间,SDA状态必须稳定,SCL为低时才允许SDA状态变化。SCL保持高电平期间,SDA出现由高至低的转换将启动I2C
总线,出现由低至高的转换将停止数据传输。起始和终止信号通常由主控器产生。I2C总线的信号时序有严格规定,本应用采用标
准模式,SCL低电平周期≥4.7μs,SCL高电平周期≥4.0μs,START和STOP之间的总线空闲时间≥4.7μs。
  I2C 总线上传送的每个字节必须为8位,启动和停止之间可传输的数据字节数不受限制。采用串行传送,首先传送最高位,每
传送一个字节后必须跟一个应答位。主控器产生应答所需的时钟脉冲期间,发送器必须释放数据线(SDA为高),以便接收器输出
应答位。低电平为应答信号,高电平为非应答信号。非应答信号是当主控器作为接收器时,收到最后一个字节数据后,必须发送
一个非应答信号给被控发送器,使被控发送器释放数据线,以便主控器发停止信号,终止数据传送。当从器件不能再接收字节时
也会出现非应答信号这种情况。
  I2C总线上的器件一般有两个地址:受控地址和通用广播访问地址,每个器件有唯一的受控地址用于定点通信,而相同的通用
广播访问地址则用于主控方同时对所有器件进行访问。如图1所示,起始信号后主控器发送的第一个字节就是被读器件的受控地址,
称作寻址字节。寻址字节由高7位地址和最低1位方向位组成,方向位为“0”表明主控器对被控器的写操作(W),方向位为 “1”
表明对被控器的读操作(R)。总线上每个器件在起始信号后都把自己的地址与寻址字节的前7位相比较,如相同则器件被选中,
产生应答,并根据读写位决定在数据传送中是接收还是发送。无论是主发、主收还是从发、从收,都是由主器件控制,数据传送完后,
主控器都必须发停止信号。
*/
#include<reg51.h>
#include <intrins.h>
#define unchar unsigned char
#define nop() _nop_()
sbit scl=P2^0;
sbit sda=P2^1;
sbit WP=P2^2;
void delayx(unchar x,unchar y)
{  
	unchar i,j,k;
	if(y==0){for(i=0;i<x;i++);}
	if(y==1)
	{
		for(i=0;i<x;i++)
		{
			for(j=0;j<40;j++)
			for(k=0;k<100;k++);
		}	 
	}
}

void Start() //时钟线保持高,数据线从高到低一次跳变,I2C通信启动
{
	sda=1;  
	scl=1; 	  //SCL高电平周期≥4.0μs
	nop();nop();nop();nop();nop(); 
	sda=0; 
	nop();nop(); 
	scl=0; 	   // SCL低电平周期≥4.7μs
	nop();nop();nop();nop();nop();
}

void Stop() //时钟线保持高,数据线从低到高一次跳变,I2C通信停止
{
	sda=0;  
	scl=1; 
	nop();nop();nop();nop();nop(); 
	sda=1; 
	nop();nop();nop();nop();
}

void writex(unchar j)  //时钟线从高电平到低电平一次跳变则写入一个字节
{  
	unchar i,temp;
    temp=j;
    for (i=0;i<8;i++)
	{
		sda=temp&0x80;
		temp=temp<<1;
		scl=1; 
		nop();nop();nop();nop();nop();
		scl=0; 
		nop();nop();nop();nop();nop();
	}
}

unchar readx()   //时钟线从低电平到高电平一次跳变则开始读取一个字节
{
	unchar i,j,k=0;
    for (i=0;i<8;i++)
	{   
		scl=0; 
		nop();nop();nop();nop();nop();
		scl=1;
		nop();nop();nop();nop();nop();
		if (sda==1) j=1;
		else j=0;
		k=(k<<1)|j;
		//nop();nop();
		//scl=0;
	} 
	return(k);
}
/*//函数说明:私有函数,I2C专用,等待从器件接收方的应答
WaitAck(void)
{
	unsigned char errtime=255;//因故障接收方无ACK,超时值为255。
	SDA=1;
	SCL=1;
	SystemError=0x10; 
	while(SDA)
	{
		errtime--;
		if(!errtime)
		{
			AD7416_I2CStop();
			AD7416_SystemError=0x11; //出错后给全局变量赋值
			return;
		}
	}
	SCL=0; 
}

//函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
void SendAck(void)
{
	SDA=0; SomeNOP(); //数据线保持低,时钟线发生一次从高低的跳变 发送一个应答信号
	SCL=1; SomeNOP();
	SCL=0;
}

//函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
void SendNotAck(void)
{
	SDA=1; SomeNOP(); //数据线保持高,时钟线发生一次从高低的跳变 没有应答
	SCL=1; SomeNOP();
	SCL=0;
}*/
void ack()         //I2C总线时钟
{
	unchar i=0;
	scl=1; 
	nop();nop();nop();nop();nop();
	//while ((sda==1)&&(i<255))i++;
	scl=0; 
	nop();nop();nop();nop();nop();
}

//数据块读取函数
void x24c02_read(unchar Data[],unchar Address,unchar Num)
{
	unchar i;
	unchar *PData;
	PData=Data;
	for(i=0;i<Num;i++)
	{
		Start();
		writex(0xa0);  //发送写信号
		ack();
		writex(Address+i);
		ack(); 
		Start();
		writex(0xa1);  //发送读信号
		ack();
		*(PData+i)=readx();	
		Stop();
	}	
}

//数据块写入函数
void x24c02_write(unchar Data[],unchar Address,unchar Num)
{
	unchar i;
	unchar *PData;
	PData=Data;
	for(i=0;i<Num;i++)
	{
		Start();
		writex(0xa0);//发送写信号
		ack();
		writex(Address+i);//发送地址
		ack();
		writex(*(PData+i));
		ack();
		Stop();
		delayx(50,0);
	}
}
void main(void)
{ 
	unchar n,AData[16],Number[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};//{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};	//字形码0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
	WP=0;
	x24c02_write(Number,0,16);//参数格式:数据指针,存储地址,存储字节数
	delayx(20,0);
	x24c02_read(AData,0,16);//参数格式:数据指针,存储地址,存储字节数]
	P0=0;delayx(50,1);
	for(n=0;n<16;n++)
	{
		P0=AData[n];
		delayx(50,1);
	} 
}

⌨️ 快捷键说明

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