搜索
bottom↓
回复: 42

共享24c256操作函数,连续读写

[复制链接]

出0入0汤圆

发表于 2005-9-30 14:48:34 | 显示全部楼层 |阅读模式
刚刚调好了个24c256的操作,自己在程序里搞了个连续读写的函数!很烦那页写跨页的问题,所以干脆做了个通用点的函数,小于3字节的写就用随机写,大于3字节的就用页写!共享拉!

真正供其他操作调用的函数是:

unchar SeqWriteTo24c256(unchar sla_add,unint addr_op,unchar write_size,unchar *write_buf);

unchar SeqReadFrom24c256(unchar sla_add,unint addr_op,unchar read_size,unchar *read_buf);

其他的都是本文件内自己调用的函数!!



//*****************************************************调试函数

void DebugEepromService(void)

{

  unchar debug_buf[255];

  debug_buf[0]=0x91;

  debug_buf[1]=0x92;

  debug_buf[2]=0x93;

  debug_buf[3]=0x94;

  debug_buf[4]=0x95;

  debug_buf[250]=0x05;

  debug_buf[251]=0x06;

  debug_buf[252]=0x07;

  debug_buf[253]=0x08;

  debug_buf[254]=0x09;

  SeqWriteTo24c256(EEP1_ADDR,1,255,debug_buf);

  SeqReadFrom24c256(EEP1_ADDR,1,255,debug_buf);

}

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







#define IIC_SDA_PB                0x20

#define IIC_SCL_PB                0x80

#define IIC_DEL_WAIT        0x10                //>4.7us(12.80us)  for Fre=11.0592M

#define IIC_DEL_WRITE        0x2700                //>6ms(7266.54us=7.266ms) for Fre=11.0592M



#define EEP1_ADDR                0xa4

#define PAGE_CAP_BYTE        64                //24C256页写容量:64字节





/*

功能函数文件

2005-9-22 9:54 by xth

版本: v1.0

--------------------------------------------

Mcu: avr mega32          Frequency: 11.0592M

--------------------------------------------

功能概述:Eeprom操作文件

--------------------------------------------

*/

//=============================函数声明

//----------IIC操作调用函数

void IicDelayService(unint delay_time);

void IicStartBitSend(void);

void IicStopBitSend(void);

void IicAckService(unchar ack_data);

unchar IicSendByteService(unchar tx_data);

unchar IicAccByteService(void);

//----------At24c256操作函数

unchar RandWriteByteTo24c256(unchar sla_add,unint addr_op,unchar data_op);

unchar WritePageTo24c256(unchar sla_add,unint addr_op,unchar *write_data_buf);

unchar SeqWriteTo24c256ByPage(unchar sla_add,unint addr_op,unchar write_size,unchar *write_buf);

unchar SeqWriteTo24c256(unchar sla_add,unint addr_op,unchar write_size,unchar *write_buf);

unchar SeqReadFrom24c256(unchar sla_add,unint addr_op,unchar read_size,unchar *read_buf);

//=============================函数定义

void IicDelayService(unint delay_count)

{

  unint count;

  for(count=0;count<delay_count;count++)

   asm("NOP");

}



void IicStartBitSend(void)

{

  PORTB |= IIC_SCL_PB;        //发送起始条件的时钟信号

  asm("NOP");

  PORTB |= IIC_SDA_PB;        //起始条件建立时间大于4.7us,延时

  IicDelayService(IIC_DEL_WAIT);

  PORTB &= ~IIC_SDA_PB;

  IicDelayService(IIC_DEL_WAIT);

  PORTB &= ~IIC_SCL_PB; //钳住I2C总线,准备发送或接收数据

  asm("NOP");

}



void IicStopBitSend(void)

{

  PORTB &= ~IIC_SDA_PB;//发送结束条件的时钟信号

  IicDelayService(IIC_DEL_WAIT);

  PORTB |= IIC_SCL_PB; //结束条件建立时间大于4μs

  IicDelayService(IIC_DEL_WAIT);

  PORTB |= IIC_SDA_PB;

  asm("NOP");

}



void IicAckService(unchar ack_data)

{//作为主控器件应答->发应答或非应答信号

  if(ack_data==0) PORTB &= ~IIC_SDA_PB;

  else PORTB |= IIC_SDA_PB;

  IicDelayService(IIC_DEL_WAIT);

  PORTB |= IIC_SCL_PB;

  IicDelayService(IIC_DEL_WAIT);

  PORTB &= ~IIC_SCL_PB;//清时钟线,钳住I2C总线以便继续接收

  asm("NOP");

}



