原创 使用GD32-I2C读写铁电存储器85RC16

2025-4-21 10:17 819 0 2 分类: MCU/ 嵌入式

85RC16是一款铁电存储器(FRAM),具有低功耗、高耐久性、快速写入等优点。通过芯片文档,可以看到对比常用的eeprom它的一些优势

与24C16的对比

  • 读写速度 :85RC16的读写速度更快,可达到与I2C总线速率相匹配的水平,没有像24C16那样的写操作延迟和页写限制,能够实现真正的随机字节写入,且不需要等待写周期完成,适合需要频繁、快速读写的应用场合。
  • 写入耐久性 :85RC16的写入耐久性更高,可承受的写入次数远超24C16,这使得其在需要频繁更新数据的应用中更具优势,使用寿命更长。
  • 功耗 :85RC16在读写操作时的功耗更低,有助于延长设备的电池寿命,对于对功耗敏感的便携式或电池供电设备来说,使用85RC16可以更有效地降低系统功耗。
  • 数据安全性 :85RC16采用铁电存储技术,数据保持性更好,能够在断电情况下更长时间地保留数据,相比24C16具有更高的数据安全性,适用于对数据可靠性要求较高的场合。
  • 存储容量 :24C16的存储容量一般为16K位,而85RC16的存储容量通常为16K字节,能够存储更多的数据。
  • 成本 :24C16的价格相对较低,成本优势明显,而85RC16由于其先进的技术和性能优势,价格相对较高。在一些对成本敏感且对性能要求不高的应用中,24C16可能更具竞争力。


对比eeprom读写时序上有一定差异,代码上需要略做调整。

#defineI2C0_S_ADDR_85RC16     0xA0

#defineI2C0_SPEED             1000000 //

 

首先是初始化过程

voidI2C0_init(void)
{
    /* enable I2C0 clock */
    rcu_periph_clock_enable(RCU_I2C0);

    i2c_software_reset_config(I2C0, I2C_SRESET_SET);
    i2c_software_reset_config(I2C0, I2C_SRESET_RESET);
    /* connect PB6 to I2C0_SCL */
    /* connect PB7 to I2C0_SDA */
    gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6|GPIO_PIN_7);
    gpio_bit_set(GPIOB, GPIO_PIN_6|GPIO_PIN_7);

    gpio_pin_remap_config(GPIO_I2C0_REMAP, DISABLE);

    /* I2C clock configure */
    i2c_clock_config(I2C0, I2C0_SPEED, I2C_DTCY_2);
/* I2C address configure */

    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C0_S_ADDR_85RC16);

    /* enable I2C0 */
    nvic_irq_enable(I2C0_EV_IRQn, 0, 1);

    i2c_enable(I2C0);
    /* enable acknowledge */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
    i2c_stop_on_bus(I2C0);

}


翻阅到读取数据逻辑

代码实现

voideeprom_buffer_read(uint8_t*p_buffer, uint16_tread_address, uint16_tnumber_of_byte)
{
    uint8_tAddrValue=0;
    AddrValue= (I2C0_S_ADDR_85RC16&0xF0);  //
    AddrValue|= ((read_address>>7) &0xE); //

    /* wait until I2C bus is idle */
    while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY))
        ;
    if (2==number_of_byte)
    {
        i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT);
    }
    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C0);
    /* wait until SBSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND))
        ;
    /* send slave address to I2C bus */
    i2c_master_addressing(I2C0, AddrValue, I2C_TRANSMITTER);
    /* wait until ADDSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
        ;
    /* clear the ADDSEND bit */
    i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
    /* wait until the transmit data buffer is empty */
    while (SET!=i2c_flag_get(I2C0, I2C_FLAG_TBE))
        ;
    /* enable I2C0*/
    i2c_enable(I2C0);

    /* send the EEPROM's internal address to write to */
    i2c_data_transmit(I2C0, (read_address&0xFF));
    /* wait until BTC bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
        ;
    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C0);
    /* wait until SBSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND))
        ;
    /* send slave address to I2C bus */
    i2c_master_addressing(I2C0, AddrValue, I2C_RECEIVER);
    if (number_of_byte<3)
    {
        /* disable acknowledge */
        i2c_ack_config(I2C0, I2C_ACK_DISABLE);
    }
    /* wait until ADDSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
        ;
    /* clear the ADDSEND bit */
    i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
    if (1==number_of_byte)
    {
        /* send a stop condition to I2C bus */
        i2c_stop_on_bus(I2C0);
    }
    /* while there is data to be read */
    while (number_of_byte)
    {
        if (3==number_of_byte)
        {
            /* wait until BTC bit is set */
            while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
                ;
            /* disable acknowledge */
            i2c_ack_config(I2C0, I2C_ACK_DISABLE);
        }
        if (2==number_of_byte)
        {
            /* wait until BTC bit is set */
            while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
                ;
            /* send a stop condition to I2C bus */
            i2c_stop_on_bus(I2C0);
        }
        /* wait until the RBNE bit is set and clear it */
        if (i2c_flag_get(I2C0, I2C_FLAG_RBNE))
        {
            /* read a byte from the EEPROM */
            *p_buffer=i2c_data_receive(I2C0);
            /* point to the next location where the byte read will be saved */
            p_buffer++;
            /* decrement the read bytes counter */
            number_of_byte--;
        }
    }
    /* wait until the stop condition is finished */
    while (I2C_CTL0(I2C0) &0x0200)
        ;
    /* enable acknowledge */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
    i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);

}


