关于I2C写EEPROM的几种写函数

写数据到EEPROM有四种形式:
         1.写一字节
         2.写多字节
         3.按页写
         4.快速写入

讲一下这四者的区别:

       1. 可以看到在写一字节的时候,是通过判断事件(Event)来一步步执行的,这中间不用管EEPROM有没有擦写内存,因为直到发送停止信号,EEPROM都还没有收到要擦写的数据,也就是没有EEPROM操作的机会。

        2. 而写多字节,是调用了写一字节的接口,写一字节的接口调用了,就开始轮到EEPROM干活了,而擦写数据是需要时间的,因为这个原因,写多字节就需要一个字节一个字节的去写,也就是要等待EEPROM写完一个字节,再来进行新的开始、发送EEPROM地址、内存地址、写入的数据和停止这个过程。这个等待的过程需要主机和EEPROM之间去确认。

        3.按页写又是一个逻辑,按页写其实与写字节的通讯逻辑差不多,只是在发送开始信号、EEPROM地址、内存写地址之后。开始用I2C_SendData这个函数来进行写多次的发送数据寄存器,这个逻辑不用等一个字节发完了又重复一个字节写的过程,而是一次写多个字节,这是EEPROM自己支持的通讯方式,由硬件完成,软件只需要这样执行就行。可能我们还停留在写多字节的时候,认为写完一个字节必须等待EEPROM擦写好了才能再与EERPOM通讯,确认这个EEPROM写好没有的过程还很复杂
         [1].发送开始信号
         [2].发送EEPROM地址
         [3].while循环读SR1寄存器的ADDR位,看EEPROM是否有回应主机,回应了则ADDR = 1,就是说EEPROM准备好了,没有回应就要不停的重复[1][2]两步
         [4].在从机响应了主机以后还没完,还要清除SR1的AF位,这个位是也是主机这边用来判断有没有ACK响应的,没有时,这个位被硬件置1了,而有ACK响应的时候,这个AF又不会被硬件清零,因此要手动软件清零
         [5].最后当然就是发送停止信号,结束这个确认EEPROM擦写的过程了。
        实际上EEPROM支持的就是这种,一次写入多字节的通信,如何实现的与硬件相关,我们按照通讯逻辑来就行了。有一点要记住的就是这个按页写中的一页字节数是8。
        因此在入参中定义的可写的字节数不可以大于8字节,否则造成的影响就是EEPROM因为不支持那么多位的写入而出错。

        4.最后就是快速写入,其实快速写入的逻辑中借用就是按页写入。
        举例来说,如果我要从11这个地址开始写入25个字节,很显然,上面三个只有多字节写入可能单独实现。但是效率可就很慢了,因为每写一个字节就要去等待EEPROM就绪,才能再去写。缩短EEPROM的擦写时间,当然能一页一页的写是最好的。因为写一页只需要等待一次EEPROM的擦写。
        再讲到快速写入的思路:
        还是上面提到的例子:从11地址开始写,写入25个字节。
        首先,从地址开始:地址是11,要利用页写入的快速性,我们希望能一页页的写最好,而写一页最快的当然是每页的首地址开始写 因为能写满页8个字节。因此如果地址都是0,8,16,24...这些页大小的倍数最好了。

        但是如果不是,也没关系,将要写入的地址(这里是11)距离下一个页首地址所缺少的那几个字节先用写页的方式填上,比如11距离16,需要填5个字节的数据,那就把这几个字节先写了,那么此时的地址不就是16了,已经写了5个字节,还剩下20个字节没写,那就再从16这个地址开始按页来写,可以写几个整数页就写几个整数页,这里还剩下20字节,就是还可以写2个整数页,写一页八个字节只需要等EEPROM一次,省了7次等待,这样的整数页有两页,16个字节还剩下4个字节。

        此时,地址已经走到了32了,那就是从32这个地址开始,写入4个字节。这时候仍然可以使用按页写入,只不过写入的字节数是4个,那么输入参数的NumOfByteToWrite填4就行了。

        至此,结束,可以算一下,这样比多字节写入少等待了多少次EEPROM的擦写等待。是不是这样有资格称作快速写入了呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于在嵌入式系统中使用I2C总线读EEPROM,您可以通过HAL库来实现。以下是一个基本的示例代码: 1. 首先,您需要在STM32的CubeMX工具中配置I2C外设和GPIO引脚。 2. 在代码中包含必要的头文件: ```c #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_i2c.h" ``` 3. 初始化I2C外设: ```c I2C_HandleTypeDef hi2c1; void I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; // I2C总线速度 hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { // 初始化失败处理 Error_Handler(); } } ``` 4. 实现EEPROM的操作函数: ```c #define EEPROM_ADDRESS 0xA0 // EEPROM的I2C地址 void EEPROM_Write(uint16_t address, uint8_t *data, uint16_t size) { HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, address, I2C_MEMADD_SIZE_16BIT, data, size, HAL_MAX_DELAY); } ``` 5. 实现EEPROM的读操作函数: ```c void EEPROM_Read(uint16_t address, uint8_t *data, uint16_t size) { HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS, address, I2C_MEMADD_SIZE_16BIT, data, size, HAL_MAX_DELAY); } ``` 6. 在主函数中调用这些函数进行读操作: ```c int main(void) { // 初始化硬件和外设 I2C1_Init(); // 写入数据到EEPROM uint8_t writeData[] = {0x01, 0x02, 0x03}; EEPROM_Write(0x0000, writeData, sizeof(writeData)); // 从EEPROM读取数据 uint8_t readData[3]; EEPROM_Read(0x0000, readData, sizeof(readData)); // 处理读取的数据 // 其他代码 while (1) { // 主循环 } } ``` 这是一个基本的示例代码,您可以根据您的具体需求进行修改和扩展。希望对您有帮助!如果您还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值