纠错

如图,代码中的500us全部改成2us,在写之后加5ms延时就可以了!!!

0. 序

从stm32上移植下来的代码,改了间隔时间,证明本代码可移植性很强。

注意自己的单片机型号,修改间隔时间以正确读写。该代码,适用于AT24C64所有场合,STM32、51都适用。

51型号 :STC15W4K32S4 

存储器:AT24C64 (好像看到说,24c64和24c02不一样,02地址是8位,64地址是16位,所以64不能直接用02的代码)

不要设置开漏模式,使用默认的准双向口,代码内容应该是有了读后写操作,所以设置开漏反而无法读写,我在这里卡了2小时。

1. 注意

延时,写最少需要800us,其他延时最少需要500us,太短会导致读写不全,读错误结果是FF,写错误就是没写进去

2. 代码

IIC.c

#include <IIC.H>
#include <Delay.h>sbit SCL=P5^5;
sbit SDA=P5^4;void EEP_I2c_Start(void)
{SDA=1;DelayUs(500);SCL=1;DelayUs(500);SDA=0;DelayUs(500);  // hold time start condition (t_HD;STA)SCL=0;DelayUs(500);
}void EEP_I2c_Stop(void)
{SCL=0;DelayUs(500);SDA=0;DelayUs(500);SCL=1;DelayUs(500);  // hold time start condition (t_HD;STA)SDA=1;DelayUs(500);
}u8 IIC_hostWait_Ack(void)//ack creat from slave
{u8 ucErrTime=0;SDA=1;DelayUs(500);SCL=1;DelayUs(500);while(SDA==1){ucErrTime++;if(ucErrTime>250){EEP_I2c_Stop();return 1;}}SCL=0;return 0;
}/产生ACK应答//4
void IIC_hostAck(void)
{SCL=0;SDA=0;DelayUs(500);SCL=1;DelayUs(500);SCL=0;
}
/不产生ACK应答   //5
void IIC_hostNAck(void)
{SCL=0;SDA=1;DelayUs(500);SCL=1;DelayUs(500);SCL=0;
}
/------------6
void EEP_I2c_WriteByte(u8 txByte)
{u8    count;SCL=0;for(count = 0; count <8; count ++)// shift bit for masking (8 times){if((txByte<<count)&0x80)SDA=1; // masking txByte, write bit to SDA-LineelseSDA=0;DelayUs(800);     // data set-up time (t_SU;DAT)SCL=1;    // generate clock pulse on SCLDelayUs(800);   // SCL high time (t_HIGH)SCL=0;DelayUs(800);}//check slave ack after send write
}/------------7
u8 EEP_I2c_ReadByte( u8 ack)
{u8 rxByte;u8 count;rxByte = 0x00;// release SDA-linefor(count = 0; count < 8; count++)    // shift bit for masking (8 times){SCL=0;                           // start clock on SCL-lineDelayUs(500);SCL=1;// SCL high time (t_HIGH)rxByte<<=1;if(SDA==1)rxByte |= 1;             // read bitDelayUs(500);                    // data hold time(t_HD;DAT)}//SDA=1;            // release SDA-lineif (!ack)IIC_hostNAck();//发送nACKelseIIC_hostAck(); //发送ACKDelayUs(500);return rxByte;         // return with no error
}/*-------------------------------AT24c64---------------------------------------------*/u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{u8 temp=0;EEP_I2c_Start();if(EE_TYPE>AT24C16){EEP_I2c_WriteByte(0XA0);    //发送写命令IIC_hostWait_Ack();EEP_I2c_WriteByte(ReadAddr>>8);//发送高地址IIC_hostWait_Ack();}else{EEP_I2c_WriteByte(0XA0+((ReadAddr/63999)<<1));   //发送器件地址0XA0,写数据IIC_hostWait_Ack();}EEP_I2c_WriteByte(ReadAddr%63999);   //发送低地址IIC_hostWait_Ack();EEP_I2c_Start();EEP_I2c_WriteByte(0XA1);           //进入接收模式IIC_hostWait_Ack();temp=EEP_I2c_ReadByte(0);EEP_I2c_Stop();//产生一个停止条件DelayUs(500);return temp;
}
/       9
//AT24CXX  Byte Write
//WriteAddr  :写入数据的目的地址
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{u8 i;EEP_I2c_Start();if(EE_TYPE>AT24C16){EEP_I2c_WriteByte(0XA0);       //发送写命令IIC_hostWait_Ack();EEP_I2c_WriteByte(WriteAddr>>8);//发送高地址}else{EEP_I2c_WriteByte(0XA0+((WriteAddr/63999)<<1));   //发送器件地址0XA0,写数据}IIC_hostWait_Ack();EEP_I2c_WriteByte(WriteAddr%63999);   //发送低地址IIC_hostWait_Ack();EEP_I2c_WriteByte(DataToWrite);     //发送字节IIC_hostWait_Ack();EEP_I2c_Stop();//产生一个停止条件DelayUs(500);}
//在AT24CXX里面的指定地址开始写入长度为Len的word or double word
//write 16bit or 32 bit data
//WriteAddr  :开始写入的地址
//DataToWrite:
//Len        :len =2 or len=4  ,first high then tow as habit
//
void AT24CXX_WriteLenByte(  u16 WriteAddr,u32 DataToWrite,u8 Len)
{u8 t;for(t=0; t<Len; t++){//AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*(Len-t-1)))&0xff);}
}//在AT24CXX里面的指定地址开始读出长度为Len word or double word
//该函数用于读出16bit或者32bit的数据.
//ReadAddr   :开始读出的地址
//返回值     :数据
//Len        :要读出数据的长度2,4
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{u8 t;u32 temp=0;for(t=0; t<Len; t++){temp<<=8;//temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);temp+=AT24CXX_ReadOneByte(ReadAddr+t);}return temp;
}//在AT24CXX里面的指定地址开始读出指定个数的数据
//ReadAddr :24c02 0~255  ,24c16 63999*32
//pBuffer  :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,char  *pBuffer,u16 NumToRead)
{while(NumToRead){*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);NumToRead--;}
}
//在AT24CXX里面的指定地址开始写入指定个数的数据
//WriteAddr :24c02 0~255
//pBuffer   :数据数组首地址
//NumToWrite:要写入数据的个数
void AT24CXX_Write(u16 WriteAddr,char *pBuffer,u16 NumToWrite)
{while(NumToWrite--){AT24CXX_WriteOneByte(WriteAddr,*pBuffer);WriteAddr++;pBuffer++;}
}

IIC.h

#ifndef IIC_H
#define IIC_H
#include <STC15.H>#define AT24C01     127
#define AT24C02     255
#define AT24C04     511
#define AT24C08     1023
#define AT24C16     2047
#define AT24C32     4095
#define AT24C64     8191
#define AT24C128    16383
#define AT24C256    32767 #define EE_TYPE  AT24C64void EEP_I2c_Start(void);
void EEP_I2c_Stop(void);
u8 IIC_hostWait_Ack(void);
void IIC_hostAck(void);
void IIC_hostNAck(void);
void EEP_I2c_WriteByte(u8 txByte);
u8 EEP_I2c_ReadByte( u8 ack);/*-------------------------------AT24c64---------------------------------------------*/
u8 AT24CXX_ReadOneByte(u16 ReadAddr);
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);
void AT24CXX_WriteLenByte(  u16 WriteAddr,u32 DataToWrite,u8 Len);
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len);
void AT24CXX_Read(u16 ReadAddr,char  *pBuffer,u16 NumToRead);
void AT24CXX_Write(u16 WriteAddr,char *pBuffer,u16 NumToWrite);#endif

Delay.h

#include <Delay.h>//*==============================================|=====================*
//*函数原型:
//*功能描述:    微妙级延时函数
//*说    明:  晶振11.0592Mhz 12T 函数体中单独放_nop_()表示1us
//*测    试:  已测试,方规 逻辑分析仪测试长度如下:
//  DelayUs(3);             //延时2.5us
//  DelayUs(5);             //延时3.5us
//  DelayUs(10);            //延时4.5us
//  DelayUs(30);            //延时53us
//  DelayUs(100);           //延时167us
//  DelayUs(10);
//  DelayUs(10);
//  DelayUs(10);
//  DelayUs(10);
//  DelayUs(10);            //延时21us
//  DelayUs(500);           //延时819us
//  DelayMs(500);           //延时491
//*结    论:  此函数做不到精确延时,以上数据供以后参考,对时序要求严格的驱动,
//*             一定要使用仪器来测量,此延时跟晶振和指令周期都有关系
//*==============================================|=====================*
void DelayUs(unsigned int us)       //1000 -> 1.7ms
{unsigned int j;        if(us==3){_nop_();_nop_();_nop_();return;}    if(us==5){_nop_();_nop_();_nop_();_nop_();_nop_();return;}if(us==10){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();return;}for(j=0;j<us;j++){_nop_();}
}//*==============================================|=====================*
//*函数原型:
//*功能描述:    毫秒级延时函数
//*说    明:  晶振11.0592Mhz 12T 1000表示1秒延时
//*测    试:  已测试,方规
//*==============================================|=====================*
void DelayMs(unsigned int ms)       //1000 -> 1秒
{unsigned int i=0;for(i=0;i<ms;i++){DelayUs(600);}
}

51单片机——读写AT24c64相关推荐

  1. 24c512 c语言程序,24C32~24C512的51单片机读写程序

    24C32~24C512的51单片机读写程序 来源:-- 作者:-- 浏览:3875 时间:2016-08-10 14:18 标签: 摘要: AT89S52 晶振频率为11.0592MHz 指令周期: ...

  2. 51单片机读写内部EEPROM详解

    文档共包含三个程序. 第一个程序最简单易懂,看懂了基本就会读写51单片机内部EEPROM了. 第二个程序和第一个读写EEPROM原理差不多,包含有LCD1602操作方法,有写字符串的方法. 第三个程序 ...

  3. DS3231_STC15W型51单片机读写日期+温度,模拟IIC

    //-------STC12C5A60S2--外置晶振11.0592M-2023/1/16/CSDN短枪王博客 //ModifyTime():修改日期函数,上电初始化时写一次即可,电池会保持写入的参数 ...

  4. c语言AT源码,51单片机读写AT24C02源代码(详细注释)

    在P1口上接八个led灯,结果就显示在这八个灯上面.AT24C02的接线方式见程序的顶部的定义.以下是源代码: #include //包含头文件 typedef unsigned char uchar ...

  5. 51单片机读写WTV语音芯片

    原帖地址:http://em78447.blog.163.com/blog/static/9986005120098541118433/ 步骤: 第一步:用语音软件mp3小助手将普通.mp3文件转换成 ...

  6. 【51单片机快速入门指南】4.1: I2C 与 AT24C02 (EEPROM) 的跨页连续读写

    目录 硬知识 AT24Cxx 介绍 引脚排列 引脚说明 存储结构 器件寻址 器件操作 待机模式 存储复位 写操作 字节写 页写 应答查询 读操作 当前地址读 随机读 顺序读 示例程序 24C02.c ...

  7. SD卡SPI读写模式,基于51单片机的讲解

    经过验证测试,sd卡使用的spi模式为模式3(mode3),即CPOL和CPHA均为1,时钟线高电平空闲,第二个边沿(上升沿)进行采样. 下面为51单片机软spi读写一个字节时序(模式3)的代码示例, ...

  8. 51单片机对SPI总线上挂接多个25AA040的读写操作+Proteus仿真

    51单片机对SPI总线上挂接多个X5045的读写操作+Proteus仿真 Proteus仿真图 实例代码 //对SPI总线上挂接多个25AA040的读写操作 #include<reg51.h&g ...

  9. NFC之基于51单片机rc522的读写

    NFC之基于51单片机rc522的读写 改程序,端口定义 上位机修改com口

最新文章

  1. 2021年春季学期-信号与系统-第三次作业参考答案
  2. JS 对象(Object)和字符串(String)互转
  3. 关于HotSpot VM以及Java语言的动态编译 你可能想知道这些
  4. ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由
  5. leetcode-231-Power of Two
  6. Zabbix主机处于check_ping_icmpping状态问题解决
  7. 如何通俗易懂地理解基于模型的强化学习?
  8. java oracle时间格式转换_oracle时间格式转换问题 ORA-01810: format code appears twice--转...
  9. 【BZOJ3916】friends(hash+分情况讨论)
  10. MQTT测试工具推荐
  11. 使用python代码调用三汇语音卡硬件拨打电话
  12. The connection to adb is down, and a severe error has occured.问题解决
  13. P2597 [ZJOI2012]灾难(支配树)
  14. 元宇宙NFT最近最火的项目,该如何选择平台呢
  15. AngularJS 事件绑定(ng-click)
  16. 以太坊bloom和logs及代码解析
  17. 2015 计蒜之道 初赛 第一场 搜狗输入法的分词算法
  18. 2022年西藏最新八大员之(安全员)模拟试题题库及答案
  19. Collection集合接口及其子接口、实现类
  20. 禁止ios字体调整大小

热门文章

  1. List.isEmpty()与CollectionUtils.isEmpty的区别
  2. 电路模型和电路定律(Ⅲ)
  3. Unity_UIWidgets新手入门
  4. iTunes制作铃声------将制作铃声导入到手机中
  5. VVC帧间预测(十)帧间帧内联合预测CIIP
  6. java libusb_libusb中断传输
  7. python斐波拉契数列(Fibonacci)
  8. HTTPS 前端劫持
  9. 行人reid ,多个开源地址数据变成 market1501格式合并,附代码,数据地址
  10. element-ui 阻止冒泡事件