unchar IicSendByteService(unchar tx_data)

{//将字节发送出去,可以是地址,也可以是数据,发完后等待应答并返回

  unchar bit_count,ack_flag;

  for(bit_count=0;bit_count<8;bit_count++)

   {

           if((tx_data<<bit_count)&0x80)

            PORTB |= IIC_SDA_PB;

           else

            PORTB &= ~IIC_SDA_PB;

           IicDelayService(IIC_DEL_WAIT);

           PORTB |= IIC_SCL_PB;                                //置时钟线为高,通知被控器开始接收数据位

           IicDelayService(IIC_DEL_WAIT);                //保证时钟高电平周期大于4μs

           PORTB &= ~IIC_SCL_PB;

   }

  IicDelayService(IIC_DEL_WAIT);

  PORTB &= ~IIC_SDA_PB;

  DDRB &= ~IIC_SDA_PB;                                        //SDA置成输入

  asm("NOP");

  PORTB |= IIC_SCL_PB;

  IicDelayService(IIC_DEL_WAIT);

  IicDelayService(IIC_DEL_WAIT);

  if(PINB&IIC_SDA_PB)                //判断是否接收到应答信号

   ack_flag=NO;

  else

   ack_flag=YES;                        //有应答信号

  DDRB |= IIC_SDA_PB;

  PORTB &= ~IIC_SCL_PB;

  asm("NOP");

  return(ack_flag);

}



unchar IicAccByteService(void)

{//接收从器件传来的数据,并判断总线错误

  unchar bit_count,get_data;

  DDRB &= ~IIC_SDA_PB;

  get_data=0;

  for(bit_count=0;bit_count<8;bit_count++)

   {

           asm("NOP");

           PORTB &= ~IIC_SCL_PB;                                //置时钟线为低,准备接收数据位

    IicDelayService(IIC_DEL_WAIT);                //时钟低电平周期大于4.7μs;

        PORTB |= IIC_SCL_PB;                                //置时钟线为高使数据线上数据有效

        get_data<<=1;

        if(PINB&IIC_SDA_PB)

         get_data++;

        asm("NOP");

        asm("NOP");

   }

  PORTB &= ~IIC_SCL_PB;

  DDRB |= IIC_SDA_PB;

  asm("NOP");

  return(get_data);

}



unchar RandWriteByteTo24c256(unchar sla_add,unint addr_op,unchar data_op)

{

  unchar result_now,temp_data;

  IicStartBitSend();                                                        //起始条件

  temp_data=sla_add;                                                        //从器件地址

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=addr_op>>8;                                                        //操作单元地址高8位

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=addr_op;                                                        //操作单元地址低8位

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=data_op;                                                        //操作数据

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  IicStopBitSend();                                                                //停止条件

  IicDelayService(IIC_DEL_WRITE);

  result_now=YES;

  return(result_now);

}



unchar SeqReadFrom24c256(unchar sla_add,unint addr_op,unchar read_size,unchar *read_buf)

{//addr “roll over” during read:from last byte of the last page, to the first byte of the first page

  unchar result_now,temp_data,read_count;

  IicStartBitSend();                                                        //起始条件

  temp_data=sla_add;                                                        //从器件地址

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=addr_op>>8;                                                        //操作单元地址高8位

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=addr_op;                                                        //操作单元地址低8位

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  IicStartBitSend();

  temp_data=sla_add+1;                                                        //读操作

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  for(read_count=0;read_count<read_size-1;read_count++)

   {                                                                                        //连续读数据

           *(read_buf+read_count)=IicAccByteService();

           IicAckService(NO);

   }

  *(read_buf+read_count)=IicAccByteService();

  IicAckService(YES);

  IicStopBitSend();

  result_now=YES;

  return(result_now);

}



unchar WritePageTo24c256(unchar sla_add,unint addr_op,unchar *write_data_buf)

{//页写

  unchar count,result_now,temp_data;

  IicStartBitSend();                                                        //起始条件

  temp_data=sla_add;                                                        //从器件地址

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=addr_op>>8;                                                        //操作单元地址高8位

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  temp_data=addr_op;                                                        //操作单元地址低8位

  result_now=IicSendByteService(temp_data);

  if(result_now==NO) return(result_now);

  for(count=0;count<PAGE_CAP_BYTE;count++)

   {//连续写

    temp_data=*(write_data_buf+count);

    result_now=IicSendByteService(temp_data);

    if(result_now==NO) return(result_now);

   }

  IicStopBitSend();                                                                //停止条件

  IicDelayService(IIC_DEL_WRITE);

  result_now=YES;

  return(result_now);

}



