【記錄】IIC

概要

IIC(IIC,inter-Integrated circuit),兩線式串行總線,用於MCU和外設間的通信。
IIC只需兩根線:數據線SDA和時鐘線SCL。以半雙工方式實現MCU和外設之間數據傳輸,速度可達400kbps。

多主機I2C總線結構

注意SDA和SCL兩根總線需要上拉,使總線處於空閒狀態。

這裏寫圖片描述

IIC協議

空閒狀態

協議規定,SDA和SCL同時爲高電平時,總線處於空閒狀態。上拉電阻保證電平處於高電平。

起始信號和停止信號

起始信號:SCL爲高電平時,SDA電平發生高到低的跳變
停止信號:SCL爲高電平時,SDA電平發生低到高的跳變

這裏寫圖片描述

應答信號

發送器每發送完一個字節(8個脈衝),在第9個脈衝間釋放總線,接收器返回一個ACK信號,協議規定,低電平爲有效應答,高電平爲無效應答。

這裏寫圖片描述

數據有效性

協議對有效數據進行了規定:即時鐘信號爲高電平期間,數據必須保持穩定,時鐘信號低電平期間,數據線上的電平才允許變化。也就是說,數據在時鐘信號到來前必須準備好,並保持到時鐘信號的下降沿之後。

這裏寫圖片描述

數據傳輸

I2C爲同步傳輸,時鐘控制數據位的傳輸,邊沿觸發。

驅動程序

直接引用實驗中的代碼。測試沒問題。

起始信號

//產生IIC起始信號
void IIC_Start(void)
{
    SDA_OUT();     //sda線輸出
    IIC_SDA=1;        
    IIC_SCL=1;
    delay_us(4);
    IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    delay_us(4);
    IIC_SCL=0;//鉗住I2C總線,準備發送或接收數據 
}   

停止信號

//產生IIC停止信號
void IIC_Stop(void)
{
    SDA_OUT();//sda線輸出
    IIC_SCL=0;
    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
    delay_us(4);
    IIC_SCL=1; 
    IIC_SDA=1;//發送I2C總線結束信號
    delay_us(4);                                
}

有效應答

//產生ACK應答
void IIC_Ack(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=0;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
}

無效應答

//不產生ACK應答          
void IIC_NAck(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=1;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
}   

發送單字節

//IIC發送一個字節
//返回從機有無應答
//1,有應答
//0,無應答           
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
    SDA_OUT();      
    IIC_SCL=0;//拉低時鐘開始數據傳輸
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1;      
        delay_us(2);   //對TEA5767這三個延時都是必須的
        IIC_SCL=1;
        delay_us(2); 
        IIC_SCL=0;  
        delay_us(2);
    }    
} 

接收單字節

//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA_IN();//SDA設置爲輸入
    for(i=0;i<8;i++ )
    {
        IIC_SCL=0; 
        delay_us(2);
        IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
        delay_us(1); 
    }                    
    if (!ack)
        IIC_NAck();//發送nACK
    else
        IIC_Ack(); //發送ACK   
    return receive;
}

EEPROM

24C02爲IIC接口,容量爲256字節。

封裝如下圖:

這裏寫圖片描述

管腳定義:

這裏寫圖片描述

設備地址的高四位固定,中間爲地址線定義的地址,最後一位爲讀寫位。
由於A0,A1,A2設置爲0,所以
讀的時候:Device Address = 0xA1;
寫的時候:Device Address = 0xA0;

這裏寫圖片描述

24C02字節寫時序

  1. 起始信號
  2. 寫設備地址,Device Address = 0xA0;
  3. 等待應答
  4. 確定寫入的EEPROM地址即WORD ADDRESS
  5. 等待應答
  6. 向SDA數據線上寫入數據DATA
  7. 等待應答
  8. 停止信號

這裏寫圖片描述

//在AT24CXX指定地址寫入一個數據
//WriteAddr  :寫入數據的目的地址    
//DataToWrite:要寫入的數據
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{                                                                                            
    IIC_Start();  
    if(EE_TYPE>AT24C16)
    {
        IIC_Send_Byte(0XA0);        //發送寫命令
        IIC_Wait_Ack();
        IIC_Send_Byte(WriteAddr>>8);//發送高地址   
    }else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //發送器件地址0XA0,寫數據   
    IIC_Wait_Ack();    
    IIC_Send_Byte(WriteAddr%256);   //發送低地址
    IIC_Wait_Ack();                                                        
    IIC_Send_Byte(DataToWrite);     //發送字節                             
    IIC_Wait_Ack();                    
    IIC_Stop();//產生一個停止條件 
    delay_ms(10);    
}

24C02字節讀時序

  1. 起始信號
  2. 寫設備地址,Device Address = 0xA0;
  3. 等待應答
  4. 確定寫入的EEPROM地址即WORD ADDRESS
  5. 等待應答
  6. 起始信號
  7. 讀設備地址,Device Address = 0xA1;
  8. 等待應答
  9. 讀SDA上數據
  10. 等待應答
  11. 停止信號

這裏寫圖片描述

//在AT24CXX指定地址讀出一個數據
//ReadAddr:開始讀數的地址  
//返回值  :讀到的數據
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{                 
    u8 temp=0;                                                                               
    IIC_Start();  
    if(EE_TYPE>AT24C16)
    {
        IIC_Send_Byte(0XA0);       //發送寫命令
        IIC_Wait_Ack();
        IIC_Send_Byte(ReadAddr>>8);//發送高地址      
    }else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //發送器件地址0XA0,寫數據      
    IIC_Wait_Ack(); 
    IIC_Send_Byte(ReadAddr%256);   //發送低地址
    IIC_Wait_Ack();     
    IIC_Start();           
    IIC_Send_Byte(0XA1);           //進入接收模式            
    IIC_Wait_Ack();  
    temp=IIC_Read_Byte(0);         
    IIC_Stop();//產生一個停止條件       
    return temp;
}

參考

STM32F3與 F4 系列 Cortex M4 內核編程手冊
STM32F4xxx中文參考手冊
STM32F4xxx英文參考手冊
STM32F4 開發指南(寄存器版)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章