打印

I2C的问题

[复制链接]
1707|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
撒旦狂魔|  楼主 | 2010-4-12 20:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2c, se, ST, ck, ic
这几天在看IIC的协议以及周立功的一些例程,程序中有些问题总是不能理解,应该是我对协议没有吃透,所以这里提出来,希望能够得到解答(中断处理程序中的):

            void __irq IRQ_I2C0(void)   
{                                                                              
        
    switch (I2STAT & 0xF8)              /* 读取I2C状态寄存器I2DAT */   
    {      
        case 0x08:                                              /* 已发送起始条件,主发送和主接收都有 */   
        {                                                                   /* 装入SLA+W或者SLA+R */   
            if(I2C_suba_en == 1)                        /* SLA+R,指定子地址读 */   
            {      
                I2DAT = I2C_sla & 0xFE;             /* 先写入地址 */   
            }   
      else                                                      /* SLA+W */   
      {         
        I2DAT = I2C_sla;                    /* 否则直接发送从机地址 */   
      }   
                                                                /* 清零SI位 */   
      I2CONCLR =    (1 << 3)|                     /* SI */   
                        (1 << 5);                     /* STA */   
    }   
    break;   
               
    case 0x10:                                              /*已发送重复起始条件,主发送和主接收都有 */   
    {                                                               /* 装入SLA+W或者SLA+R */   
      I2DAT = I2C_sla;                              /* 重起总线后,重发从地址*/   
      I2CONCLR = 0x28;                              /* 清零SI,STA */   
        }   
    break;   
            
        case 0x18:   
    case 0x28:                                              /* 已发送I2DAT中的数据,已接收ACK */   
    {   
      if (I2C_suba_en == 0)   
      {   
           if (I2C_num > 0)   
           {    I2DAT = *I2C_buf++;   
                I2CONCLR = 0x28;                    /* 清零SI,STA */   
                    I2C_num--;   
           }   
           else                                                 /* 没有数据发送了 */   
           {                                                        /* 停止总线 */   
                    I2CONSET = (1 << 4);  /* STO  */   
                    I2CONCLR = 0x28;                /* 清零SI,STA */   
                    I2C_end = 1;                    /* 总线已经停止 */   
           }   
       }   
               
       if(I2C_suba_en == 1)                     /* 若是指定地址读,则重新启动总线 */   
       {     
          if (I2C_suba_num == 2)   
          {     
                I2DAT = ((I2C_suba >> 8) & 0xff);   
                    I2CONCLR = 0x28;                /* 清零SI,STA */   
                    I2C_suba_num--;   
                    break;      
            }     
                    
            if(I2C_suba_num == 1)   
            {   I2DAT = (I2C_suba & 0xff);   
                    I2CONCLR = 0x28;                    /* 清零SI,STA */   
                    I2C_suba_num--;   
                    break;      
            }   
                    
          if (I2C_suba_num == 0)   
          { I2CONSET = 0x20;   
                    I2CONCLR = 0x08;   
                    I2C_suba_en = 0;     /* 子地址己处理 */   
                    break;   
          }   
        }   
               
        if (I2C_suba_en == 2)                   /* 指定子地址写,子地址尚未指定,则发送子地址 */   
        {   
            if (I2C_suba_num > 0)   
          {     
            if (I2C_suba_num == 2)   
            {   I2DAT = ((I2C_suba >> 8) & 0xff);   
                        I2CONCLR = 0x28;   
                        I2C_suba_num--;   
                        break;   
            }   
            if (I2C_suba_num == 1)   
            {      
                I2DAT = (I2C_suba & 0xff);   
              I2CONCLR = 0x28;   
              I2C_suba_num--;   
              I2C_suba_en  = 0;   
              break;   
            }   
          }   
        }   
      }   
      break;   
                  
      case 0x40:                                        /* 已发送SLA+R,已接收ACK */   
      {   
        if (I2C_num <= 1)                        /* 如果是最后一个字节 */            
        {      
            I2CONCLR = 1 << 2;        /* 下次发送非应答信号 */   
        }   
        else   
        {      
            I2CONSET = 1 << 2;                /* 下次发送应答信号 */   
        }   
        I2CONCLR = 0x28;                        /* 清零SI,STA */   
      }         
      break;   
   
      case 0x20:                                        /* 已发送SLA+W,已接收非应答              */   
      case 0x30:                                        /* 已发送I2DAT中的数据,已接收非应答     */   
      case 0x38:                                        /* 在SLA+R/W或数据字节中丢失仲裁         */   
        case 0x48:                                      /* 已发送SLA+R,已接收非应答              */   
      {         
        I2CONCLR = 0x28;   
        I2C_end = 0xFF;   
        }      
        break;                     
        
        case 0x50:                                          /* 已接收数据字节,已返回ACK */   
        {      
            *I2C_buf++ = I2DAT;   
            I2C_num--;   
            if (I2C_num == 1)                           /* 接收最后一个字节 */   
            {   I2CONCLR = 0x2C;                    /* STA,SI,AA = 0    */   
            }   
            else   
            {   I2CONSET = 0x04;                    /* AA=1 */   
                I2CONCLR = 0x28;   
            }   
        }      
        break;   
            
        case 0x58:                                          /* 已接收数据字节,已返回非应答 */   
        {      
            *I2C_buf++ = I2DAT;                 /* 读取最后一字节数据 */   
      I2CONSET = 0x10;                  /* 结束总线 */   
      I2CONCLR = 0x28;   
      I2C_end = 1;     
    }            
    break;   
                    
    default:   
      break;   
    }   
  VICVectAddr = 0x00;              /* 中断处理结束 */   

}   

Question1:当状态为40H时(已经发送SLA+R),程序判断是否是最后一个字节,然后判断下次是发送应答信号还是非应答信号,所以我想问,为什么在发送完SLA+W时没有这个判断过程。


Question2:关于状态30与状态58----为什么已发送I2DAT中的数据,已接受非应答信号(30H)这个状态就是属于总线出错,而已接受数据字节,已返回非应答信号(58H)这个状态就是代表是最后一个字节,结束总线。

相关帖子

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

本版积分规则

0

主题

1

帖子

1

粉丝