51单片机——读写AT24c64
纠错
如图,代码中的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相关推荐
- 24c512 c语言程序,24C32~24C512的51单片机读写程序
24C32~24C512的51单片机读写程序 来源:-- 作者:-- 浏览:3875 时间:2016-08-10 14:18 标签: 摘要: AT89S52 晶振频率为11.0592MHz 指令周期: ...
- 51单片机读写内部EEPROM详解
文档共包含三个程序. 第一个程序最简单易懂,看懂了基本就会读写51单片机内部EEPROM了. 第二个程序和第一个读写EEPROM原理差不多,包含有LCD1602操作方法,有写字符串的方法. 第三个程序 ...
- DS3231_STC15W型51单片机读写日期+温度,模拟IIC
//-------STC12C5A60S2--外置晶振11.0592M-2023/1/16/CSDN短枪王博客 //ModifyTime():修改日期函数,上电初始化时写一次即可,电池会保持写入的参数 ...
- c语言AT源码,51单片机读写AT24C02源代码(详细注释)
在P1口上接八个led灯,结果就显示在这八个灯上面.AT24C02的接线方式见程序的顶部的定义.以下是源代码: #include //包含头文件 typedef unsigned char uchar ...
- 51单片机读写WTV语音芯片
原帖地址:http://em78447.blog.163.com/blog/static/9986005120098541118433/ 步骤: 第一步:用语音软件mp3小助手将普通.mp3文件转换成 ...
- 【51单片机快速入门指南】4.1: I2C 与 AT24C02 (EEPROM) 的跨页连续读写
目录 硬知识 AT24Cxx 介绍 引脚排列 引脚说明 存储结构 器件寻址 器件操作 待机模式 存储复位 写操作 字节写 页写 应答查询 读操作 当前地址读 随机读 顺序读 示例程序 24C02.c ...
- SD卡SPI读写模式,基于51单片机的讲解
经过验证测试,sd卡使用的spi模式为模式3(mode3),即CPOL和CPHA均为1,时钟线高电平空闲,第二个边沿(上升沿)进行采样. 下面为51单片机软spi读写一个字节时序(模式3)的代码示例, ...
- 51单片机对SPI总线上挂接多个25AA040的读写操作+Proteus仿真
51单片机对SPI总线上挂接多个X5045的读写操作+Proteus仿真 Proteus仿真图 实例代码 //对SPI总线上挂接多个25AA040的读写操作 #include<reg51.h&g ...
- NFC之基于51单片机rc522的读写
NFC之基于51单片机rc522的读写 改程序,端口定义 上位机修改com口
最新文章
- 2021年春季学期-信号与系统-第三次作业参考答案
- JS 对象(Object)和字符串(String)互转
- 关于HotSpot VM以及Java语言的动态编译 你可能想知道这些
- ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由
- leetcode-231-Power of Two
- Zabbix主机处于check_ping_icmpping状态问题解决
- 如何通俗易懂地理解基于模型的强化学习?
- java oracle时间格式转换_oracle时间格式转换问题 ORA-01810: format code appears twice--转...
- 【BZOJ3916】friends(hash+分情况讨论)
- MQTT测试工具推荐
- 使用python代码调用三汇语音卡硬件拨打电话
- The connection to adb is down, and a severe error has occured.问题解决
- P2597 [ZJOI2012]灾难(支配树)
- 元宇宙NFT最近最火的项目,该如何选择平台呢
- AngularJS 事件绑定(ng-click)
- 以太坊bloom和logs及代码解析
- 2015 计蒜之道 初赛 第一场 搜狗输入法的分词算法
- 2022年西藏最新八大员之(安全员)模拟试题题库及答案
- Collection集合接口及其子接口、实现类
- 禁止ios字体调整大小