通过文档翻阅写入数据逻辑

代码实现

voideeprom_buffer_write(uint8_t*p_buffer, uint16_twrite_address, uint16_tnumber_of_byte)
{
    uint8_tAddrValue=0;
    AddrValue= (I2C0_S_ADDR_85RC16&0xF0);  //
    AddrValue|= ((write_address>>7) &0xE); //

    Eeprom_WREnable();

    /* wait until I2C bus is idle */
    while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY))
        ;
    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C0);
    /* wait until SBSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND))
        ;
    /* send slave address to I2C bus */
    i2c_master_addressing(I2C0, AddrValue, I2C_TRANSMITTER);
    /* wait until ADDSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
        ;
    /* clear the ADDSEND bit */
    i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
    /* wait until the transmit data buffer is empty */
    while (SET!=i2c_flag_get(I2C0, I2C_FLAG_TBE))
        ;
    /* send the EEPROM's internal address to write to : only one byte address */
    i2c_data_transmit(I2C0, (write_address&0xFF));
    /* wait until BTC bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
        ;
    /* while there is data to be written */
    while (number_of_byte--)
    {
        i2c_data_transmit(I2C0, *p_buffer);
        /* point to the next byte to be written */
        p_buffer++;
        /* wait until BTC bit is set */
        while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
            ;
    }
    /* send a stop condition to I2C bus */
    i2c_stop_on_bus(I2C0);
    /* wait until the stop condition is finished */
    while (I2C_CTL0(I2C0) &0x0200)
        ;
    Eeprom_WRDisable();

}

总结:本次项目中使用的GD32F303读写操作实现,对比之前用的eeprom,速度提高到1M,价格稍微贵了,读写速度提升了

作者: 小手凉凉, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-4026957.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

开发工匠 2025-4-22 11:04

写的好,学习和参考,很实用,大师之作

eeNick 2025-4-21 11:00

厉害,支持原创,先奖励20个E币
相关推荐阅读
小手凉凉 2025-04-21 16:17
【拆解】OBD-Tbox工具内部构造
车载 OBD-Tbox 作为车联网核心终端,通过 OBD 接口获取车辆数据并实现远程通信。本文通过实物拆解,深度解析其 PCB 板上的 STM32 主控芯片、OBD 接口隔离方案、4G 无线模块及 C...
小手凉凉 2025-04-19 19:32
【拆解】解剖儿子的原地掉头坦克
趁儿子上学去,出于好奇心驱使,偷偷把儿子的遥控坦克拆了,看看内部构造。以便于后续改造改造。拆解前玩具效果如下,现有的功能是遥控前进、后退、原地掉头、侧行、子弹发射等等。直接拆轮子,轮子的构造确实巧妙反...
小手凉凉 2025-04-19 18:52
【拆解】解剖周立功CANFD盒内部结构
在汽车零部件工作过的朋友基本都有使用过周立功CANFD盒子,2000多块的盒子里面究竟藏了多少东西。周立功 CAN FD 盒外观简洁坚固,外壳采用金属材质,具有良好的电磁屏蔽性能,能有效抵御外界电磁干...
小手凉凉 2025-04-19 18:22
【拆解】解剖分析一个RS485转DIDO模块构造
在工业自动化控制领域,RS485 转 DIDO(数字输入 / 数字输出)模块起着关键作用,它能够实现信号的转换与控制。采购从淘宝购买了一个常见的 RS485 转 DIDO 模块,交到我这边,拆解后对其...
小手凉凉 2025-04-19 18:08
【拆解】解剖一个淘宝上买的带网口的网关
在物联网时代,网关设备起着至关重要的作用,它如同一个智能中枢,连接着各种设备与网络。换做自己设计网关,估计使用stm32h750 这种带网口的高性能芯片来做,加上电平转换芯片、rj45口、外壳、继电器...
我要评论
2
0
关闭 站长推荐上一条 /3 下一条