stm32f3的i2c使用小结

这几天拿到了stm32f3discovery,拿到手的第一件事就是测试了硬件i2c,使用stm32cube生成库,测试对象为AD5934与ADG715。经过两天的调试,完美调通。中间也碰到了些问题。
1、一开始用的I2C1,一仿真就会出现死机的情况。
        由于I2C1与swd接口重合,所以调用HAL_I2C_Init()函数后就死机,改成I2C2后问题解决。
2、无法访问指定地址的设备
        库函数中的入口地址并不是7bit地址,需要输入8bit。我的设备地址为13,始终无法访问设备,改为26后解决。
3、可以读写单个地址的数据,但是不能多字节读写。
       (1)、对于多字节写, 库函数中的
        HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
       其中 MemAddSize表示地址的位数,0表示7bit地址,1表示10bit地址。我误认为这个写的字节数,所以导致在写多字节的时候出错。
       (2)、对于多字节读,由于AD5934的读操作与库函数的读操作有些出入,所以导致一直读错误。在库函数中写完读的内存地址就开始读,而AD5934中写完block read后接着还要再写一个number bytes read然后才开始读。所以需要对库函数进行修改,新增一个函数,以适合AD5934的block read.

stm32f3的i2c使用小结_第1张图片

        stm32f3的i2c有三种模式:Reload、AutoEnd、SoftEnd模式。

        i2c每发送完一个字节,就会产生TXIS标志,当发送完最后一个字节时:

        对于Reload模式,当字节大于255字节时,必须使用此模式,此模式下发送结束后,会产生tcr标志。

        对于AutoEnd模式,发送后最后一个字节时,会自动产生STOP。

        对于SoftEnd模式,发送完最后一个字节时,会产生tc标志,对于发送过程中需要Restart的需要使用此模式。

        对于AD5934的读操作,可以事先工作在SoftEnd模式,发送完block read与number bytes read字节后,再转入AutoEnd模式进行Restart,读取完指定的字节后自动产生STOP。操作流程如下:






