標籤:
概要
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位元組寫時序
- 起始訊號
- 寫裝置地址,Device Address = 0xA0;
- 等待應答
- 確定寫入的EEPROM地址即WORD ADDRESS
- 等待應答
- 向SDA資料線上寫入資料DATA
- 等待應答
- 停止訊號
//在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位元組讀時序
- 起始訊號
2.寫裝置地址,Device Address = 0xA0;
- 等待應答
- 確定寫入的EEPROM地址即WORD ADDRESS
- 等待應答
- 起始訊號
- 讀裝置地址,Device Address = 0xA1;
- 等待應答
- 讀SDA上資料
- 等待應答
- 停止訊號
//在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 開發指南(寄存器版)
【記錄】IIC