欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > 关于I2C读写AT24C04存储芯片的一些浅显认知?

关于I2C读写AT24C04存储芯片的一些浅显认知?

2025/5/3 16:20:01 来源:https://blog.csdn.net/xingyuncao520025/article/details/144028922  浏览:    关键词:关于I2C读写AT24C04存储芯片的一些浅显认知?

这两天一直在尝试往AT24C04芯片里面存储数据,试了几天了,发现能查找的相关资料还是很少的,有些东西搞不明白,说是可以看数据手册,但是我的英文视频不要太辣鸡了。翻译软件又翻译的不准确,所以只能自己摸索着试验了。所以这个东西很费时间啊?最终实验的结果是,我只能往前255个字节内写入数据,并能够保存下来,剩下的那257个字节要怎么存储呢?我一直没有什么头绪,特此我把我的实验结果分享出来!要是能够遇到大佬能够为我答疑解惑,我在这里感激不尽了!如果没有人替我解惑,就当我分享出来给大家学习吧!毕竟这个东西还是很稀缺的资源,国内应该有不少小伙伴会的,但是都没有分享出来。我来分享吧!也许我说的太过了,主要是我这几天视频和网页确实是没有少看,但是没有找到丁点线索,基本上千篇一律,都是互相抄袭的。

好了,我先把我写的I2C的底层驱动贴出来吧:

//我的I2C.c文件
#include "MyI2C.h"void MyI2C_W_SCL(uint8_t value)
{GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)value);Delay_us(10);
}void MyI2C_W_SDA(uint8_t value)
{GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)value);Delay_us(10);
}uint8_t MyI2C_R_SDA(void)
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10);Delay_us(10);return BitValue;
}void MyI2C_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}void MyI2C_Start(void)
{MyI2C_W_SDA(1);MyI2C_W_SCL(1);MyI2C_W_SDA(0);MyI2C_W_SCL(0);
}void MyI2C_Stop(void)
{MyI2C_W_SDA(0);MyI2C_W_SCL(1);MyI2C_W_SDA(1);
}void MyI2C_SendByte(uint8_t Byte)
{uint8_t i;for(i=0; i<8; i++){MyI2C_W_SDA(Byte & (0x80>>i));MyI2C_W_SCL(1);MyI2C_W_SCL(0);}
}uint8_t MyI2C_ReceiveByte(void)
{uint8_t i, Byte=0x00;MyI2C_W_SDA(1);for(i=0; i<8; i++){MyI2C_W_SCL(1);if(MyI2C_R_SDA() == 1){Byte |= (0x80>>i);}MyI2C_W_SCL(0);}return Byte;
}void MyI2C_SendACK(uint8_t ACK)
{MyI2C_W_SDA(ACK);MyI2C_W_SCL(1);MyI2C_W_SCL(0);}uint8_t MyI2C_ReceiveACK(void)
{uint8_t ACK;MyI2C_W_SDA(1);MyI2C_W_SCL(1);ACK = MyI2C_R_SDA();MyI2C_W_SCL(0);return ACK;
}// 从机地址扫描程序(传入从机地址的变量)  最后读取变量就是从机地址
void MyI2C_Scan(uint8_t *addr)
{uint16_t i;for(i=0;i<256;i++){MyI2C_Start();MyI2C_SendByte(i);uint8_t ACK = MyI2C_ReceiveACK();if(ACK == 0){*addr = i;}}
}

下面是:我的I2C.h文件

#ifndef __MYI2C_H
#define __MYI2C_H#include "stm32f10x.h"                  // Device header
#include "Delay.h"void MyI2C_Init(void);void MyI2C_Start(void);void MyI2C_Stop(void);void MyI2C_SendByte(uint8_t Byte);uint8_t MyI2C_ReceiveByte(void);void MyI2C_SendACK(uint8_t ACK);uint8_t MyI2C_ReceiveACK(void);// 从机地址扫描程序(传入从机地址的变量)  最后读取变量就是从机地址
void MyI2C_Scan(uint8_t *addr);#endif

下面是AT24C256.c文件(刚开始时是手上有C256的芯片,试了一天后发现自己搞不定,就买了24C04芯片来实验,结果也没有搞定,好惭愧啊!所以文件名字也没有改!)

