打印

请教,24FJ64GA006的硬件I2C总是不对!

[复制链接]
3320|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
刘骁奖|  楼主 | 2009-11-1 22:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
24FJ64GA006的硬件I2C总是不对,是芯片BUG吗?芯片上面的印字为PIC24FJ64GA006 -I / PT 064932P,在MPLAB IDE中连接信息如下:
Target Device PIC24FJ64GA006 found, revision = Rev 0x3002


这个是PIC24FJ128GA010 Family Silicon Errata and Data Sheet Clarification
ERROR.jpg (41.12 KB)
2009-10-30 22:37




我用这款芯片的第一组I2C端口,外接了一片24FC512的EEPROM,我外接4M的晶体,I2CBRG设定为2,但是和EE的通信总是不对,使用MICROCHIP上面的例子程序也不行!这个芯片有点早,当时项目用24FJ64GA004了,申请了一直放着,所以是不是我这款有硬件BUG呢,不知道芯片版本如何看!请各位FAE帮助给看一下,谢谢啦。


我的程序如下:unsigned GetValue(void)                 //本函数的返回值:0,表示接收错误;1,表示接收正确
{
           unsigned OK;
        unsigned char j;
   
           OK = false;
        I2C1BRG = 0x02;                 //Fosc=4MHZ, Fcy=2MHZ, Fscl=100K      
        I2C1CON = 0xD200;                      //Enable I2C
        
        I2Cdelay(30);        
        I2CIdle();
          I2C1CONbits.PEN=1;                   //发送Stop位;
        while(I2C1CONbits.PEN);                //

            I2Cdelay(30);   
        I2CIdle();
        I2C1CONbits.SEN=1;                  //I2CStart   
        while(I2C1CONbits.SEN);         //PIC24的特点就是:SEN人工置1=启动;自动清零=启动执行完毕

        I2CIdle();
        MasterWriteI2C1(0B10100001);        //写器件地址(bit7~bit6:器件地址1010 000,bit0=0表示写,=1表示读)
        I2CIdle();
        if(I2C1STATbits.ACKSTAT)
        goto        STOPI2C;                   //如果cpu收到的是NACK,则直接发送I2CSTOP

        I2CIdle();
        MasterWriteI2C1(0x01);            //选中内部地址 A15~A8
        I2CIdle();        
        if(I2C1STATbits.ACKSTAT)
        goto        STOPI2C;                   //如果cpu收到的是NACK,则直接发送I2CSTOP
        
        I2CIdle();
        MasterWriteI2C1(0x01);            //选中内部地址 A7~A0
        I2CIdle();
        if(I2C1STATbits.ACKSTAT)
        goto        STOPI2C;                   //如果cpu收到的是NACK,则直接发送I2CSTOP

        for(j=0;j<15;j++)
        {
                I2C_RECV[j]=MasterReadI2C1();
               
                if (j!=15)
                {
                        I2C1CONbits.ACKDT = 0;                //要发的应答信号是0(即ACK)
                        I2C1CONbits.ACKEN = 1;                //要发的应答的使能信号
                        while(I2C1CONbits.ACKEN);        //发送ACKDT数据位,主器件应答序列结束时由硬件清零
                }
                else
                {
                        I2C1CONbits.ACKDT = 1;                //要发的应答信号是0(即NO ACK)
                        I2C1CONbits.ACKEN = 1;                //要发的应答的使能信号
                        while(I2C1CONbits.ACKEN);        //发送ACKDT数据位,主器件应答序列结束时由硬件清零
                        OK = true;
STOPI2C:                        
                        I2Cdelay(30);
                        I2C1CONbits.PEN=1;                   //发送Stop位;
                        while(I2C1CONbits.PEN);                //         
                }
        }

        I2C1CON = 0;                                      //Disable I2C1        
        SETSDA = 1;                                        //input status
        SETSCL = 1;
        return(OK);
}
//***********************************************
//daughter routines
//***********************************************
void I2CIdle(void)
{
        while(I2C1CONbits.SEN||I2C1CONbits.PEN||I2C1CONbits.RSEN
           ||I2C1CONbits.RCEN||I2C1CONbits.ACKEN||I2C1STATbits.TRSTAT);   //wait I2C idle
}

unsigned char MasterWriteI2C1(unsigned int Data_out)
{
        I2C1TRN = Data_out;   //所谓“OUT”,是说CPU输出(可不是说2304输出),TRN是transist的缩写
//I2C1TRN=发送缓冲器,存放数据
        if(I2C1STATbits.IWCOL)          /* If write collision occurs,return 0 */
          return 0;
        else
        {
                  while(I2C1STATbits.TBF);  //发送过程中,处于“忙”状态,发完后自动清零,不用我们操心
                  return 1;
        }
}

unsigned int MasterReadI2C1(void)  /*read data*/
{
        I2Cdelay(3);
        I2C1CONbits.RCEN = 1;
        I2Cdelay(3);

        while(!I2C1STATbits.RBF);   //置1、清0均由硬件自动完成,1=已经接收完;0=没接收完,请等待
        I2C1STAT&= 0xFFBF;    //here , please use word operation to clr i2cov
//i2cov=1表示溢出(收到的旧数据尚未处理,新数据来了,)
        return(I2C1RCV);   //I2C1RCV=接收缓冲器,存放数据
}

void I2Cdelay(unsigned int Time)
{
        unsigned int i,j;
        for(i=0;i<=Time;i++)
        {
                asm("nop");
                for(j=0;j<=570;j++)   //1ms
                  {
                  asm("nop");
                  asm("nop");
                  }
        }
}
沙发
夜夜| | 2009-11-2 00:08 | 只看该作者
芯片出问题的机会非常的小,如果怀疑建议焊下来换一个芯片试一下。

不知道你的通讯不正常具体表现是什么;是iic口没有波形出来,还是读写的数据不对?

大概看了下你的程序,在读数据之前先要指定地址的,你的getvalue函数看起来是随机读取数据。

使用特权

评论回复
板凳
portx| | 2009-11-24 13:28 | 只看该作者
本帖最后由 portx 于 2009-11-24 13:30 编辑

我记得I2C通讯的读操作顺序应该是  起始->功能码0xA1->ACK检测->器件地址码->ACK检测->功能码0xA0->ACK检测->读地址码->ACK检测->读出的数据内容->停止

使用特权

评论回复
地板
e掾木| | 2009-11-24 21:22 | 只看该作者
i2c时序还是比较恼火的,包括MCHP网站上那个代码示例,仅此运行是没错的,稍加修改就不行,我为此郁闷了好几天,最后自己慢慢写,搬出DSO认证校对,才搞定了。

使用特权

评论回复
5
isbit| | 2010-6-5 09:26 | 只看该作者
一直都用io模拟,pic自己的iic真jb麻烦啊!
晕,还是要用pic api做!头痛
谁有 能跑的历程啊

使用特权

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

本版积分规则

36

主题

430

帖子

22

粉丝