打印

有关I2C给EEPROM传输数据的程序

[复制链接]
2424|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
恬蔚|  楼主 | 2013-11-14 11:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
有关用I2C给EEPROM传数据的实验,我不明白什么时候才用ACK,这个程序里bytein里包含ACK而byteout不含ACK,不太明白怎么回事?难道写入EEPROM时用I2C,写出EEPROM不用么?
还有这句;ch |= SDA_R;    //数据通过SDA 串行移出EEPROM  "|="是对位操作吧?所以是数据通过SDA串行移出吗?   谢谢解答了先!
/******************************IO口初始化****************************/
void Eerom_Gpio_Init(void)
{
        EALLOW;
    GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0;                  //上拉
    GpioCtrlRegs.GPBDIR.bit.GPIO32 = 1;           // 输出端口
    GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 0;          // IO口
    GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3;         // 不同步

    GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0;                  //上拉
    GpioCtrlRegs.GPBDIR.bit.GPIO33 = 1;           // 输出端口
    GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 0;          // IO口
    GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3;   // 不同步
    EDIS;
}
__inline void SDA_READ(void)
{
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO32=0;       //Input, SDA
    EDIS;
}

__inline void SDA_WRITE(void)
{
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO32=1;       //Output. SDA
    EDIS;
}




///=========================GPIO SIMULATE I2c communication=====================*/
void delay(Uint16 time)                                         //延时函数
{
    for(; time>0 ; time--)
    {
        asm(" nop");
        asm(" nop");
        asm(" nop");
        asm(" nop");
                asm(" nop");
        asm(" nop");
        asm(" nop");
        asm(" nop");
    }
}


void begintrans(void)                                       //发送START 信号
{
    SDA_W1;                                                         //SDA=1
    delay(DELAY_UNIT * 10);                         //延时
    SDA_WRITE();                                            //SDA 方向为输出到EEPROM
    delay(DELAY_UNIT * 10);                         //延时
    SCL_1;                                                          //SCL=1
    delay(DELAY_UNIT * 10);                         //延时
    SDA_W0;                                                         //SDA=0
    delay(DELAY_UNIT * 10);                                //延时
}

void stoptrans(void)                                        //发送STOP 信号
{
    SDA_WRITE();                                            //SDA方向为输出到EEPROM
    delay(DELAY_UNIT * 10);                                //延时
    SDA_W0;                                                         //SDA=0
    delay(DELAY_UNIT * 10);                         //延时
    SCL_1;                                                          //SCL=1
    delay(DELAY_UNIT * 10);                         //延时
    SDA_W1;                                                         //SDA=1
    delay(DELAY_UNIT * 10);       
}

void ack(void)                                              //等待EEPROM 的ACK 信号
{
    Uint16 d;
    Uint16  i;     
    SDA_READ();                                             //SDA方向为从EEPROM 输入
    delay(DELAY_UNIT * 2);                          //延时
    SCL_1;                                                          //SCL=1
    delay(DELAY_UNIT * 2);                                  //延时
    i = 0;              
    do
    {
        d = SDA_R;
        i++;
        delay(DELAY_UNIT);       
    }
    while((d == 1) && (i <= 500));              //等待EEPROM 输出低电平,4ms后退出循环

    if (i >= 499)
    {
        eromrw_err = 0xff;
    }
   
    i = 0;           
    SCL_0;                                                          //SCL=0
    delay(DELAY_UNIT * 2);                          //延时
}

void bytein(Uint16 ch)                                          //向EEPROM 写入一个字节
{
    Uint16 i;     
    SCL_0;                                                          //SCL=0
    delay(DELAY_UNIT * 2);                                        //延时
    SDA_WRITE();                                            //SDA方向为输出到EEPROM
    delay(DELAY_UNIT);                                          //延时
    for(i=8;i>0;i--)
    {       
        if ((ch & 0x80)== 0)
            {
            SDA_W0;                                             //数据通过SDA 串行移入EEPROM
            delay(DELAY_UNIT);                                //延时
            }
        else
            {
            SDA_W1;
            delay(DELAY_UNIT);                                //延时
            }
        SCL_1;                                                      //SCL=1
        delay(DELAY_UNIT * 2);                      //延时
        ch <<= 1;
        SCL_0;                                                      //SCL=0
        delay(DELAY_UNIT);                              //延时
    }
    ack();
}

