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

📄 i2c24lc单字写.c

📁 上载的程序可以用于PIC单片机,也可以用于430单片机,本人原创,到至今还没有发现哪位网友想出这种办法,希望站长能多加分.
💻 C
字号:
//。。。。。。。。。。。。。。。。。。。
//切记,当连续页写入时,中间要加入查询是否数据已写入标志;
//本程序在写完后;已加入//查询上次数据是否已写完;
//。。。。。。。。。。。。。。。。。。。
//本程序用于测试24LC的MSP430的程序,
//可用于24LC系列地址为8位或者为16位的,只需更改,
//(#define ic24_adr   1  //0代表8位地址,1代表16位地址,)

//本程序可用于对数组的读写,或者用于对单个变量的读写.
//对数组的读写时,取数组名既可,同时更改写字节数,
//  IIC(write_table,Quantity,incept_add,(AT24_ADD|write));
// ( #define Quantity  4   //读写字节数量)
//对变量的读写时,取变量地址既可;同时更改写字节数,
//  IIC(&write_table,Quantity,incept_add,(AT24_ADD|write));

//本程序算法部分可以用在其它部分,
//2007年6月7日调试已通过; 
#define uchar unsigned char
#define uint unsigned int  


#include "ic24LC.h"
//#define  XF_MCU    1       //定义用哪一种单片机,1时,用于PIC; 0时,用于MSP430;

#if      XF_MCU==0
//文件名:DS1302.c
#include<msp430x14x.h>

#else
#include<pic.h>
uchar pa_out;
uchar pb_out;
uchar pc_out;
uchar pd_out;
uchar pe_out;
#endif 

//写入AT24C02数据表
 unsigned char write_table[8]={1,2,3,4,5,6,7,8};
//unsigned char write_table=25;  //写入单字节时
//读出AT24C02数据缓冲区
 unsigned char read_Buff[8]={0}; 
//unsigned char read_Buff;       //读入单字节时
 unsigned char read_Buff1[8]={9,8,7,6,5,4,3,2}; 
//unsigned char read_Buff;       //读入单字节时
 
 unsigned char iic_check;   //检查标志,可选的.
 
 
//小延时********************************
nop_()
{
uchar hang=1;
while(hang--);
}

SomeNOP()
 {uchar hang=2;
  while(hang--);
  
 	}

//**************************************
//起始信号
void I2CStart(void)
 {
 NOT_INT;               //关总中断;
 SCLOUT;                //SCL口设为输出-------后加
 SDAOUT;                //SDA口设为输出 
 SDA1;                   
 //SCLOUT;                //SCL口设为输出 
 SCL1;
 SomeNOP(); SomeNOP();            //INI
 SDA0;                   
 SomeNOP(); SomeNOP();           //START
 SCL0;         
 }
//**************************************
//结束信号
void I2CStop(void)
 {
  SCL0;   
  SDA0;                   
  SomeNOP();              //INI
  SCL1;                                  
  SomeNOP(); 
  SDA1;                  //STOP
  OPE_INT;               //EA=1;
 }
//**************************************
//等待从器件接收方的应答
unsigned char WaitAck(void)
 {
 unsigned char errtime=255;      //因故障接收方无ACK,超时值为255。
 SDA1;                  
 SomeNOP();
 SCL1;
 SomeNOP();
 SDAIN;                 //SDA口设为输入
 while(SDA_STATE)       //SDA出现为0时,则为有应答
  { errtime--; 
   if (!errtime)        //errtime是否为0
    {I2CStop();        
     return NO;}        //返回为0(失败)
  }
 SDAOUT;                //SDA口设为输出 
 SCL0; 
 return OK;             //返回为1(成功)
 }
//**************************************
//主器件为接收方,从器件为发送方时,单片机发出应答信号
//MCU Send to IC
void SendAck(void)
 {
 SDA0;                 
 SomeNOP();
 SCL1;                 
 SomeNOP();
 SCL0;         
 }