HAL_StatusTypeDef   HAL_I2C_Mem_Read_AD5934_Block ( I2C_HandleTypeDef   * hi2c ,   uint16_t   DevAddress ,   uint16_t   MemAddress ,   uint16_t   MemAddSize ,   uint8_t   * pData ,   uint16_t   Size ,   uint32_t   Timeout )
{
  
uint32_t   Sizetmp   =   0 ;

  
/* Check the parameters  http://tiyubisai.com/video_news/news_135585.html */
  
assert_param ( IS_I2C_MEMADD_SIZE ( MemAddSize ));
  
  
if ( hi2c -> State   ==   HAL_I2C_STATE_READY )
  
{     
    
if (( pData   ==   NULL )   ||   ( Size   ==   0 ))  
    
{
      
return    HAL_ERROR ;                                     
    
}

    
if ( __HAL_I2C_GET_FLAG ( hi2c ,   I2C_FLAG_BUSY )   ==   SET )
    
{
      
return   HAL_BUSY ;
    
}

    
/* Process Locked */
    
__HAL_LOCK ( hi2c );
    
    
hi2c -> State   =   HAL_I2C_STATE_MEM_BUSY_RX ;
    
hi2c -> ErrorCode   =   HAL_I2C_ERROR_NONE ;
    
/*
    //Send Slave Address and Memory Address 
    if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout) != HAL_OK)
    {
      if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      {
        // Process Unlocked 
        __HAL_UNLOCK(hi2c);
        return HAL_ERROR;
      }
      else
      {
        // Process Unlocked 
        __HAL_UNLOCK(hi2c);
        return HAL_TIMEOUT;
      }
    }*/

    
    
I2C_TransferConfig ( hi2c , DevAddress , MemAddSize + 1 ,   I2C_SOFTEND_MODE ,   I2C_GENERATE_START_WRITE );
      
    
/* Wait until TXIS flag is set */
    
if ( I2C_WaitOnTXISFlagUntilTimeout ( hi2c ,   Timeout )   !=   HAL_OK )
    
{
      
if ( hi2c -> ErrorCode   ==   HAL_I2C_ERROR_AF )
      
{
        
return   HAL_ERROR ;
      
}
      
else
      
{
        
return   HAL_TIMEOUT ;
      
}
    
}
    
    
/* If Memory address size is 8Bit */
    
if ( MemAddSize   ==   I2C_MEMADD_SIZE_8BIT )
    
{
      
/* Send Memory Address */
      
hi2c -> Instance -> TXDR   =   __HAL_I2C_MEM_ADD_LSB ( MemAddress );     
    
}       
    
/* If Mememory address size is 16Bit */
    
else
    
{
      
/* Send MSB of Memory Address */
      
hi2c -> Instance -> TXDR   =   __HAL_I2C_MEM_ADD_MSB ( MemAddress );  
      
      
/* Wait until TXIS flag is set */
      
if ( I2C_WaitOnTXISFlagUntilTimeout ( hi2c ,   Timeout )   !=   HAL_OK )
      
{
        
if ( hi2c -> ErrorCode   ==   HAL_I2C_ERROR_AF )
        
{
          
return   HAL_ERROR ;
        
}
        
else
        
{
          
return   HAL_TIMEOUT ;
        
}
      
}
      
      
/* Send LSB of Memory Address */
      
hi2c -> Instance -> TXDR   =   __HAL_I2C_MEM_ADD_LSB ( MemAddress );   
    
}
   
    
/* Wait until TXIS flag is set */
    
if ( I2C_WaitOnTXISFlagUntilTimeout ( hi2c ,   Timeout )   !=   HAL_OK )
    
{
      
if ( hi2c -> ErrorCode   ==   HAL_I2C_ERROR_AF )
      
{
        
return   HAL_ERROR ;
      
}
      
else
      
{
        
return   HAL_TIMEOUT ;
      
}
    
}
    
    
hi2c -> Instance -> TXDR   =   Size ;  
    
    
/* Wait until TC flag is set */
    
if ( I2C_WaitOnFlagUntilTimeout ( hi2c ,   I2C_FLAG_TC ,   RESET ,   Timeout )   !=   HAL_OK )       
    
{
      
return   HAL_TIMEOUT ;
    
}     
    
    
/* Send Slave Address */
    
/* Set NBYTES to write and reload if size > 255 and generate RESTART */
    
/* Size > 255, need to set RELOAD bit */
    
if ( Size   >   255 )
    
{
      
I2C_TransferConfig ( hi2c , DevAddress , 255 ,   I2C_RELOAD_MODE ,   I2C_GENERATE_START_READ );
      
Sizetmp   =   255 ;
    
}
    
else
    
{
      
I2C_TransferConfig ( hi2c , DevAddress , Size ,   I2C_AUTOEND_MODE ,   I2C_GENERATE_START_READ );
      
Sizetmp   =   Size ;
    
}
    
    
do
    
{   
      
/* Wait until RXNE flag is set */
      
if ( I2C_WaitOnFlagUntilTimeout ( hi2c ,   I2C_FLAG_RXNE ,   RESET ,   Timeout )   !=   HAL_OK )       
      
{
        
return   HAL_TIMEOUT ;
      
}
          
      
/* Read data from RXDR */
      
(* pData ++)   =   hi2c -> Instance -> RXDR ;

      
/* Decrement the Size counter */
      
Sizetmp --;
      
Size --;    

      
if (( Sizetmp   ==   0 )&&( Size != 0 ))
      
{
        
/* Wait until TCR flag is set */
        
if ( I2C_WaitOnFlagUntilTimeout ( hi2c ,   I2C_FLAG_TCR ,   RESET ,   Timeout )   !=   HAL_OK )       
        
{
          
return   HAL_TIMEOUT ;
        
}
        
        
if ( Size   >   255 )
        
{
          
I2C_TransferConfig ( hi2c , DevAddress , 255 ,   I2C_RELOAD_MODE ,   I2C_NO_STARTSTOP );
          
Sizetmp   =   255 ;
        
}
        
else
        
{
          
I2C_TransferConfig ( hi2c , DevAddress , Size ,   I2C_AUTOEND_MODE ,   I2C_NO_STARTSTOP );
          
Sizetmp   =   Size ;
        
}
      
}

    
} while ( Size   >   0 );

    
/* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
    
/* Wait until STOPF flag is reset */  
    
if ( I2C_WaitOnSTOPFlagUntilTimeout ( hi2c ,   I2C_TIMEOUT_STOPF )   !=   HAL_OK )
    
{
      
if ( hi2c -> ErrorCode   ==   HAL_I2C_ERROR_AF )
      
{
        
return   HAL_ERROR ;
      
}
      
else
      
{
        
return   HAL_TIMEOUT ;
      
}
    
}

    
/* Clear STOP Flag */
    
__HAL_I2C_CLEAR_FLAG ( hi2c ,   I2C_FLAG_STOPF );
    
    
/* Clear Configuration Register 2 */
    
__HAL_I2C_RESET_CR2 ( hi2c );
    
    
hi2c -> State   =   HAL_I2C_STATE_READY ;
    
    
/* Process Unlocked */
    
__HAL_UNLOCK ( hi2c );
    
    
return   HAL_OK ;
  
}
  
else
  
{
    
return   HAL_BUSY ;
  
}
}
http://blog.csdn.net/xiaoxiongli/article/details/49637785
http://blog.csdn.net/xiaoxiongli/

你可能感兴趣的:(stm32f3的i2c使用小结)