瑞萨CPU平台的GPIO模拟I2C之二:读数据,基础读写调用

申明,下面的关于真值和假值的定义跟一般软件中的值相反,一般TRUE为1:

#define  TRUE  0   // 
#define  WRONG  -1   // 

 

U8 dtv_i2c_read( void )    //带应答的读字节,用于读多个数据时的中间字节
{
       U8 bReadData = 0x00;   //默认值

       U8 RoopCt;
       BusWait( _45us );

       pvSDA2= OFF;                //置SDA为输入
       for( RoopCt=0; RoopCt<8; RoopCt++ )
      {
             IntDisableWithPush;      
             poSCL2 = OFF;       
             pvSCL2 = ON;
             IntEnableByPop;

 

             BusWait( 4 + CNT_DATA );
             pvSCL2 = OFF; 

             BusWait( 1 + CNT_DATA );


             if( poSDA2  == ON )
             {     
                      bReadData |= BitOn[RoopCt];    //读的是1就保存相应位,否则以0移位
             }
             BusWait( 1 + CNT_DATA );
       }
       IntDisableWithPush;      
       poSCL2 = OFF;       
       pvSCL2 = ON;
       IntEnableByPop;

       BusWait( 4 + CNT_DATA );

 

       IntDisableWithPush;       
       poSDA2  = OFF;        
       pvSDA2 = ON;       //ack   ,读完一个字节数据要发应答信号
       IntEnableByPop; 

       BusWait( 1 + CNT_DATA );


       pvSCL2 = OFF;        
       BusWait( 4 + CNT_DATA );

       IntDisableWithPush;       
       poSCL2 = OFF;        
       pvSCL2 = ON;
       IntEnableByPop; 

       BusWait( 1 + CNT_DATA );
       return bReadData;
}

U8 dtv_i2c_readnc( void )        //不带应答的读数据,用来读取最后一个字节,同时停止I2C通讯
{
       U8 bReadData = 0x00;

       U8 RoopCt;
       BusWait( _45us );

       pvSDA2= OFF; 
       for( RoopCt=0; RoopCt<8; RoopCt++ )
       {
              IntDisableWithPush;      
              poSCL2 = OFF;       
              pvSCL2 = ON;
              IntEnableByPop;

 

              BusWait( 4 + CNT_DATA );
              pvSCL2 = OFF; 

              BusWait( 1 + CNT_DATA );
              if( poSDA2  == ON )
              {     
                      bReadData |= BitOn[RoopCt];       //读取数据位并保存
              }
              BusWait( 1 + CNT_DATA );
        }
        IntDisableWithPush;      
        poSCL2 = OFF;       
        pvSCL2 = ON;
        IntEnableByPop;

        BusWait( 4 + CNT_DATA );
      
        pvSDA2 = OFF;       //no ack    读完后不发应答,终止I2C通讯

        BusWait( 4 + CNT_DATA );
        pvSCL2 = OFF;        
        BusWait( 4 + CNT_DATA );

 

        IntDisableWithPush;       
        poSCL2 = OFF;        
        pvSCL2 = ON;
        IntEnableByPop; 

        BusWait( 4 + CNT_DATA );
        return bReadData;
}

 

以下是I2C传输基础函数

SI dtv_i2c_send( U8 bDataLength, U8* bDatBuffer )   //写数据,bDataLength数据长度,bDatBuffer 数据组指针
{
      SI RoopCt = 1;
      if( !dtv_i2c_start(*bDatBuffer) )      //I2C开始,并写一个数据
      {
             while(1)
             { 
                   if(RoopCt>=bDataLength)     //如果RoopCt计数大于等于数据长度,说明I2C传输完整成功
                   {
                          dtv_i2c_end();
                          return TRUE;
                   }
                   if(dtv_i2c_data(*(bDatBuffer+RoopCt)))    //如果没有传输完毕,继续剩下的数据
                   {
                           break;
                   }
                   RoopCt++;
             }
      }
      dtv_i2c_end();
      return WRONG;
}

 

SI dtv_i2c_recv( U8 bDataLength, U8 bInputPos, U8* bDatBuffer )  //bInputPos表示开始接受输入的数组元素位置
{                                                                           //bDataLength是总共的写入参数跟读出参数共享一个数组bDatBuffer 的长度
         SI IICErr;
         SI OutputCount = 1;
         U8 SlaveRead = 0;

 

        if(dtv_i2c_start(*bDatBuffer)==TRUE)         //开始I2C传输并传输一个数据
        {
              if(bInputPos!=1)  //如果bInputPos不为1,说明还要写入几个数据后,才能开始读
             {
                     for(IICErr=TRUE; OutputCount<bInputPos; OutputCount++)
                     {
                            if(dtv_i2c_data(*(bDatBuffer+OutputCount)))   //继续写入要传入的几个数据
                            {
                                   IICErr=WRONG;
                                   break;
                            }
                     }
                     SlaveRead = (*bDatBuffer | 0x01);  //之后,开始配置读命令。*bDatBuffer 始终存地址
                     dtv_i2c_end();                              //写完要读的地址之后,发个STOP。

                     if((IICErr==WRONG)||(dtv_i2c_start(SlaveRead)==WRONG))   //开始真正的读命令
                     {
                            dtv_i2c_end();
                            return WRONG;
                      }
              }
              for( ; OutputCount<bDataLength; OutputCount++ )
              {
                     *(bDatBuffer+OutputCount)=dtv_i2c_read();  //持续的读数据,用带应答的读命令
              }
              *(bDatBuffer+OutputCount)=dtv_i2c_readnc();     //读最后一个数据时,采用不发应答的读命令
              dtv_i2c_end();
              return TRUE;
       }
       dtv_i2c_end();
       return WRONG;
}

你可能感兴趣的:(c,平台,通讯)