//**************************************
//主器件为接收方,从器件为发送方时,非应答信号
void SendNotAck(void)
 {
 SDA1;  
 SomeNOP();
 SCL1;                   
 SomeNOP();
 SCL0; 
 }
//**************************************
//发送字节
 void I2CSendByte(unsigned char ch)
 {
  unsigned char i=8;
  while (i--)
  {
   SCL0;                //SCL=0;
   nop_();
   if(ch&0x80)
    SDA1;               //使SDA为1位
   else
    SDA0;               //使SDA为0位
   //---------------
   ch<<=1; 
   SomeNOP();
   SCL1;           
   SomeNOP();
   }
  SCL0;         
 }
//**************************************
//接收字节
unsigned char I2CReceiveByte(void)
 {
 unsigned char i=8;   //接收8位
 unsigned char ddata,timp;
 ddata=0;
 SDA1;                  
 SDAIN;               //SDA口设为输入
 while (i--)
 {
  ddata<<=1;           //将ddata位向高位移,于让位0
  SCL0;
  SomeNOP();
  SCL1;
  SomeNOP();
  
  timp = SDA_STATE;     //读入SDA,后加
  timp>>=SDA_MOV_BIT;   //将timp的SDA位数据移到位0
  ddata|=timp;          //将timp的SDA位数据移到ddata位0 
 }
 SCL0;                  //SCL=0;
 SDAOUT;                //(附加)SDA口设回为输出
 return  ddata;
 }
 

//正常操作时返回位值为0,有故障时返回位值为1.
//unsigned char *DataBuff数据缓冲区指针,char ByteQuantity字节数量,
//unsigned int Address IC片内地址,
//unsigned char ControlByte芯片控制字节-IC地址/读写位,
unsigned char IIC(unsigned char *DataBuff,char ByteQuantity,unsigned int Address,
         unsigned char ControlByte)
{
 unsigned char errorflag=error;      //错误标志位,1为错误,0为正确
 unsigned char i,q;                   //i为允许本次操作的最大次数
 unsigned char p;
 i=1;
 SCLOUT;                             //时钟口长设为输出
 
 while(i--)
 for(p=0;p<ByteQuantity;p++)
 { i=1;
 	 q=1;
 	while(i--)
 { 
   I2CStart();
   I2CSendByte(ControlByte&0xfe);   //指定芯片,此次必定为写
   if(!WaitAck())                   //涵数返回一个1为成功
     continue;//结束写操作,并i-1后,再来一次
   if(ic24_adr==0)                  //0代表8位地址,1代表16位地址,
     {I2CSendByte((unsigned char)Address);      //发送片内地址
      if(!WaitAck())                  //数返回一个1为成功                            
      continue;//结束写操作,并i-1后,再来一次
     }
   else
     {I2CSendByte(*((char *)&Address+1));       //发送片内高8位地址
      if(!WaitAck())                  //数返回一个1为成功                            
      continue;                      //结束写操作,并i-1后,再来一次
     
      I2CSendByte(*((char *)&Address+0));       //发送片内低8位地址
      if(!WaitAck())                  //数返回一个1为成功                            
      continue; //结束写操作,并i-1后,再来一次 
     }
     
     Address++;                      //IC片内地址,
   
  //------------------------------已经选定好IC
   if(!(ControlByte&0x01))        //本次操作是读还是写
      {                           //写操作
     errorflag=right;             //清错误标志位为0
     while(q--)        //操作j个数字节
          {
            I2CSendByte(*DataBuff++);//发送        
         if(WaitAck())            //涵数返回一个1为成功,涵数返回一个0为失败
              continue;           //成功,下一个数据循环(跳while)
         errorflag=error;          //不应答,失败了. errorflag=1
         break;                   //退出写操作
       }
     if(errorflag==error)         //经过写完后,如果最后errorflag标志为1,则表示有错误
           continue;              //结束写操作,并i-1后,再来一次
     break;                       //写操作完成
      }  
   else                           //则为读操作
     {  I2CStart();                //开始       
        I2CSendByte(ControlByte);
        if(!WaitAck())                      //涵数返回一个1为成功
        {continue;}                         //结束此操作,并i-1后,再来一次
     while(q--)                  //读入ByteQuantity个数字节
           {*DataBuff++=I2CReceiveByte();   //连续读入ByteQuantity个数据
              SendAck();}                   //主机向从机发出应答,表示主机已接收            
        *DataBuff=I2CReceiveByte();         //读入最后个数据
     SendNotAck();                          //最后发出不应答信号(位),表示主机不再读了.
     errorflag=right;                       //向错误标志位写0(right),表示读数据正确.
     break;}                                //读操作完成*/
     }
 I2CStop();                                 //停止,结束IIC总线
 if(!(ControlByte&0x01))                    //当本次操作为写时,查询数据是否已写完;
 	 I2C_QUERY();                             //查询本次数据是否已写完;
 return(errorflag);                         //返回操作成败标志
}
}