#include "AT24C256.h"void AT_24C256_Init(void)
{MyI2C_Init();
}// 我的I2C写单字节函数(16位地址, 要写入的字节)
void AT24C256_WriteByte(uint16_t addr, uint8_t data)
{MyI2C_Start();               //I2C开始信号MyI2C_SendByte(0xA0);              //I2C发送从机地址uint8_t ACK1 = MyI2C_ReceiveACK();  //接收应答位MyI2C_SendByte(addr>>8);           //I2C发送地址的高8位uint8_t ACK2 = MyI2C_ReceiveACK();  //接收应答位MyI2C_SendByte(addr % 256);        //I2C发送地址的低8位uint8_t ACK3 = MyI2C_ReceiveACK();  //接收应答位MyI2C_SendByte(data);               //I2C发送要写入的数据MyI2C_ReceiveACK();                //I2C接收应答位Delay_ms(20);	                   //延时20毫秒MyI2C_Stop();                   //I2C停止信号Delay_ms(20);                   //延时20毫秒
}// 我的I2C写函数(16位地址, 要写入数组的首地址)
void AT24C256_WriteReg(uint16_t addr, uint8_t *data)
{uint8_t i;MyI2C_Start();MyI2C_SendByte(0xA0);uint8_t ACK1 = MyI2C_ReceiveACK();MyI2C_SendByte(addr>>8);MyI2C_ReceiveACK();MyI2C_SendByte(addr % 256);uint8_t ACK3 = MyI2C_ReceiveACK();for(i=0; i<17; i++){MyI2C_SendByte(*data);uint8_t ACK4 = MyI2C_ReceiveACK();data++;}MyI2C_Stop();Delay_ms(5);
}// 我的I2C读函数(16位的地址)
uint8_t AT24C256_ReadByte(uint16_t addr)
{MyI2C_Start();MyI2C_SendByte(0xA0);MyI2C_ReceiveACK();MyI2C_SendByte(addr>>8);MyI2C_ReceiveACK();MyI2C_SendByte(addr % 256);MyI2C_ReceiveACK();MyI2C_Start();MyI2C_SendByte(0xA1);MyI2C_ReceiveACK();uint8_t data = MyI2C_ReceiveByte();MyI2C_SendACK(1);MyI2C_Stop();return data;
}// 我的I2C读函数(16位的地址, 接收数据的数组首地址,要接收的字节个数)
void AT24C256_ReadReg(uint16_t addr, uint8_t *data, uint16_t len)
{uint8_t i;MyI2C_Start();MyI2C_SendByte(0xA0);uint8_t ACK1 = MyI2C_ReceiveACK();MyI2C_SendByte(addr>>8);uint8_t ACK2 = MyI2C_ReceiveACK();MyI2C_SendByte(addr % 256);uint8_t ACK3 = MyI2C_ReceiveACK();MyI2C_Start();MyI2C_SendByte(0xA1);uint8_t ACK4 = MyI2C_ReceiveACK();for(i=0; i<len; i++){*data = MyI2C_ReceiveByte();if(i==(len-1)){MyI2C_SendACK(1);}else{MyI2C_SendACK(0);}data++;}MyI2C_Stop();}

下面是AT24C256.h文件:

#ifndef __AT24C256_H
#define __AT24C256_H#include "stm32f10x.h"                  // Device header
#include "MyI2C.h"
#include "OLED.h"void AT_24C256_Init(void);// 我的I2C写单字节函数(16位地址, 要写入的字节)
void AT24C256_WriteByte(uint16_t addr, uint8_t data);// 我的I2C写函数(16位地址, 要写入的值)
void AT24C256_WriteReg(uint16_t addr, uint8_t *data);// 我的I2C读函数(16位的地址)
uint8_t AT24C256_ReadByte(uint16_t addr);// 我的I2C读函数(16位的地址, 接收数据的数组首地址,要接收的字节个数)
void AT24C256_ReadReg(uint16_t addr, uint8_t *data, uint16_t len);#endif

最后就是主函数中调用的文件了。

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Delay.h"
#include "AT24C256.h"
#include "MyI2C.h"
#include "Serial.h"
uint8_t a[255];uint8_t b[512];void DX(uint16_t i,uint8_t d)
{//AT24C256_WriteByte((uint16_t)i,d);  //向传入的i地址写入数据duint8_t data = AT24C256_ReadByte((uint16_t)i);//读取i地址下的数据赋值给dataOLED_ShowHexNum(3,1,data,2);    //OLED显示datab[i]=data;                     //数组b中添加data
}int main(void)
{OLED_Init();Serial_Init();AT_24C256_Init();uint16_t i;for(i=0;i<255; i++){a[i]=0x11;//DX(i,i);    //调用DX函数传入地址i和要写入的值i}//AT24C256_WriteReg(0x0000,a);   //  地址0x0000:前15个地址被设置值AT24C256_WriteReg(0x1000,a);     //地址0x1000:从第16个地址到第31个地址被设置  共16个字节//AT24C256_WriteReg(0x2000,a);      // 地址0x2000:从第32个地址到第47个地址被设置  共16个字节//AT24C256_WriteReg(0x3000,a);      // 地址0x3000:继续设置 共16个字节//AT24C256_WriteReg(0x4000,a); //AT24C256_WriteReg(0x5000,a);//AT24C256_WriteReg(0x6000,a);//AT24C256_WriteReg(0x7000,a);//AT24C256_WriteReg(0x8000,a);//AT24C256_WriteReg(0x9000,a);//AT24C256_WriteReg(0xa000,a);//AT24C256_WriteReg(0xb000,a);//AT24C256_WriteReg(0xc000,a);//AT24C256_WriteReg(0xd000,a);//AT24C256_WriteReg(0xe000,a);//AT24C256_WriteReg(0xf000,a);  // 地址0xf000:继续设置 共16个字节AT24C256_ReadReg(0x0000,b,255); //24C256读数据时可以一次性读多个字节,(参数:从哪个地址开始读,接收数据数组的地址,接收字节的个数)AT24C256_ReadReg(0x1000,b+255,255); Serial_SendArray(b,512);  //串口发送数组b
}

如果哪个小伙伴看到了,能够在我的基础上又有了新的发现,望能告知,我在此感激不尽啊!

我找了好久也没有找到过AT24C04的页起始地址,英文文档我又看不懂,只能一个一个的试了。结果还是没有搞定。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词