unchar SeqWriteTo24c256ByPage(unchar sla_add,unint addr_op,unchar write_size,unchar *write_buf)

{//addr “roll over” during write:from last byte of the current page to first byte of the same page.

  unint page_write,read_addr,temp_op_int;

  unchar data_count,result_out,modify_count,count,write_data_buf[PAGE_CAP_BYTE];

  result_out=YES;

  data_count=0;

  while(write_size>0)

   {

           page_write=addr_op/PAGE_CAP_BYTE;                                //得到当前页

    read_addr=page_write*PAGE_CAP_BYTE;

    SeqReadFrom24c256(sla_add,read_addr,PAGE_CAP_BYTE,write_data_buf);

    temp_op_int=addr_op&(PAGE_CAP_BYTE-1);                        //得到在页内的起始字节地址

    if(temp_op_int+write_size>=PAGE_CAP_BYTE)

     {

      modify_count=PAGE_CAP_BYTE;

      addr_op=(page_write+1)*PAGE_CAP_BYTE;                        //写下一页的起始地址

     }

    else

     modify_count=write_size;

    count=temp_op_int;

    write_size=write_size-modify_count+count;                //写下一页的数据量

    for(;count<modify_count;count++,data_count++)

     write_data_buf[count]=*(write_buf+data_count);

    result_out=WritePageTo24c256(sla_add,read_addr,write_data_buf);

   }

  return(result_out);

}



unchar SeqWriteTo24c256(unchar sla_add,unint addr_op,unchar write_size,unchar *write_buf)

{//连续写(非页写)

  unchar write_result;

  if(write_size<3)

   {//如果要写入的数据小于3个,则用随机写实现

    write_result=RandWriteByteTo24c256(sla_add,addr_op,*write_buf);

    write_result=RandWriteByteTo24c256(sla_add,addr_op+1,*(write_buf+1));

   }

  else

   write_result=SeqWriteTo24c256ByPage(sla_add,addr_op,write_size,write_buf);

  return(write_result);

}


-----此内容被wogudan于2005-10-11,11:27:44编辑过

出0入0汤圆

发表于 2005-9-30 17:38:21 | 显示全部楼层
谢谢

出0入50汤圆

发表于 2005-9-30 19:29:42 | 显示全部楼层
谢谢楼主分享,今天我自己刚搞好读写C51对24C01---16的一个读写程序,准备过完节做256的,有个AVR的就更好了。

出0入0汤圆

发表于 2006-3-19 17:53:01 | 显示全部楼层
谢谢楼主分享!

出0入0汤圆

发表于 2006-3-20 13:25:56 | 显示全部楼层
是ICC吗?

出0入0汤圆

发表于 2006-8-10 20:53:56 | 显示全部楼层
谢谢了,先看看

出0入0汤圆

发表于 2006-9-23 18:17:51 | 显示全部楼层
如何对24C256的A0,A1接线呢?

出0入0汤圆

发表于 2006-11-24 15:31:54 | 显示全部楼层
ilikemcu,我弄了一个24c16的读写程序,可是没反应,能帮我看看吗?

出0入0汤圆

发表于 2006-11-24 16:32:31 | 显示全部楼层
点击此处打开armok01136382.pdf

出0入0汤圆

发表于 2006-11-24 23:55:31 | 显示全部楼层
谢谢正需要用这个程序,不过代码有点多。



程序好像是用ICC写的吧。

出0入0汤圆

发表于 2006-12-12 18:36:07 | 显示全部楼层
”//起始条件建立时间大于4.7us,延时 “



根据24C256的工作电压不同,它的相关延时也不同。

出0入0汤圆

发表于 2006-12-13 13:19:49 | 显示全部楼层
还没有过TWI呢,准备试试,谢谢了

出0入0汤圆

发表于 2007-1-9 17:34:29 | 显示全部楼层
楼主,你好。看了你的程序,有几个问题想问一下:

1、你用的编译环境是不是ICCAVR?

2、我用Mega128读写24C256时是不是和你用Mega32读写类似,分为IIC操作调用函数和At24c256操作函数两部分来做,我这边有一个例程从网上看到的http://blog.21ic.com/user1/3240/archives/2006/25216.html

他用的是51单片机,也是IIC协议读写24C256。

是不是用IIC读写EEPROM一定要写Mega128里面那些和IIC(TWI)有关的寄存器呢?比如TWBR、TWCR等等?