//***********************************************************************

//******************************************************


//******************************************************
//软延时
void delay(unsigned int n)
{unsigned int k;
 for(k=0;k<n;k++);
}


//******************************************************
//检验两组数据是否正确,如在检验数据中有一组不正确,则退出.
//*Data_REF参考值数组,*Data_CHK被检验数组,n检验数量
//并返回一个成败标志.
unsigned char data_check(unsigned char *Data_REF, unsigned char *Data_CHK, 
                         unsigned char n)
{unsigned char chk ;
 while(n) 
  {
   if(Data_REF[n-1]==Data_CHK[n-1])     //进行校对
    { chk = right;                      //正确
      n--;                              //下一位
    }
   else
    { chk = error;                      //校对有错
      continue;                         //马上退出
    }
  }
 return chk ;                           //返回校对成败标志.
}

void I2C_QUERY(void)                 //查询本次数据是否已写完;
{
	 while(1)
 { 
   I2CStart();
   I2CSendByte((AT24_ADD|write)&0xfe);   //指定芯片,此次必定为写
   if(WaitAck())                         //涵数返回一个1为成功
     {break;                              //结束写操作,
      I2CStop();}                            //停止,结束IIC总线
  }
}



void I2C_CLR(void)                      //清24LC子程序;
{
uint a,b;
for(a=0;a<400;a++)
  {
  b=a*8;
  iic_check=IIC(read_Buff,Quantity,b,(AT24_ADD|write));
  
//  I2C_QUERY();                         //查询本次数据是否已写完;
  }
}

void I2C_WR(void)                     //页连续写子程序
{
uint a,b;
//for(a=0;a<400;a++)
for(a=0;a<406;a++)
{
//b=((a-168)*8+160);
b=a*8;
iic_check=IIC(write_table,Quantity,b,(AT24_ADD|write));

//I2C_QUERY();                           //查询本次数据是否已写完;
}
}



//******************************************************
void main(void)
{
#if  XF_MCU==0
  WDTCTL=WDTPW+WDTHOLD;         //停止WDT
#endif
 
I2C_CLR();                    //清24LC子程序;
I2C_WR();                     //页连续写子程序
while(1)
  {
//写入数据所在的数组或者地址?
  //向AT24C02芯片写入字节数
  //向AT24C02芯片写入片内地址
  //芯片控制字节-IC地址/读写位
  iic_check=IIC(write_table,Quantity,incept_add,(AT24_ADD|write));
 //iic_check=IIC(&write_table,Quantity,incept_add,(AT24_ADD|write)); //写入单字节时
  delay(500);                 //写入后,做一个适当的延时
  //读入数据所在的数组或者地址
  //向AT24C02芯片读入字节数
  //向AT24C02芯片读入片内地址
  //芯片控制字节-IC地址/读写位
  iic_check=IIC(read_Buff,Quantity,incept_add,(AT24_ADD|read));
 //iic_check=IIC(&read_Buff,Quantity,incept_add,(AT24_ADD|read));  //读入单字节时
  //判别校验是否成功
  if(!(data_check(write_table,read_Buff,Quantity)))
  ; 
} 
}

⌨️ 快捷键说明

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