基於STM8的IIC協議通信


一、 綜述

  I2C(IIC,Inter-Integrated Circuit),兩線式串行總線,由PHILIPS公司開發用於連接微控制器及其外圍設備。

  它是由數據線SDA和時鍾SCL構成的串行總線,可發送和接收數據。在CPU和被控IC之間、IC與IC之間進行雙向傳送,高速IIC總線一般可達400kbps以上。但在STM8中,400kHZ已經是最快速度了。

       在往后的模塊調試中也經常涉及,是一個很常見並且很好用的協議。

二、STM8S103中手冊對I2C簡介

 

 

 

 

 

 看完中文資料手冊,個人覺得比較淺顯,具體使用在后面我會貼出來。

 

三、 I2C詳細解析

I2C總共由五個核心函數,分別為:

①起始信號

②停止信號

③應答信號

④發送數據

⑤接收數據

 

通過這五個核心基本函數就能於大多數的傳感進行通信了。

以下對各個部分進行詳細介紹,附上部分主要代碼,各位可以參考一下。

 

3.1 起始信號

當SCL為高電平期間,SDA由高電平到低電平的跳變過程;起始信號是一種電平跳變時序信號,而不是一個電平信號,如上圖虛線框所。

void Start_Signal_IIC_(void){
  
  //起始信號:
  GPIO_WriteHigh(GPIOD, GPIO_PIN_2);//數據線
  IIC_Delay_4us();
  GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//時鍾線
  IIC_Delay_4us();
  GPIO_WriteLow(GPIOD, GPIO_PIN_2); //數據線
  IIC_Delay_4us();
  GPIO_WriteLow(GPIOD, GPIO_PIN_3); //時鍾線
  IIC_Delay_4us();
}

  

3.2 停止信號

當SCL為高電平期間,SDA由低電平到高電平的跳變過程;停止信號也是一種電平跳變時序信號,而不是一個電平信號,如上圖虛線框所。

void End_Data_IIC_()
  {
    GPIO_WriteLow(GPIOD, GPIO_PIN_2); //數據線拉低
    IIC_Delay_4us();
    GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//時鍾線拉高
    IIC_Delay_4us();
    GPIO_WriteHigh(GPIOD, GPIO_PIN_2);//數據線拉高
}

  

3.3 應答信號

 

 

 

應答信號有兩種:分別是主動應答信號和主動不應答信號

①Ack(主動拉低SDA形成應答信號)

 I2C總線的數據都是以字節(8位)的方式傳送的,發送器件每發送一個字節之后,在時鍾的第9個脈沖期間釋放數據總線,由接收器發送一個  ACK(把數據總線的電平拉低)來表示數據成功接收。

//主動應答信號
void vIIC_Ack() { GPIO_WriteLow(GPIOD, GPIO_PIN_2); IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); }

 

②NAck(主動不拉低SDA不形成應答信號)

在時鍾的第9個脈沖期間發送器釋放數據總線,接收器不拉低數據總線表示一個NACK,NACK有兩種用途:

a. 一般表示接收器未成功接收數據字節;

b. 當接收器是主控器時,它收到最后一個字節后,應發送一個NACK信號,以通知被控發送器結束數據發送,並釋放總線,以便主控接收器發送一個停止信號STOP。

//主動不應答
void vIIC_NAck()
{
  GPIO_WriteHigh(GPIOD, GPIO_PIN_2);
  IIC_Delay_4us();
  GPIO_WriteHigh(GPIOD, GPIO_PIN_3);
  IIC_Delay_4us();
  GPIO_WriteLow(GPIOD, GPIO_PIN_3);
  IIC_Delay_4us();
}

 ③ReadAck(等待應答信號)

    該信號在主機發送完數據后等待從機應答時候使用。

 u8 bIIC_ReadACK()
  {
    GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);//將SDA改為輸入模式。
    GPIO_WriteHigh(GPIOD, GPIO_PIN_3);               //拉高時鍾線。
    IIC_Delay_4us();  
    if(IIC_SDA_R != 0)
       {
         //低 有應答
         GPIO_WriteLow(GPIOD, GPIO_PIN_3);
         IIC_Delay_4us();
         GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);//SDA
         return 1;
       }
     else
        //高 無應答
       {
        GPIO_WriteLow(GPIOD, GPIO_PIN_3);
        IIC_Delay_4us();
        GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);//SDA
        return 0;
       }
  }

  

3.4 發送數據

在發送起始信號后開始通信,主機發送一個8位數據。然后,主機釋放SDA線並等待從從機發出得確認信號(ACK)。

void Send_Data_IIC_(uint8_t Data){
    int i;
//拉低數據線和時鍾線 GPIO_WriteLow(GPIOD, GPIO_PIN_3); GPIO_WriteLow(GPIOD, GPIO_PIN_2); for(i=0;i<8;i++) { if(Data&0x80) GPIO_WriteHigh(GPIOD, GPIO_PIN_2); else GPIO_WriteLow(GPIOD, GPIO_PIN_2); Data= Data<<1; IIC_Delay_2us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_2us(); } }

  

3.5 接收數據

在發送起始信號后開始通信,主機發送一個8位數據。然后,從機收到數據返回一個確認信號(ACK)給主機,這時候主機才開始接收數據,待主機接收數據完成后,發送一個NACK信號給從機,以通知接收端結束數據接收。

//接收函數
uint8_t uIIC_RecvByte()
{
  uint8_t i,uReceiveByte = 0;
  GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
  for(i=0;i<8;i++)
  {
  
    uReceiveByte <<= 1;
    IIC_Delay_4us();
    GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//高時鍾線時讀取數據電平
    IIC_Delay_4us();
    if(IIC_SDA_R !=0 )
    {
      uReceiveByte|=0x01;
    }
    IIC_Delay_4us();
    GPIO_WriteLow(GPIOD, GPIO_PIN_3);
    IIC_Delay_4us();
  }
  
   GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);
   return uReceiveByte;
}

  

 

 

3.6 I2C通信總過程

 

以下圖完美地詮釋了iic從接收到發送全過程中,SDA和SCL線的變化線。綜合上面的解釋和過程代碼,這張圖可以幫助記憶和理解。

 

 

 

四、例程

 

4.1 編譯環境:

        這里用的是IAR進行編譯,較為好用,后期使用STM32的開發板可以推薦使用CUBE直接生成初始化函數,與Keil5相互搭配使用,很是方便。

4.2 主芯片:

  我的主芯片是STM8S系列中的103,其中STM8S的003、005、和103、105,配置一樣(外設和CPU頻率,FLASH),在代碼相同的情況下均可進行燒寫。

4.3 代碼&解析

       iic代碼可以驅動幾乎市面上的所有時鍾模塊,所以這里的代碼可以與時鍾模塊的代碼相互調用。每個函數我都有加以解釋,可以詳細了解一下。

      看了上面的代碼也可以知道,這個協議是由數據線和時鍾線,數據發送接收要求拉高數據線或拉低時鍾線。所以這里推薦直接使用庫函數的拉高低,如果要方便的話,再加個宏定義可以更加直觀方便。

 

五、結尾

以上是iic的核心函數,對於每個函數我已經寫的很清楚,下一篇博客我會將基於iic的時鍾模塊的傳感通信博客貼出來,各位可以繼續閱讀下一篇博客做一下參考。


免責聲明!

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



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