我刚学习AVR128,很多不懂,请大虾们指教~~~~

出0入0汤圆

发表于 2007-1-9 17:38:29 | 显示全部楼层
还有#define EEP1_ADDR      0xa4  

24c256的地址格式是 1010 A2 A1 A0 R/W

为何置为0xa4呢?这个外扩存储器地址的选择和所用单片机的存储器地址分配有关吗?

出0入0汤圆

发表于 2007-5-24 17:20:38 | 显示全部楼层
define EEP1_ADDR      0xa4   

应该是楼主的AT24C256硬件地址配置成10了

24c256的地址格式是 1010 A2 A1 A0 R/W

0xA4=0B10100100,   A1=1,A0=0



先下测试,晚上试验

出0入0汤圆

发表于 2007-5-25 11:43:31 | 显示全部楼层
是用I/O口模拟TWI时序么?

出0入0汤圆

发表于 2007-5-25 21:06:37 | 显示全部楼层
调用SeqWriteTo24c256(unsigned char sla_add,unsigned int addr_op,unsigned char write_size,unsigned char *write_buf)函数



写入的数据小于64字节,似乎程序会停住,有朋友测试过吗,

出0入0汤圆

发表于 2007-5-25 21:41:11 | 显示全部楼层
R/W 读写控制在程序中没有看出来,

演示读的函数

SeqReadFrom24c256(EEP1_ADDR,1,255,debug_buf);

此时为EEP1_ADDR(0xA4),



24c256的地址格式是 1010 A2 A1 A0 R/W

子程序没有发现对读写指令的识别,

改为SeqReadFrom24c256(EEP1_ADDR+1,1,255,debug_buf)可能还说的过,

请楼主帮忙分析

出0入0汤圆

发表于 2007-5-26 10:19:51 | 显示全部楼层
是我看错了,找到了



if(result_now==NO) return(result_now);

  IicStartBitSend();

  temp_data=sla_add+1;                     //读操作

  result_now=IicSendByteService(temp_data);



YES,NO是怎么定义的,是GCC带的吗,我是改到ICC下用

出0入0汤圆

发表于 2008-1-24 16:41:58 | 显示全部楼层
谢谢!分享是一种快乐!

出0入0汤圆

发表于 2008-7-7 11:01:47 | 显示全部楼层
太谢谢了!正是需要........

出0入0汤圆

