📄 iic-89c52.c
字号:
***************************************************************************************************
连线图: *
*24C04-------89C52* *
*WP----------P2.5* *
*SCL---------P2.6* *
*SDA---------P2.7* *
注:89C52的晶振频率为12MHz *
***************************************************************************************************/
#include<reg52.h>
#include<intrins.h>
#define Uchar unsigned char
#define _Nop() _nop_() /*定义空指令*/
/***********IIC总线接口引脚定义***************/
/*端口位定义*/
sbit WP= 0xa5;
sbit SCL=0xa6; //定义89C52单片机的P2.5、P2.6和P2.7作为IIC总线的WP、SCL和SDA信号
sbit SDA=0xa7;
/*状态标志*/
bit ack; /*应答标志位*/
/*****************************IIC总线程序*****************************/
/*******************************************
起动总线函数
函数原型:void Start_I2c();
功能:起动IIC总线,即发送IIC起始条件
**********************************************/
void Start_I2c()
{
// EA = 0;
SCL=0; /*钳住IIC总线,准备发送或接收数据*/
_Nop();
_Nop();
SDA=1;/*发送起始条件的数据信号*/
_Nop();
_Nop();
SCL=1;
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0;/*发送起始信号*/
_Nop();/*起始条件锁定时间大于4us*/
_Nop();
_Nop();
_Nop();
_Nop();
}
/****************************************************
结束总线函数
函数原型:void Stop_I2c();
功能:结束IIC总线,即发送IIC结束条件
******************************************************/
void Stop_I2c()
{
SCL=0;
_Nop();
_Nop();
SDA=0;/*发送结束条件的数据信号*/
_Nop();/*发送结束条件的时钟信号*/
_Nop();
_Nop();
_Nop();
SCL=1;/*结束条件建立时间大于4us*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1;/*发送IIC总线结束信号*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0;
_Nop();
_Nop();
_Nop();
SDA=0;
_Nop();
_Nop();
//EA = 1;
}
/********************************************
字节数据传送函数
函数原型:void SendByte(uchar c);
功能:将数据c发送出去,可以是地址,也可以是数据,发送完后等待应答,并对此状态
位进行操作(不应答或非应答都使ack=0.发送数据正常,ack=1;
ack=0表示被控制器无应答或损坏。
*********************************************/
void SendByte(Uchar c)
{
Uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
SCL=0;
_Nop();
_Nop();
if((c<<BitCnt)&0x80)
SDA=1;/*判断发送位*/
else
SDA=0;
_Nop();
SCL=1; /*置时钟线为高,通知被控制器开始接收数据位*/
_Nop();
_Nop(); /*保证时钟高电平周期大于4us*/
_Nop();
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
SDA=1; /*8位发送完后释放数据线,准备接收应答*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
if(SDA==1) /*判断是否接收到应答信号*/
ack=0; /*SDA==1 ack=0 表示从器件没收到*/
else
ack=1; /*SDA==0 ack=1 表示从器件收到*/
SCL=0;
_Nop();
_Nop();
}
/************************************************
字节数据传送函数
函数原型:uchar RcvByte();
功能:用来接收从器件传来的数据,并判断总线错误(不发应答信号)
发完后请用应答函数。
***************************************************************/
Uchar RcvByte()
{
Uchar rete;
Uchar BitCnt;
rete=0;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SDA=1; /*置数据线为输入方式*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=1; /*置时钟线为高电平使数据线上数据有效*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
rete=rete<<1;
if(SDA==1)
rete=rete+1; /*读数据位,接收的数据位放入rete中*/
SCL=0;
}
_Nop();
_Nop();
return(rete);
}
/****************10ms延时(时钟频率为12MHz)*****************/
void wait_10ms(void){
register int j;
for (j=0;j<1950;j++)
;
}
/*******************************
向有子地址器件发送多字节数据函数
函数原型:bit ISendStr(uchar sla,uchar suba, uchar *s,uchar no);
功能:从起动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,
子地址suba,发送内容是s指向的内容,发送no个字节。如果返回1表示操作成功,否则操作失败。
******************************************************/
bit ISendStr(Uchar sla,Uchar suba,Uchar no,Uchar *s)
{
Uchar i;
for(i=0;i<no;i++)
{
Start_I2c(); /*起动总线*/
SendByte(sla);/*发送器件地址*/
if(ack==0) /*SDA==0 ack=1 表示从器件收到*/
return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)
return(0);
SendByte(*s);/*发送数据*/
if(ack==0)
return(0);
s++;
suba++;
Stop_I2c(); /*结束总线*/
wait_10ms();
}
_Nop();
_Nop();
return(1);
}
/*********************************************************
向有子地址器件读多字节数据函数
函数原型:bit ISendStr(uchar sla, uchar suba, uchar *s,uchar no);
功能:从起动总线到发送地址,子地址,读数据,结束总线的全过程,从器件地址sla,
子地址suba,读出的内容放入s指向的存储区,读no个字节。如果返回1
表示操作成功,否则操作有误。
*********************************************************/
bit IRcvStr(Uchar sla,Uchar suba,Uchar no,Uchar *s)
{
Uchar i;
for(i=0;i<no;i++)
{
Start_I2c(); /*起动总线*/
SendByte(sla&0xfe); /*发送器件地址 “先写后读”*/
if(ack==0) /*SDA==0 ack=1 表示从器件收到*/
{
Stop_I2c();
return(0);
}
SendByte(suba); /*发送器件子地址*/
if(ack==0)
{
Stop_I2c();
return(0);
}
Start_I2c();
SendByte(sla);
if(ack==0)
{
Stop_I2c();
return(0);
}
*s=RcvByte();
s++;
suba++;
SDA=1; /*在此发出应答信号*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*时钟低电平周期大于4us*/;
Stop_I2c(); /*结束总线*/
}
_Nop();
_Nop();
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -