使用STM8S i2c對TPS65987寄存器進行讀寫


 

上圖是TPS65987的i2c讀寫協議,和標准i2c協議有點出入,不過也不難理解,在讀的時候i2c slave在發送數據過來之前會先發送1byte數據表示后面會有幾個字節數據過來,在寫的時候i2c host要先寫1byte數據告訴i2c slave接下來會寫幾個bytes數據。

 Talk is cheap. Show me the code.

以下代碼是基於STM8S。

/*******************************************************************************
**函數名稱:void IIC_Read(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer)
**功能描述:向IIC器件讀數據
**入口參數:
          subaddr :  從器件地址
          Byte_addr : 確定從器件寫地址的起始地址
          *buffer   : 讀數據的緩沖區起始地址
**輸出:無
*******************************************************************************/
void TPS65987_IIC_Read(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer)
{
  unsigned char i2csr1;
  unsigned char DataLen;
  
  I2C_CR2_bit.ACK = 1;            //產生應答信號
  
  I2C_CR2_bit.START = 1;    //發送起始信號
  while(I2C_SR1_bit.SB == 0);    //等待起始信號產生
  i2csr1 = I2C_SR1;        //SR1.AF??
  I2C_DR = subaddr;        //發送器件地地址,並清除SB標志位
  while(I2C_SR1_bit.ADDR == 0);    //等待器件地址發送完成
  i2csr1 = I2C_SR1;
  i2csr1 = I2C_SR3;        //讀狀態寄存器1和狀態寄存器3清除發送器件地址標志位
  I2C_DR = Byte_addr;
  while(I2C_SR1_bit.BTF == 0);//等待移位發送器發送完成
  i2csr1 = I2C_SR1;    //清除BIT標志位
  
  //重新發送起始信號
  I2C_CR2_bit.START = 1;//I2C1->CR1 |= I2C_CR1_START;
  while(I2C_SR1_bit.SB == 0);//等待起始信號產生

  i2csr1 = I2C_SR1;//SR1.AF??
  I2C_DR = (char)(subaddr | 0x01);    //發送器件地地址,並清除SB標志位
  while(I2C_SR1_bit.ADDR == 0);         //等待器件地址發送完成
  i2csr1 = I2C_SR1;
  i2csr1 = I2C_SR3;            //讀狀態寄存器1和狀態寄存器2清除發送器件地址標志位
  
  while (I2C_SR1_bit.RXNE == 0); //先讀取Byte Count到DataLen
  i2csr1 = I2C_SR1;
  DataLen = I2C_DR;
  
  while(DataLen)
  {
    if(DataLen == 1)
    {
        I2C_CR2_bit.ACK = 0;          //最后一個字節不產生應答信號
        I2C_CR2_bit.STOP = 1;         //發送停止信號結束數據傳輸
    }

    while(I2C_SR1_bit.RXNE == 0);
    i2csr1 = I2C_SR1;

    *buffer = I2C_DR;    
    buffer++;
    DataLen--;
  }
}
/*******************************************************************************
**函數名稱:void IIC_Write(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer , unsigned short num)
**功能描述:向IIC器件寫數據
**入口參數:
          subaddr :  從器件地址
          Byte_addr : 確定器件寫地址的起始地址
          *buffer   : 寫數據的起址地址
          num                : 要寫數據的個數
**輸出:無
*******************************************************************************/
void TPS65987_IIC_Write(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer , unsigned short num)
{
    unsigned char i2csr1;
    
    
    //while(I2C1->SR2 & I2C_SR2_BUSY);          //判斷I2C模塊是否忙
    
    //發送起始信號
    I2C_CR2_bit.START = 1;    
    while(I2C_SR1_bit.SB == 0);    //等待起始信號產生
    i2csr1 = I2C_SR1; //SR1.AF
    I2C_DR = (subaddr);        //發送從器件地址,並清除SB標志位
    while(I2C_SR1_bit.ADDR == 0);    //等待器件地址發送完成
    i2csr1 = I2C_SR1;
    i2csr1 = I2C_SR3;        //讀狀態寄存器1和狀態寄存器3清除發送器件地址標志位
    

    I2C_DR = Byte_addr;             //發送從器件存儲首地址
#if 1
    while(I2C_SR1_bit.BTF == 0);  //等待移位發送器發送完成
    i2csr1 = I2C_SR1;          //清除BIT標志位
#else
    while((I2C_SR1_bit.TXE) == 0);//數據寄存器為空,跳出循環繼續運行
    i2csr1 = I2C_SR1;
#endif
        I2C_DR = (unsigned char)num; //把Byte Count先告訴給TPS65987
        while(I2C_SR1_bit.BTF == 0);//等待移位發送器發送完成
        i2csr1 = I2C_SR1;        //清除BIT標志位
        i2csr1 = I2C_DR;
        
    while(num > 0)
    {
            I2C_DR = *buffer;        //發送器件存儲首地址

            while(I2C_SR1_bit.BTF == 0);//等待移位發送器發送完成
            i2csr1 = I2C_SR1;        //清除BIT標志位
            i2csr1 = I2C_DR;
            buffer++;
            num--;
    }
    I2C_CR2_bit.STOP = 1;       //發送停止信號結束數據傳輸
}

這樣就可以對TPS65987進行讀寫了。

上面的i2c讀寫函數沒有加上timeout功能,如果不想在i2c通信不成功時一直阻塞的話,可以在while循環里面加上,例如:

unsigned int count = 0;

while(I2C_SR1_bit.ADDR == 0)    //等待器件地址發送完成
{
     if (++count > 6000) { //count大於6000立即返回
         I2C_CR2_bit.STOP = 1;
         return;
     }   
}    

 注意:

從Windows下上位機工具也可以進行TPS65987的register讀寫,TPS65981_2_6_7_8 Application Customization 6.1.1上顯示的i2c1地址為0x20, i2c2的地址為0x38;注意0x20/0x38是七位地址位的值,進行i2c讀寫時的地址要左移一位,即0x20/0x38 << 1等於0x40/0x70。

如果直接用地址0x20/0x38進行讀寫會怎么樣呢,結果就是地址發過去沒收到ACK。下圖是用0x38地址去讀寄存器值的時候示波器抓到的波形(黃色波形是SCL,紫色波形是SDA)。

 從波形上看0x38地址發過去是沒有ACK的,所以slave地址0x38肯定是錯誤的了。

后面用示波器量了一下TPS65981_2_6_7_8 Application Customization 6.1.1上位機軟件和TPS65987 EVM進行i2c讀寫時的波形,發現i2c2的地址發過去的確實是0x70。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM