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

📄 z_i2c.c

📁 基于i2c总线控制的24c32C程序读写
💻 C
字号:
#include<at89x52.h>
#include<intrins.h>
#define uchar  unsigned char
#define uint   unsigned int
#define _Nop()  _nop_()           //定义空指令
//#define ADDRWR   0xa0
//#define ADDRRD   0xa1
/*定义变量*/
uchar   ADDRWR=0xa0,ADDRRD=0xa1;
uchar   bdata   Rshu;
sbit    Rshu_3=Rshu^3;
sbit    SDA=P1^2;
sbit    SCL=P1^1;
sbit    WP=P1^0;
bit     ack;
uchar    code Wshujiu[]={0xff};
uchar    code Rshujiu[]={0x00};
/******************************************
功能:读写存储卡需要一定的延时,此函数用来延时
参数:wtime
返回值:无
********************************************/
void delay (uchar wtime)
{
 uchar i,j;
 for(i=wtime;i>0;i--)
  	 for(j=0;j<200;j++);
}
/******************************************
功能:固定时间延时
参数:无
返回值:无
********************************************/
void  wait(void)
{_Nop();
 _Nop();
 _Nop();
 _Nop();
 _Nop();
 
 }
 /**************************************************
启动总线函数
函数原形:
void   start_I2C();
功能:
启动I2C总线,即发送I2C起始条件
参数:无
返回值:无
*****************************************************/
void  start_I2C()
{   SCL=0;
	wait();
    SDA=1;                      //发送起始条件的数据信号
    _Nop();
	_Nop();
    SCL=1;						//起始条件建立时间大于4uS
    wait(); 
    SDA=0;                      //发送起始信号
    wait();                     //起始条件锁定时间大于4us
    SCL=0;                      //准备发送或接受数据
    _Nop();
    _Nop();
	_Nop();
	_Nop();
}
/**************************************************
结束总线函数
函数原形:
void   stop_I2C();
功能:
结束I2C总线,即发送I2C结束条件
参数:无
返回值:无
*****************************************************/
void  stop_I2C()
{   SDA=0;                      //发送结束条件的数据信号
    _Nop();
	_Nop();
    SCL=1;                      //发送结束条件的时钟信号
    wait();                  //结束条件建立时间大于4uS
    SDA=1;                     //发送结束信号
    _Nop();                     //结束条件锁定时间大于4us
    _Nop(); 
    _Nop();
    _Nop();
}
/*******************************************************
字节数据传送函数
函数原形:
void  sendbyte(uchar data);
功能:
发送数据,可以是地址,发送后等待回应,并对此状态位进行操作.
应答或非应答都使ack=0,发送正常,ack=1;ack=0,表示接收器无应答或损坏
参数:
data:需要发送的数据
返回值:无
********************************************************/
void sendbyte(uchar Data)
{
  uchar  bitcount;
  for(bitcount=0;bitcount<8;bitcount++)    //要传送的数据长度为8位
   {
     if((Data<<bitcount)&0x80)             //判断发送位
           SDA=1;
     else  SDA=0;
	  
      _Nop();
	  _Nop();
       SCL=1;                              //置时钟线为高,通知被控器开始接收数据位
      wait();							   //保证时钟高电平周期大于4um                     
   	  SCL=0;
    }  
	   SDA=1;
      _Nop();
      _Nop();
//	  _Nop();    
                                     //8位发送后释放数据线,准备接收应答位
//    _Nop();
//    _Nop();

      SCL=1;
      _Nop();
      _Nop();
//      _Nop();
//	    _Nop();
//      _Nop();
//      _Nop();
//      _Nop();
	  if(SDA==1)
	        ack=0;
	  else  ack=1;                         //判断是否接收到应答信号
	  SCL=0;
      _Nop();
      _Nop();
	  _Nop();
      _Nop();

}
/************************************************************
字节数据接收函数
函数原形:
uchar  recbyte();
功能:用来接收从器件传来的数据,并判断总线错误(不发生应答信号),发送后请用应答函数
参数:无
返回值:读到的数据
***uchar*****************************************************/
uchar recbyte()
{ uchar recdata;
  uchar bitcount;
  recdata=0;
  SDA=1;                                    //置数据线为输入方式
  for(bitcount=0;bitcount<8;bitcount++)
    { _Nop();
 	  _Nop();						
       SCL=0;                               //置时钟线为低,准备接收数据位
      wait();                               //保证时钟低电平周期大于4um
       SCL=1;	                            //置时钟为高使数据线上数据有效
      _Nop();
      _Nop();
      _Nop();
      recdata=recdata<<1;
      if(SDA==1)
         recdata=recdata+1;                 //读数据位,接收的数据位放入recdata中
        _Nop();
        _Nop();
        _Nop();
     }
	 SCL=0;
	 _Nop();
     _Nop();
     _Nop();
	 return(recdata);
 }
