AT24C16 2K字节(存储内存) = 128(页面数)* 16 (每页的字节数) = 2^11 (寻址地址位数 11位)。
AT24C16有128(2^7=128)页只需要7位地址,分为高3位和低4位,高3位在设备地址中,低4位在字地址中。
设备地址:1010+页地址高3位+读写方向(1:读 0:写)
字地址:页地址高4位+4位页内偏移地址
例如读写地址:1864 ,首先计算该地址是多少页的多少个字节,1864/16=116(0x74)页,1864%16=8(0x08),即116页的第8个字节
其中页地址0x74=0 1 1 1 0 1 0 0,最高位忽略,剩下分为D6、D5、D4(高3位)和D3~D0(低4位)两个部分 。
可以计算出 设备地址和字地址:
设备地址:1010 111 0/1 (AT24C16设备地址高4位固定为1010)
字地址:0100 1000(高4位是页地址低4位,低4位是页内偏移地址,即0x08)
AT24C16 BYTE WRITE,比较简单,我们看看多页的写入
PAGE WRITE
查看手册
简单翻译
16K EEPROM 能够进行16字节的页写入
页写的初始化和字节写入是同样的,但是在第一个数据被写入后,微控制器不需要发送停止信号。相反,EEPROM收到第一个数据之后,进行应答,微控制器可以传送剩下的15个字节, EEPROM在接收到每个数据字后,将以一个0响应。微控制器必须用一个停止条件终止页面写入序列。
当内部自动递增地址到达页面边界时,后面的字节被放置在同一页的开头。如果超过16个数据被传输到EEPROM,数据字地址将“滚动”,以前的数据将被覆盖。
上图是一页写入过程,多页写入时,首先检查写入总数据字节数是否大于一页,大于一页,就进行跨页处理,上面手册,提到过,如果超过16个数据被传输到EEPROM,数据字地址将“滚动”,以前的数据将被覆盖,为了防止覆盖前面写入,地址要增加。
先看代码
void testPage(){
uchar pDataWrite[LEN];//用于写入的数组
for(num = 0; num < LEN; num++){
pDataWrite[num] = num+1;
}
at24xxWrite(0x64, pDataWrite, LEN);//从地址 开始写入多个数据
}
//首先检查写入总数据字节数是否大于一页
void at24xxWrite(uint16_t addr, const char* pBuff, uint16_t size)
{
uchar writeLen, pageOffset;
while(size > 0){
// AT24C16有128(2^7=128)页,需要7位地址,分为高3位和低4位, 页低4位和页内偏移地址(4位),组成word address 8位
// 如读写地址:1864 ,1864/16=116(0x74)页,1864%16=8(0x08),即116页的第8个字节
// 0x74=0 1 1 1 0 1 0 0, 最高位忽略,分为D6、D5、D4(高3位)和D3~D0(低4位)两个部分
// 设备地址:1010 111 0/1, word address: 0100 1000(页低4位 和 页内偏移地址(4位))
// addr & (PAGE_SIZE - 1) 取出低4位 页内偏移地址
pageOffset = PAGE_SIZE - (addr & (PAGE_SIZE - 1));
writeLen = size > pageOffset ? pageOffset : size;
page_write(addr, pBuff, writeLen);
size = size - writeLen;
if(size > 0){
pBuff = pBuff + writeLen;
addr = addr + writeLen;
}
}
}
at24xxWrite(0x64, pDataWrite, LEN); 定义 LEN = 18,一次写入18个字节(写入数据1~18),超过一页
看下图表明数据写入成功
I2C Debugger仪器,在仿真调试期中,该仪器可以显示I2C数据传送时间、S(START状态)、Sr(ReStart状态)、A(Ask响应)、N (No ask状态)、P(Stop状态)、数据(同时显示数据的16进制值和每位的值)。通过查看I2C Debugger窗口的显示,可以知道I2C总线上发送和接受的数据是否正确。
proteus I2C Debugger 查看 写入过程
S:start()
A0:write_byte(slaveAddr);发送器件写地址 0xa0:1010 0000
A:host_wait_ask()
64:write_byte(newAddr);发送地址(0x64)
A:host_wait_ask()
01:write_byte(*pData);发送数据1
A:host_wait_ask()
...依次发送0x2...0xC(12)共12位数据
P:stop()
从地址 0x64,开始,发送0x1~0xC(1~12)共12位数据,为什么只发送了12位,而不是16位?
前面,有提到过,word address高4位是页地址,低4位是页内偏移地址,而0x64 = 0110 0100
高4位0110页地址(第0x110=6页), 低4位0100页内偏移地址,从第4个字节开始写入,总共可写入(16-4=12)个字节
第6页写完后,要跨到下一页,0x64 + 0xC(12) = 0x70
S:start()
A0:write_byte(slaveAddr);发送器件写地址 0xa0:1010 0000
A:host_wait_ask()
70:write_byte(newAddr);发送地址( 0x70)
A:host_wait_ask()
0D:write_byte(*pData);发送数据13(0xD)
A:host_wait_ask()
...依次发送0xE...0x12(18)后面共5位数据
P:stop()
后续,试试 读操作:当前地址读取、随机地址读取、顺序连续读取。然后LCD液晶显示结果。
源程序和仿真下载