Uint16 byteout(void)                                        //从EEPROM 输出一个字节
{
    unsigned char i;
    Uint16 ch;
    ch = 0;

    SDA_READ();                                             //SDA 的方向为从EEPROM 输出
    delay(DELAY_UNIT * 2);                                 //延时
    for(i=8;i>0;i--)
    {
        ch <<= 1;
        SCL_1;                                                      //SCL=1
        delay(DELAY_UNIT);                              //延时
        ch |= SDA_R;                                            //数据通过SDA 串行移出EEPROM
        delay(DELAY_UNIT);                                     //延时
        SCL_0;                                                      //SCL=0
        delay(DELAY_UNIT * 2);                      //延时
    }
    return(ch);
}

void writebyte(Uint16 addr,Uint16 data)         //向EEPROM 指定地址写入一个字节的数据
{
    begintrans();                                                        //开始
    bytein(0xA0 + ((addr & 0x0300) >> 7));  //写入写控制字0xA0
    bytein(addr);                                               //写入指定地址
    bytein(data);                                                      //写入待写入EEPROM 的数据
    stoptrans();                                                        //停止
    delay(8000);
}



Uint16 readbyte(Uint16 addr)                                 //从EEPROM 指定地址读取一个字节的数据
{
    Uint16 c;   
    begintrans();                                               //开始
    bytein(0xA0 + ((addr & 0x0300) >> 7));  //写入写控制字0xA0
    bytein(addr);                                               //写入指定地址
    begintrans();                                               //开始
    bytein(0xA1);                                               //写入读控制字0xA1
    c = byteout();                                              //读出EEPROM 输出的数据
    stoptrans();                                                //停止
    delay(2000);                                                //延时
    return(c);
}

相关帖子

沙发
zhangmangui| | 2013-11-14 23:38 | 只看该作者
关于你的ACK还要看具体说明了   一些IIC器件要求不同
写入和读出EEPROM肯定都是通过IIC的   有一位标志表明是读还是写
ch |= SDA_R;  意思就是ch = ch |SDA_R;

使用特权

评论回复
板凳
skeletons| | 2014-1-12 13:26 | 只看该作者
你好,看来咱们用的是同一个测试程序,我想问下
bytein(0xA0 + ((addr & 0x0300) >> 7));  //写入写控制字0xA0
这句,他为啥不直接用bytein(0xA0);,为什么还要移位运算,貌似没有啥不同啊?
谢谢

使用特权

评论回复
地板
zhangmangui| | 2014-1-12 17:07 | 只看该作者
skeletons 发表于 2014-1-12 13:26
你好,看来咱们用的是同一个测试程序,我想问下
bytein(0xA0 + ((addr & 0x0300) >> 7));  //写入写控制字0 ...

应该还与它的地址中某些位代表的意思有关系吧
是读是写?

使用特权

评论回复
5
skeletons| | 2014-1-13 08:49 | 只看该作者
zhangmangui 发表于 2014-1-12 17:07
应该还与它的地址中某些位代表的意思有关系吧
是读是写?

读写都有

使用特权

评论回复
6
zhangmangui| | 2014-1-13 09:05 | 只看该作者
skeletons 发表于 2014-1-13 08:49
读写都有

A0和A1来区分读写吧

使用特权

评论回复
7
xxf6212| | 2015-12-25 13:26 | 只看该作者
skeletons 发表于 2014-1-12 13:26
你好,看来咱们用的是同一个测试程序,我想问下
bytein(0xA0 + ((addr & 0x0300) >> 7));  //写入写控制字0 ...

你这个程序还有吗,能不能给我参考下

使用特权

评论回复
8
DWT1993| | 2015-12-26 14:46 | 只看该作者
学习!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

147

帖子

1

粉丝