/*******************************************************
应答子函数
函数原形:void ack_i2c(bit a);
功能:主控器进行应答信号,可以是应答或非应答信号。
参数:a应答信号
返回值:无
********************************************************/
void ack_i2c(bit a)
{ if(a==0)
          SDA=0;
  else    SDA=1;
    _Nop();
    _Nop();
    _Nop();
    _Nop();
       SCL=1;
    wait();
       SCL=0; // 清除时钟线,以便继续接收
    _Nop();
    _Nop();
    _Nop();
    _Nop();
 }
/**********************************************************************************
 向有子地址器件发送多字节数据函数
 函数原形:
 bit  sendstr(uchar subaddress1,uchar subaddress2,uchar *source,uchar num);
 功能:
 从启动总线到发送地址,子地址,结束总线的过程
 参数:
 subaddress1:子地址1
 subaddress2:子地址2
 source:发送内容的指针
 num:发送字节个数
 返回值: 
 如果返回1,表示操作成功;否则操作有误
 注意:使用前必须已结束总线
/**********************************************************************************/
 bit  sendstr(uchar subaddress1,uchar subaddress2,uchar *source,uchar num)
 { 
   uchar i;
   start_I2C();                              //启动总线
   sendbyte(ADDRWR);                          //发送器件地址
   if(ack==0)  return(0);
   sendbyte(subaddress1);                     //发送器件高子地址    
   if(ack==0)  return(0);
   sendbyte(subaddress2);                     //发送器件低子地址    
   if(ack==0)  return(0);
   for(i=0;i<num;i++)
   {
     sendbyte(*source);                       //发送数据
     if(ack==0) return(0);
     source++;
	 }
   stop_I2C();                                //结束总线
   return(1);                         
 }
/**********************************************************************************
 向有子地址器件读多字节数据函数
 函数原形:
 bit  recstr(uchar subaddress1,uchar subaddress2,uchar *source,uchar num);
 功能:
 从启动总线到发送地址,子地址,读数据,结束总线的过程
 参数:
 subaddress1:子地址1,subaddress2:子地址2,source:指向读出的内容放入的存储区的指针,num:读字节个数
 返回值: 
 如果返回1,表示操作成功;否则操作有误
 注意:使用前必须已结束总线
**********************************************************************************/
/*bit  recstr(uchar subaddress1,uchar subaddress2,uchar *source,uchar num)
{   uchar i;					     
   	start_I2C();                      // 启动总线
	sendbyte(ADDRWR);                  //发送器件地址—写
	if(ack==0)return(0);
	sendbyte(subaddress1);          //发送器件高子地址
	if(ack==0)return(0); 
	sendbyte(subaddress2);           //发送器件低子地址
	if(ack==0)return(0);
	start_I2C();                      // 再次启动总线
	sendbyte(ADDRRD);                  //再次发送器件地址—读
	if(ack==0)return(0);
    for(i=0;i<num-1;i++)	
	  {*source=recbyte();             //接收数据
	    ack_i2c(0);                    //发应答位
	    source++;
	  }
	   ack_i2c(1);                    //发非应答位
	   stop_I2C();                    //结束总线
       return(1);
  }*/
/**********************************************************************************
 向有子地址器件读多字节数据函数
 函数原形:
 bit  recstr(uchar subaddress1,uchar subaddress2,uchar *source,uchar num);
 功能:
 从启动总线到发送地址,子地址,读数据,结束总线的过程
 参数:
 subaddress1:子地址1,subaddress2:子地址2,source:指向读出的内容放入的存储区的指针,num:读字节个数
 返回值: 
 如果返回1,表示操作成功;否则操作有误
 注意:使用前必须已结束总线
**********************************************************************************/
bit  recstr(uchar subaddress1,uchar subaddress2)
{   					     
   	start_I2C();                        // 启动总线
	sendbyte(ADDRWR);                   //发送器件地址—写
	if(ack==0)return(0);
	sendbyte(subaddress1);              //发送器件高子地址
	if(ack==0)return(0); 
	sendbyte(subaddress2);             //发送器件低子地址
	if(ack==0)return(0);
	start_I2C();                       // 再次启动总线
	sendbyte(ADDRRD);                  //再次发送器件地址—读
	if(ack==0)return(0);
   	Rshu=recbyte();                    //接收数据
	   ack_i2c(1);                     //发非应答位
	   stop_I2C();                     //结束总线
       return(1);
  }
  void main()
  {   
      uchar *Point1,*Point2;	       
	  uchar ADDRWR=0xa0,ADDRRD=0xa1;
      Point1=Wshujiu; 
	  Point2=Rshujiu;
	  SDA=0;
      SCL=0;
	  WP=0;
	  _Nop();
	  //sendstr(0x00,0x00,Point1,1);
      //recstr (0x00,0x00);
	while(1) 
	{ 
      sendstr(0x00,0xee,Point1,1);
	  delay (200);
      recstr (0x00,0xee);									
	  P0=Rshu;
	  delay (100);
  	 }
  }






















⌨️ 快捷键说明

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