发表于 2008-7-7 21:55:49 | 显示全部楼层
以下是我自己用IO口模拟的IIC读写代码,经过测试好久了.cm_ASK_polling();为忙检函数,可以用延时代替.
#include <iom8v.h>
#include<macros.h>  
#define uint unsigned int
#define uchar unsigned char
#define  SCL    3
#define  SDA    2
#define  CM_CLK_HI    (PORTD |= (1<<SCL))
#define  CM_CLK_LO    (PORTD &=~(1<<SCL))
#define  CM_DATA_HI   (PORTD |= (1<<SDA))
#define  CM_DATA_LO   (PORTD &=~(1<<SDA))
#define  CM_DATA_OUT  (DDRD |= (1<<SDA))
#define  CM_CLK_OUT   (DDRD |= (1<<SCL))
#define  CM_DATA_IN   (DDRD &=~(1<<SDA))
#define  CM_DATA_RD   (PIND &(1<<SDA))
////////////////////////////////////////////////////////////////////////////////
//PORTD.2 PORTD.3 with pull_up 4.7K resistor.
////////////////////////////////////////////////////////////////////////////////
void delay_50ms(uint t)//1M,for 1us
{
uint j;   
for(;t>0;t--)
  for(j=6245;j>0;j--)
  ;
}
////////////////////////////////////////////////////////////////////////////////
void cm_Delay(uint ucDelay)//Delay_time=(0.854*ucDelay+2.75)us
{                          //ucDelay=(Delay_time-2.75)/0.854
  while(ucDelay--);//NOP();
}
////////////////////////////////////////////////////////////////////////////////
void cm_Clockhigh(void)
{
    cm_Delay(2);
    CM_CLK_HI;
    cm_Delay(2);
}
////////////////////////////////////////////////////////////////////////////////
void cm_Clocklow(void)
{
    cm_Delay(2);
    CM_CLK_LO;
    cm_Delay(2);
}
////////////////////////////////////////////////////////////////////////////////
void cm_ClockCycle(void)
{
    cm_Clocklow();
    cm_Clockhigh();
}
////////////////////////////////////////////////////////////////////////////////
void cm_ClockCycles(uchar n)
{
    uchar i;
    for (i = 0; i < n; ++i) cm_ClockCycle();
}
////////////////////////////////////////////////////////////////////////////////
void START(void)
{     
      cm_Clocklow();
      CM_DATA_HI;
      cm_Delay(5);
      cm_Clockhigh();
      cm_Delay(5);
      CM_DATA_LO;
      cm_Delay(10);
      cm_Clocklow();       //after start,SCL=0,SDA=1
      CM_DATA_HI;
      cm_Delay(10);
}
////////////////////////////////////////////////////////////////////////////////
void STOP(void)
{
    cm_Clocklow();
    CM_DATA_LO;
    cm_Delay(5);
    cm_Clockhigh();
    cm_Delay(10);
    CM_DATA_HI;
    cm_Delay(5);
}
////////////////////////////////////////////////////////////////////////////////
uchar cm_Read(void)
{
    uchar i;
    uchar rByte = 0;
    CM_DATA_IN;                          // Set data line to be an input
    CM_DATA_HI;
    for(i=0x80; i; i=i>>1)
    {
        cm_ClockCycle();
        if (CM_DATA_RD) rByte |= i;
        cm_Clocklow();  
    }
    CM_DATA_OUT;                        // Set data line to be an output
    return rByte;
}
////////////////////////////////////////////////////////////////////////////////
uchar cm_Write(uchar ucData)
{
    uchar i;
    CM_DATA_OUT;                         // Set data line to be an output
    for(i=0; i<8; i++) // Send 8 bits of data
    {                 
        cm_Clocklow();
        if (ucData&0x80) CM_DATA_HI;
        else             CM_DATA_LO;
        cm_Clockhigh();
        ucData = ucData<<1;
    }
    cm_Clocklow();
                                     // wait for the ack
    CM_DATA_IN;                      // Set data line to be an input
    cm_Delay(8);
    cm_Clockhigh();
    while(i>1)                     // loop waiting for ack (loop above left i == 8)
   {    cm_Delay(2);
        if (CM_DATA_RD) i--;        // if SDA is high level decrement retry counter
        else {i = 0;break;}
    }      
    cm_Clocklow();
    CM_DATA_OUT;                     // Set data line to be an output
    return i;                        //only i=0,write successfully
}
////////////////////////////////////////////////////////////////////////////////
uchar cm_ASK_polling(void)
{uchar i,j=50;
uchar ucData=0xA0;
  while(j>1)
  { START();
    CM_DATA_OUT;                         // Set data line to be an output
    for(i=0; i<8; i++) // Send 8 bits of data
    {      
        cm_Clocklow();
        if (ucData&0x80) CM_DATA_HI;
        else             CM_DATA_LO;
        cm_Clockhigh();
        ucData = ucData<<1;
    }
    ucData=0xA0;
    cm_Clocklow();
    CM_DATA_IN;                      // Set data line to be an input
    cm_Delay(8);
    cm_Clockhigh();
    cm_Delay(2);
    if (CM_DATA_RD)j--;        // if SDA is high level decrement retry counter
    else {j = 0;break;}
    cm_Clocklow();
    CM_DATA_OUT;               // Set data line to be an output
  }
    cm_Clocklow();
   // CM_DATA_HI;//
    CM_DATA_OUT;                     
    return j;                       //if j=0,slave ask,if j=1,slave not ask
}
////////////////////////////////////////////////////////////////////////////////
void cm_AckNak(uchar ucAck)              //TRUE,send a ASK
{
    CM_DATA_OUT;                    // Data line must be an output to send an ACK
    cm_Clocklow();
    if (ucAck) CM_DATA_LO;               // Low on data line indicates an ACK
    else       CM_DATA_HI;               // High on data line indicates an NACK
    cm_Delay(4);
    cm_Clockhigh();
    cm_Delay(12);
    cm_Clocklow();
}
////////////////////////////////////////////////////////////////////////////////
void  WRITE_24C256(uchar *save_address,uchar SLA,uint address,uchar n)//only max=64 bytes
{uint i;

  START();                                               //STRAT signal
  cm_Write(SLA);
  cm_Write(address/256);                                        //24C256 address=0xA0
  cm_Write(address%256);                                     //24C256 memory address
  for(i=0;i<n;i++)cm_Write(save_address);             //write data to 24C256
  STOP();                                                //STOP signal
  cm_ASK_polling();
}
////////////////////////////////////////////////////////////////////////////////
void READ_24C256(uchar *save_address,uchar SLA,uint address,uint n)
{uint i;
  START();                                           //STRAT signal
  cm_Write(SLA);  
  cm_Write(address/256);                                        //24C256 address=0xA0
  cm_Write(address%256);                                 //24C256 memory address
  START();                                           //STRAT signal
  cm_Write(SLA+1);                                   //24C256 read address=0xA0+1

  for(i=0;i<n-1;i++)
  {save_address=cm_Read();                   //read data from 24C256,need  ASK
   cm_AckNak(1);
  }
   save_address=cm_Read();                   //read data from 24C02,need no ASK
   cm_AckNak(0);

  STOP();                                       //STOP signal
}
////////////////////////////////////////////////////////////////////////////////

出0入0汤圆

发表于 2008-7-7 22:00:36 | 显示全部楼层
以下是用mega8的TWI模块来读写24c02,供参考
uchar ASK_polling(void)
{uchar i=50;
  TWBR=0x20;                                 //F=100K
  TWSR=0x00;                                 //F=(CPU CLOCK frequency)/(16+2(TWBR)*4**TWPS)
while(i>1)
{ TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //STRAT signal
  while(!(TWCR & (1<<TWINT)) );
  TWDR=0xA0;                                 //24C02 address=0xA0
  TWCR=(1<<TWINT) | (1<<TWEN);               
  while(!(TWCR & (1<<TWINT)) );   
  if ((TWSR & 0xF8) !=0x18)i--;
  else {i=0;break;}
}
return i;
}  
void  WRITE_24C02(uchar *data_address,uchar SLA,uchar address,uchar n)//only 8 bytes
{uchar i;
  TWBR=0x20;                                 //F=100K
  TWSR=0x00;                                 //F=(CPU CLOCK frequency)/(16+2(TWBR)*4**TWPS)
  TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //STRAT signal
  while(!(TWCR & (1<<TWINT)) );            
  TWDR=SLA;                                  //24C02 address=0xA0
  TWCR=(1<<TWINT) | (1<<TWEN);               
  while(!(TWCR&(1<<TWINT)));   
  TWDR=address;                              //24C02 memory address
  TWCR=(1<<TWINT) | (1<<TWEN);              
  while(!(TWCR & (1<<TWINT)) );   
  for(i=0;i<n;i++)                           //write data to 24C02
  {   
    TWDR=data_address;
    TWCR=(1<<TWINT) | (1<<TWEN) ;
    while(!(TWCR & (1<<TWINT)));
  }
  TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);  //STOP signal
  while(i--)NOP();
  ASK_polling();
}
void READ_24C02(uchar *save_address,uchar SLA,uchar address,uchar n)
{uchar i;
  TWBR=0x20;                                 //F=100K
  TWSR=0x00;                                 //F=(CPU CLOCK frequency)/(16+2(TWBR)*4**TWPS)
  TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //STRAT signal
  while(!(TWCR & (1<<TWINT)) );            
  TWDR=SLA;                                  //24C02 address=0xA0
  TWCR=(1<<TWINT) | (1<<TWEN);               
  while(!(TWCR & (1<<TWINT)) );              
  TWDR=address;                              //24C02 memory address
  TWCR=(1<<TWINT) | (1<<TWEN);               
  while(!(TWCR & (1<<TWINT)) );  
  TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //STRAT signal
  while(!(TWCR & (1<<TWINT)) );            
  TWDR=SLA+1;                                //24C02 read address=0xA0+1
  TWCR=(1<<TWINT) | (1<<TWEN);               
  while(!(TWCR & (1<<TWINT)) );  
  
  for(i=0;i<n-1;i++)                         //read data from 24C02,need  ASK
  {
    TWCR=(1<<TWINT) | (1<<TWEN)| (1<<TWEA) ;
    while(!(TWCR&(1<<TWINT)));
    save_address=TWDR;
  }
  TWCR=(1<<TWINT) | (1<<TWEN);               //read data from 24C02,need no ASK
  while(!(TWCR&(1<<TWINT)));
  save_address= TWDR;
  TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);  //STOP signal
}

出0入228汤圆

发表于 2008-7-7 22:19:38 | 显示全部楼层
MARK

出0入93汤圆

发表于 2008-7-8 08:53:35 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-7-8 15:50:45 | 显示全部楼层
收藏

出0入0汤圆

发表于 2008-7-8 16:28:28 | 显示全部楼层
MARK~~

出0入0汤圆

发表于 2009-4-15 13:46:25 | 显示全部楼层
waltonzxh

能否把你程序中的两个函数中的参数解释一下
void  WRITE_24C02(uchar *data_address,uchar SLA,uchar address,uchar n)

