AT24C1024的模拟IIC驱动

AT24C1024是基于IIC的EEPROM,容量为1024/8=128k bytes。它的引脚如下:

其中A1,A2为硬件地址引脚

WP为写保护引脚,一般我们需要读写,需要接低电平GND,接高的话则仅允许读

SDA和SCL则为IIC通信引脚

芯片通信采用IIC,有关IIC的通信原理可参考:

IIC通信原理-CSDN博客文章浏览阅读298次,点赞5次,收藏8次。这样看起来,区分起止信号与数据电平是不是就更加容易些了,但是嘛由于只有一根数据线了,缺点就是无法同时收发了,因此它是半双工通信的。一般的IIC器件,比如EEPROM,此时会发送要写入或读取的地址,如往0x0000地址写入数字1,那么会先发送0x0000,等到回码后再发送0x01,之后在收到应答后结束通信。前面在讲UART时提到过通信传输所需要的几个必要条件,首先得知道什么时候通信开始,什么时候通信结束,然后就是如何去解析数据了,根据这几点,我们来谈谈IIC是如何实现通信的。从图上可以看到,IIC规定的。https://blog.csdn.net/u011436603/article/details/136007075接下来说下具体的操作流程

读数据:

  1. 启动总线
  2. 发送设备地址+写...等待应答
  3. 发送数据存储地址...等待应答
  4. 发送数据
  5. 结束总线

写数据:

  1. 启动总线
  2. 发送设备地址+写...等待应答
  3. 发送数据存储地址...等待应答
  4. 发送设备地址+读...等待应答
  5. 读数据
  6. 结束总线

本次采用模拟IIC的方式,便于移植,具体的代码如下

void eeprom_start(void)
{
    IIC_SDA_ON;
    IIC_SCL_OFF;
    DELAY_US (10);

    IIC_SCL_ON;
    DELAY_US(1);
    IIC_SDA_OFF;
    DELAY_US(1);
    IIC_SCL_OFF;
    DELAY_US(2);

    IIC_SCL_OFF;
    IIC_SDA_ON;
    DELAY_US(10);
}

void eeprom_stop(void)
{
    IIC_SDA_OFF;
    IIC_SCL_OFF;
    DELAY_US(1);
    IIC_SCL_ON;
    DELAY_US(1);
    IIC_SDA_ON;
    DELAY_US(2);
    IIC_SCL_OFF;
    DELAY_US(2);

    IIC_SCL_OFF;
    IIC_SDA_ON;
    DELAY_US(10);
}

void eeprom_ack(void)
{
    IIC_SDA_ON;
    IIC_SCL_OFF;
    DELAY_US (10);
    IIC_SDA_OFF;
    DELAY_US(1);
    IIC_SCL_ON;
    DELAY_US(1);
    IIC_SCL_OFF;
    DELAY_US(2);
    IIC_SCL_OFF;
    IIC_SDA_ON;
    DELAY_US(10);
}

void eeprom_noack(void)
{
    IIC_SDA_ON;
    IIC_SCL_OFF;
    DELAY_US (10);
    IIC_SCL_ON;
    DELAY_US(1);
    IIC_SCL_OFF;
    DELAY_US(2);
    IIC_SCL_OFF;
    IIC_SDA_ON;
    DELAY_US(10);
}

void eeprom_checkack(void)
{
    IIC_SCL_ON;
    DELAY_US(10);
    IIC_SCL_OFF;
}

void eeprom_write_byte(unsigned char ucChar)
{
    unsigned char i;
    IIC_SDA_ON;
    IIC_SCL_OFF;
    DELAY_US (10);
    for(i=0; i<8; i++)
    {
        if(!(ucChar & BIT(7-i)) == 0)  IIC_SDA_ON;
        else                           IIC_SDA_OFF;
        DELAY_US (1);
        IIC_SCL_ON;
        DELAY_US(1);
        IIC_SCL_OFF;
        DELAY_US(2);
    }
    IIC_SCL_OFF;
    IIC_SDA_ON;
    DELAY_US(10);
}

unsigned char eeprom_read_byte(void)
{
    unsigned char i;
    unsigned char ucChar = 0;

    for(i=0; i<8; i++)
    {
        if(IIC_SDA_VALUE == 1)
        {
            ucChar |= BIT(7 - i);
        }
        else
        {
            ucChar &= ~BIT(7 - i);
        }
        IIC_SCL_ON;
        DELAY_US(1);
        IIC_SCL_OFF;
        DELAY_US(2);
    }
    IIC_SCL_OFF;
    IIC_SDA_ON;
    DELAY_US(10);
    return ucChar;
}
void eeprom_write_char(unsigned int nAddress,unsigned char ucChar)
{
    eeprom_start();
    if(nAddress>=0x10000)    eeprom_write_byte(0xa2);
    else                     eeprom_write_byte(0xa0);

    eeprom_checkack();

    eeprom_write_byte(nAddress/256);                               
    eeprom_checkack();
    eeprom_write_byte(nAddress%256);                          
    eeprom_checkack();

    eeprom_write_byte(ucChar);
    eeprom_checkack();

    eeprom_stop();                                
    if(nAddress%256 == 0) DELAY_MS(100);
    else DELAY_MS(8);
}

unsigned char eeprom_read_char(unsigned int nAddress)
{
    unsigned char ucChar;
    eeprom_start();                                      
    if(nAddress>=0x10000)    eeprom_write_byte(0xa2);
    else                     eeprom_write_byte(0xa0);

    eeprom_checkack();

    eeprom_write_byte(nAddress/256);                        
    eeprom_checkack();
    eeprom_write_byte(nAddress%256);                
    eeprom_checkack();

    eeprom_start();                                             
    if(nAddress>=0x10000)    eeprom_write_byte(0xa3);
    else                     eeprom_write_byte(0xa1);

    eeprom_checkack();

    ucChar = eeprom_read_byte();

    eeprom_noack();

    eeprom_stop();

    DELAY_US(10);

    return  ucChar;
}

其中IIC_SCL_ON和IIC_SCL_OFF表示SCL引脚电平拉高或拉低,

IIC_SDA_ON和IIC_SDA_OFF表示SDA引脚电平拉高或拉低,IIC_SDA_VALUE表示读取SDA引脚电平。需要注意的是,模拟IIC时引脚需要设置为开漏输出且需要上拉电阻。

有两个需要注意的点,一个是器件地址指令,当写存储地址处于前一半时,发送A0指令,当写存储地址处于后一半时,发送A2指令。另一个则是跨页写,每256字节为一页,当出现跨页写时,需要增大延时,否则有可能出错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕诗客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值