恬蔚 发表于 2013-11-14 11:18

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

有关用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;
    Uint16i;   
    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 static/image/common/back.gif
你好,看来咱们用的是同一个测试程序,我想问下
bytein(0xA0 + ((addr & 0x0300) >> 7));//写入写控制字0 ...

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

skeletons 发表于 2014-1-13 08:49

zhangmangui 发表于 2014-1-12 17:07 static/image/common/back.gif
应该还与它的地址中某些位代表的意思有关系吧
是读是写?

读写都有

zhangmangui 发表于 2014-1-13 09:05

skeletons 发表于 2014-1-13 08:49 static/image/common/back.gif
读写都有

A0和A1来区分读写吧

xxf6212 发表于 2015-12-25 13:26

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

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

DWT1993 发表于 2015-12-26 14:46

学习!!
页: [1]
查看完整版本: 有关I2C给EEPROM传输数据的程序