AT24C16 读写

at24c16 有8块 256字节组成,共2K字节16K bit

在这里插入图片描述
在这里插入图片描述
I2C开始信号后,第一个字节为器件地址,由1010+3位块地址+1位读写标志组成, 3位块地址刚好可以表示 8个块, 所以一次写完256字节,换到下一下块的时候,要重新更改器件地址
在这里插入图片描述
共有三种写入模式:
字节写入模式: MODE脚可接高电平或低电平

多字节模式:MODE接高电平,一次最多写8个字节,24c16收到数据后,地址低4bit递增,当地址超出边界时,会回滚到本页的开头,相当于低4bit溢出了,而且写入时间加倍到20ms。

页写入模式:一次最多写入16字节。主机每发送一个字节,24c16收到确认,内部地址递增(仅限低4bit,所以1次可写16字节)。
在这里插入图片描述
写保护功能:
8个块(每个块256byte)中,高四个块是可以写保护的,防止误改。
从边界地址—到顶部0x07FF之间被保护,边界地址由PB1 PB0两个引脚电平和0x07FF这个字节确定。
PB0 PB1选择四个块,地址0x07FF里面的内容的高4bit选择行号,一个块里有16行,每行16字节。低4bit 必须是0。所以边界地址是以行为单位的。

写保护的顺序:
1、将要保护的数据写入内存的顶部,最多但不包括location7FFh
2、硬件选择PB0 PB1 电平
3、通过在地址指针(位置7FFh的4个MSB)中写入正确的底部边界地址并将位b2(保护标志)设置为“0”来设置保护。

注意:位置7FFh的低4bit必须写入0,然后当PRE引脚接高电平时,保护将起作用。

备注:只有当PRE为高电平,并且7FFH存储的地址的bit2位为0,保护才起作用。其它情况,7FFH可以作为普通存储单元。


    /*****************************************************************************
    函数名称 : readAT24C16
    功能描述 :从at24c16读取数据
    输入参数 : 要读的开始地址,读出来的数据存放到数组的指针,数据长度
    返回参数 : hal_ok/hal_error
    使用说明 : 无
    *****************************************************************************/
HAL_StatusTypeDef readAT24C16(uint16_t addr,uint8_t *data, uint16_t len)
{
	uint8_t rNum=0;
	uint16_t lenLeft=len;
	uint8_t deviceId;
	uint8_t *p=data;

	/*is the address overfolw*/
	if(addr+len>E2PROM_SIZE)   return HAL_ERROR;

	/*calculate the current read position to know how many word can read continully*/
	rNum=16-addr & E2PROM_PAGE_MASK;
	if(rNum == 0)  rNum=16;
	rNum = lenLeft>=rNum ? rNum : lenLeft;//剩余未读字节数如果大于rNum, 则读rNum个,如果小于rNum,则一次读完了

	/*read the data from e2prom*/
	while(lenLeft)
	{
		//这里计算页地址,当地址小于256时,右移8位会小于0,所以器件地址为基地址A1
		//如果读取的地址大于256时,右移8位则不会小于0,所以器件地址为 基地址A1 | 3位页地址
		deviceId=(addr>>8)<0 ?  E2PROM_BASE_RID : (E2PROM_BASE_RID | (uint8_t)((addr>>7)&0x0E));

		if(HAL_I2C_Mem_Read(&hi2c2,deviceId,addr&0x00FF,I2C_MEMADD_SIZE_8BIT,p,rNum, 20)!=HAL_OK)
		{
			printf("i2c read error\r\n");
			continue;
		}
		addr+=rNum;//已经读了rNum个了,所以地址后移rNum个
		lenLeft-=rNum;//剩余未读数据减少rNum个
		p+=rNum;
		rNum=lenLeft>16? 16 : lenLeft;//如果剩余大于16个,则下次再读16个,如果小于,则一次读完
	}
    	return HAL_OK;
    }

上页的函数,会调用

HAL_I2C_Mem_Read(&hi2c2,deviceId,addr&0x00FF,I2C_MEMADD_SIZE_8BIT,p,rNum, 20)!

来读取16个字节。这个函数再调用下面的函数来读取

I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)

读取的流程为:
设置CR1应答ACK-------产生START-------wait SB set -----发送器件地址-----wait ADDR set 表示地址发送完-----清除ADDR-----wait TXE set表示发送寄存器目前是空的---------发送子地址-------wait TXE set-------再次产生START------wait SB set ------发送器件地址-------wait ADDR set ------退回上一层。接收数据。

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值