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有三種模式: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/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章