void READ_24C02(uchar *save_address,uchar SLA,uchar address,uchar n)

出0入4汤圆

发表于 2009-4-20 20:35:45 | 显示全部楼层
记号。

出0入0汤圆

发表于 2009-4-21 14:06:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-5-20 15:09:40 | 显示全部楼层
有没有牛人把他改成51的啊!我不是很了解avr现在想用这个。我有个256读写程序似乎写多了就有错

#include   <reg52.h>   
#include   <intrins.h>
      #define ERROR 10
      sbit SDA=P2^4;
      sbit SCL=P2^3;
      enum eepromtype
      {AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};
      enum eepromtype enumer;
      unsigned char code buf1 []={1,3,5,7,9,10,11,12,13,15}; /* 发送缓冲区 */
      unsigned char buf2 [10]; /* 接收缓冲区 */


      /* 一个通用的24C01-24C256共9种EEPROM的字节读写操作程序,
      此程序有五个入口条件,分别为读写数据缓冲区指针,
      进行读写的字节数,EEPROM首址,EEPROM控制字节,
      以及EEPROM类型。此程序结构性良好,具有极好的容错性,程序机器码也不多:
      DataBuff为读写数据输入/输出缓冲区的首址
      Length 为要读写数据的字节数量
      Addr 为EEPROM的片内地址 AT24256为0~32767
      Control 为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W),其中R/W=1,
      表示读操作,R/W=0为写操作,A2,A1,A0为EEPROM的页选或片选地址;
      enumer为枚举变量,需为AT2401至AT24256中的一种,分别对应AT24C01至AT24C256;
      函数返回值为一个位变量,若返回1表示此次操作失效,0表示操作成功;
      ERROR为允许最大次数,若出现ERRORCOUNT次操作失效后,则函数中止操作,并返回1
      SDA和SCL由用户自定义,这里暂定义为P3^0和P3^1; */


      /* ----- AT24C01~AT24C256 的读写程序 ------ */
      bit RW24xx(unsigned char *DataBuff,unsigned char Length,unsigned int Addr,

      unsigned char Control,enum eepromtype enumer)
      { void Delay(unsigned char DelayCount); /* 延时 */
      void Start(void); /* 启动总线 */
      void Stop(void); /* 停止IIC总线 */
      bit RecAck(void); /* 检查应答位 */
      void NoAck(void); /* 不对IIC总线产生应答 */
      void Ack(void); /* 对IIC总线产生应答 */
      unsigned char Receive(void); /* 从IIC总线上读数据子程序 */
      void Send(unsigned char sendbyte); /* 向IIC总线写数据 */
      unsigned char data j,i=ERROR;
      bit errorflag=1; /* 出错标志 */
      while(i--)
      { Start(); /* 启动总线 */
      Send(Control & 0xfe); /* 向IIC总线写数据 */
      if(RecAck()) continue; /* 如写正确结束本次循环 */
      if(enumer > AT2416)
      { Send((unsigned char)(Addr >> 8));
      if(RecAck()) continue;
      }
      Send((unsigned char)Addr); /* 向IIC总线写数据 */
      if(RecAck()) continue; /* 如写正确结束本次循环 */
      if(!(Control & 0x01))
      { j=Length;
      errorflag=0; /* 清错误特征位 */
      while(j--)
      { Send(*DataBuff++); /* 向IIC总线写数据 */
      if(!RecAck()) continue; /* 如写正确结束本次循环 */
      errorflag=1;
      break;
      }
      if(errorflag==1) continue;
      break;
      }
      else
      { Start(); /* 启动总线 */
      Send(Control); /* 向IIC总线写数据 */
      if(RecAck()) continue;
      while(--Length) /* 字节长为0结束 */
      { *DataBuff ++= Receive();
      Ack(); /* 对IIC总线产生应答 */
      }
      *DataBuff=Receive(); /* 读最后一个字节 */
      NoAck(); /* 不对IIC总线产生应答 */
      errorflag=0;
      break;
      }
      }
      Stop(); /* 停止IIC总线 */
      if(!(Control & 0x01))
      { Delay(255); Delay(255); Delay(255); Delay(255);
      }
      return(errorflag);
      }


      /* * * * * 以下是对IIC总线的操作子程序 * * * * */
      /* * * * * * 启动总线 * * * * */
      void Start(void)
      { SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平表示 */
      SDA=1; /* 一个"开始"状态,该状态必须在其他命令之前执行 */
      SCL=1;
      _nop_(); _nop_(); _nop_();
      SDA=0;
      _nop_(); _nop_(); _nop_(); _nop_();
      SCL=0;
      SDA=1;
      }


      /* * * * * 停止IIC总线 * * * * */
      void Stop(void)
      { SCL=0; /*SCL处于高电平时,SDA从低电平转向高电平 */
      SDA=0; /*表示一个"停止"状态,该状态终止所有通讯 */
      SCL=1;
      _nop_(); _nop_(); _nop_(); /* 空操作 */
      SDA=1;
      _nop_(); _nop_(); _nop_();
      SCL=0;
      }


      /* * * * * 检查应答位 * * * * */
      bit RecAck(void)
      { SCL=0;
      SDA=1;
      SCL=1;
      _nop_(); _nop_(); _nop_(); _nop_();
      CY=SDA; /* 因为返回值总是放在CY中的 */
      SCL=0;
      return(CY);
      }


      /* * * * *对IIC总线产生应答 * * * * */
      void Ack(void)
      { SDA=0; /* EEPROM通过在收到每个地址或数据之后, */
      SCL=1; /* 置SDA低电平的方式确认表示收到读SDA口状态 */
      _nop_(); _nop_(); _nop_(); _nop_();
      SCL=0;
      _nop_();
      SDA=1;
      }


      /* * * * * * * * * 不对IIC总线产生应答 * * * * */
      void NoAck(void)
      { SDA=1;
      SCL=1;
      _nop_(); _nop_(); _nop_(); _nop_();
      SCL=0;
      }


      /* * * * * * * * * 向IIC总线写数据 * * * * */
      void Send(unsigned char sendbyte)
      { unsigned char data j=8;
      for(;j>0;j--)
      { SCL=0;
      sendbyte <<= 1; /* 使CY=sendbyte^7; */
      SDA=CY; /* CY 进位标志位 */
      SCL=1;
      }
      SCL=0;
      }


      /* * * * * * * * * 从IIC总线上读数据子程序 * * * * */
      unsigned char Receive(void)
      { register receivebyte,i=8;
      SCL=0;
      while(i--)
      { SCL=1;
      receivebyte = (receivebyte <<1 ) | SDA;
      SCL=0;
      }
      return(receivebyte);
      }


      /* * * * * * * * 一个简单延时程序 * * * * * * * * * * * * */
      void Delay(unsigned char DelayCount)
      { while(DelayCount--);
      }


      /* ----- AT24C01~AT24C256 的读写程序 ------ */


      void main()
      { unsigned char Control,*p1,*p2;
      unsigned char Length;
      unsigned int addr ; // 24Cxx片内地址  
      p1=buf1;p2=buf2;
      addr=0; // 片内地址 AT24C256为0~32767  
      Length=8; // 读写长度  
      enumer=AT24256; // 读写AT24C256
      Control=0xa0; // 写操作
      RW24xx(p1,Length,addr,Control,enumer); // 写
      Control=0xa1; // 读操作  
      RW24xx(p2,Length,addr,Control,enumer);// 读  
      }
      /* 以上为AT24C01~AT24C256的读写程序,各人可根据自己的需要应用。
      在buf1中填入需要写入的内容,buf2的大小可根据需要定义。
      addr可根据使用的芯片选择,可从任何位置读写,只要在该芯片的范围内。
      enumer=ATxxx,根据使用的芯片赋值。各函数中的形式参数不需改变。
      本程序只要在调用的程序中定义实际参数即可,上述各子程序不必改动。*/

出0入0汤圆

发表于 2009-5-21 20:19:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-5-22 11:13:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-5 11:36:27 | 显示全部楼层
写入的数据是112233445566112233445566,读出的数据是112233445566FE1122334455,何故?

出0入0汤圆

发表于 2009-7-8 15:59:00 | 显示全部楼层
谢谢楼主分享!

出0入0汤圆

发表于 2009-7-8 16:59:50 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2010-1-5 16:08:01 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-1-5 16:21:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-30 16:09:08 | 显示全部楼层
好东西,支持!
楼主好伟大!
终于找到页写的程序了

出0入0汤圆

发表于 2010-11-3 12:58:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-3 20:10:43 | 显示全部楼层
回复【楼主位】wogudan
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2011-11-30 19:53:42 | 显示全部楼层
回复【楼主位】wogudan
-----------------------------------------------------------------------

好,试试你的程序,但是程序的可读性好像不是太好,看起来特别辛苦

出0入0汤圆

发表于 2016-9-17 11:25:54 | 显示全部楼层
感谢楼主!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-8 23:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表