開發板:mini2440
內核 :linux2.6.32.2
參考 :韋東山畢業班I2C視頻教程
1、i2c協議簡要分析
i2c中線是一種由 PHILIPS 公司開發的串行總線,用于連接微控制器及其外圍設備,它具有以下特點。
1、只有兩條總線線路:一條串行數據線SDA,一條串行時鐘線SCL。
2、每個連接到總線的器件都可以使用軟件根據它的唯一的地址來確定。
3、傳輸數據的設備之間是簡單的主從關系。
4、主機可以用作主機發送器或者主機接收器。
5、它是一個真正的多主機總線,兩個或多個主機同時發起數據傳輸時,可以通過沖突檢測和仲裁來防止數據被破壞。
6、串行的8位雙向傳輸,位速在標準模式下可達 100kbit/s,在快速模式下可達400kbit/s,在高速模式下可待3.4Mbit/s。
7、片上的濾波器可以增加抗干擾能力,保證數據的完整性。
8、連接到同一總線上的IC數量只受到總線的最大電容400Pf的限制。
如上圖所示,啟動一個傳輸時,主機先發送一個S信號,然后發送8位數據。這8位數據的前7位為從機地址,第八位表示傳輸的方向(0表示寫,1表示讀),如果有數據則繼續發送,最后發出P信號停止。
信號類型:
注意:正常數據傳輸時,SDA 在 SCL 為低電平時改變,在 SCL 為高電平時保持穩定。
開始信號 S 信號:
SCL 為高電平時,SDA由高電平向低電平跳變,開始傳送數據。
結束信號 P 信號:
SCL 為高電平時,SDA由低電平向高電平跳變,結束傳送數據。
響應信號 ACK:
接收器在接收到8位數據后,在第9個時鐘周期,拉低 SDA 電平
注意:在第9個時鐘周期,發送器保持SDA為高,如果有ACK,那么第9個時鐘周期SDA為低電平,如果沒有為高電平,發送器根據電平高低分辨是否有ACK信號。
如果使能了IIC中斷,發送完8bit數據后,主機自動進入中斷處理函數,此時SCL被發送器拉低,讓接收器被迫等待。恢復傳輸只需要清除中斷掛起。
2、 s3c2440 讀寫流程
1、設置傳輸模式 IICSTAT[7-6],我們做實驗與AT24C08通信時,2440作為主機,因此只用到主機發模式和主機收模式。
2、寫入從機地址到 IICDS[7-1],此時IICDS[7-1]位表示從機地址,第0位不關心。如 AT24C08 為 0xA0(最低位寫0了,發送到數據線上的7位地址的后邊以為才表示收發,這里雖然寫0但并不是根據這里的0來真正發送的)。
3、寫 0xF0(寫) 或 0xB0(讀)到 IICSTAT 寄存器, 高兩位表示 傳輸模式前邊設置過了,設置IICSTT[5-4] 為 11,使能傳輸,發送S信號。
4、IIC控制器自動將第2步中設置的 IICDS[7-1] 再根據 傳輸模式 補充 IICDS[0]位,發送出去。
5、進入第9個時鐘周期,此時,從機決定是否發出ACK信號,主機進入中斷,判斷是否收到ACK信號,以及是否繼續傳輸。
繼續發送:
1、將數據寫入 IICDS
2、清除中斷掛起,SCL時鐘恢復,IICDS的數據被自動發送到 SDA 線上,回到第5步。
停止發送:
1、寫 0xD0(寫) 和 0x90(讀) 到 IICATAT ,IICATAT[7-6]還是表示的傳輸模式,IICATAT[5-4] == 0 1,發送停止信號
2、清除中斷掛起,SCL時鐘恢復,發出停止信號
3、延時,等待停止信號發出
3、 AT24C08 讀寫分析
1、寫過程
寫過程與2440芯片的里的寫流程相一致,按照流程寫就OK
2、讀過程
讀過程是由2440芯片里的一個寫流程加一個讀流程組合而成,其中寫流程結束沒有發出P信號,而是直接發出了S信號開始讀流程,也就是我為什么加了一道紅線的原因。
附上一份簡單的裸機程序,僅供參考:基于MINI2440
#include
#include "s3c2440.h"
void Delay(int time);
#define WRDATA (1)
#define RDDATA (2)
typedef struct tI2C {
unsigned char *pData; /* 數據緩沖區 */
volatile int DataCount; /* 等待傳輸的數據長度 */
volatile int Status; /* 狀態 */
volatile int Mode; /* 模式:讀/寫 */
volatile int Pt; /* pData中待傳輸數據的位置 */
}tS3C24xx_I2C, *ptS3C24xx_I2C;
static tS3C24xx_I2C g_tS3C24xx_I2C;
/*
* I2C初始化
*/
void i2c_init(void)
{
GPEUP |= 0xc000; // 禁止內部上拉
/*
* AT24C08 兩根線 I2CSCL I2CSDA 與 2440芯片相連
* 配置2440 GPECON GPE15 GPE14引腳為I2C功能
*/
GPECON |= 0xa0000000; // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL
/* 開INT_IIC中斷 */
//INTMSK &= ~(BIT_IIC);
/* bit[7] = 1, 使能ACK
* bit[6] = 0, IICCLK = PCLK/16
* bit[5] = 1, 使能中斷
* bit[3:0] = 0xf, Tx clock = IICCLK/16
* PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz
*/
IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); // 0xaf
//IICADD = 0x10; // S3C24xx slave address = [7:1]
IICSTAT = 0x10; // I2C串行輸出使能(Rx/Tx)
}
void I_Write(unsigned int slvaddr, unsigned char addr, unsigned char data)
{
unsigned int ack;
// 寫從地址
IICSTAT |= 0x1<<6;//主機寫模式
IICSTAT |= 0x1<<7;
IICDS = slvaddr;//0xa0; //write slave address to IICDS
IICCON&=~0x10; //clear pending bit
IICSTAT = 0xf0; //(M/T start)
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
// 寫寄存器地址
IICDS = addr;
IICCON&=~0x10; //clear pending bit
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
// 寫數據
IICDS = data;
IICCON&=~0x10; //clear pending bit
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
// 發出停止信號
IICSTAT = 0xD0; //write (M/T stop to IICSTAT)
IICCON&=~0x10; //clear pending bit
while((IICSTAT & 1<<5) == 1);
}
unsigned char I_Read(unsigned int slvaddr, unsigned char addr)
{
unsigned char data = 1;
int ack;
// 寫從地址
IICSTAT |= 0x1<<6;//主機寫模式
IICSTAT |= 0x1<<7;
slvaddr = 0xA0;
IICDS = slvaddr;//0xa0; //write slave address to IICDS
IICCON&=~0x10; //clear pending bit
IICSTAT = 0xf0; //(M/T start)
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
// 寫寄存器地址
IICDS = addr;
IICCON&=~0x10; //clear pending bit
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
// 寫從地址(讀模式)
slvaddr = 0xA1;
IICSTAT &= ~(0x1<<6);//主機接受模式
IICSTAT |= 0x1<<7;
IICDS = slvaddr;
IICCON&=~0x10; //clear pending bit
IICSTAT = 0xb0; //(M/R Start)
while((IICCON & 1<<4) == 0);//udelay(10);//uart_SendByte('o');//ack period and then interrupt is pending::
// 讀數據
data = IICDS;
//IICCON&=~0x10; //clear pending bit
IICCON = 0x2f; //清掛起狀態,并設置無應答
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
data = IICDS;
//IICCON&=~0x10; //clear pending bit
IICCON = 0x2f; //清掛起狀態,并設置無應答
while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending
IICSTAT = 0x90;
IICCON = 0xaf;
//IICCON &= ~0x10; //clear pending bit
while((IICSTAT & 1<<5) == 1);
return data;
}
4、adapter驅動程序
這里,我們主要分析驅動里的發送核心算法,至于注冊中斷,IO內存映射,設置寄存器不在討論。
static int xxx_i2c_xfer(struct i2c_adapter *adpap, struct i2c_msg *msg,int num)
這個算法函數的作用就是將上層封裝好的一些i2c_msg 進行解析,將數據寫入寄存器,發送出去。在設備驅動層,我們使用了類似i2c_smbus_write_byte 等函數,類似的函數有很多,它們的作用就是封裝i2c_msg 結構(比如讀和寫的 msg 肯定不一樣,讀一個字節和讀多個字節也不一樣),然后調用 i2c_smbus_xfer_emulated->i2c_transfer,最終調用到我們的xxx_i2c_xfer函數進行傳輸。通過分析i2c_smbus_xfer_emulated函數,我們可以了解i2c_msg是如何封裝的。下面,我們簡單分析一下,知道最上層想干什么,我們才能知道實現哪些底層的功能不是。
struct i2c_msg {
__u16 addr; //從機地址
__u16 flags;
__u16 len; // buf 里 有多少個字節
__u8 *buf; // 本 msg 含有的數據,可能是1個字節,可有可能是多個字節
};
此函數,省略了很多內容,舉例分析而已~,細節請看源碼
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
unsigned short flags,
char read_write, u8 command, int size,
union i2c_smbus_data * data)
{
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ?2:1; // 寫操作兩個Msg 讀操作一個msg 這和我們前面分析AT24c08是一致的
struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
};
msgbuf0[0] = command; // 從機地址右移1位得到的,比如AT24C08 為 0x50
switch(size) {
case I2C_SMBUS_BYTE_DATA: // 單字節讀寫
if (read_write == I2C_SMBUS_READ)
msg[1].len = 1;
/*
* 讀:
* msgbuf0[0] = command
* msg[1].len = 1 ,數據會讀到 msgbuf0[1] 里
*/
else {
msg[0].len = 2;
msgbuf0[1] = data->byte;
/*
* 寫:
* msgbuf0[0] = command
* msgbuf0[1] = data->byte
*/
}
break;
}
status = i2c_transfer(adapter, msg, num);
}
上面代碼跟我們分析AT24C08的時候如出一轍,對于一個寫操作,我們只需要一個2440的寫流程對應于這里的一個Msg,然而對于讀操作,我們需要2440的兩個流程,對應于這里的兩個Msg。那么,我們底層控制器驅動需要做的工作就是,取出所有的Msg,將每一個Msg里buf里的數據發送出去,如果有下一個Msg, 那么再將下一個Msg里的buf發送完畢,最后發出P停止信號。還有一點,每發送一個Msg都要先發出S開始信號。
在看adapter程序之前,我們先來簡單思考一下,發出S開始信號之后,可能有以下3中情況:
1、當前msg.len == 0 ,如果有ACK直接發出stop信號。這種情況出現在,控制器枚舉設備的時候,因為它只發送S信號以及設備地址,不發送數據。
2、根據msg->flags 為 I2C_M_RD 等信息判斷讀寫,msg->flags 最低位為1表示讀,最低位為0表示寫。
#define I2C_M_TEN0x0010 /* this is a ten bit chip address */
#define I2C_M_RD0x0001 /* read data, from slave to master */
上一篇:i2c驅動程序全面分析,從adapter驅動程序到設備驅動程序
下一篇:Linux ARMv7中斷向量表搬移(2)
推薦閱讀
史海拾趣
GPD Optoelectronics Corp公司發展故事
故事一:初創與鍺晶體管的誕生
GPD Optoelectronics Corp.(前身為Germanium Power Devices Corp.)成立于1973年,最初專注于高品質鍺晶體管的制造。在那個半導體技術剛剛起步的年代,鍺晶體管作為重要的電子元件,在電子行業中占據著舉足輕重的地位。公司憑借其精湛的工藝和嚴格的質量控制,迅速在市場中站穩了腳跟,為后續的光電二極管業務打下了堅實的基礎。
故事二:轉型為光電二極管制造商
進入1980年代,隨著光電技術的快速發展,GPD Optoelectronics Corp.敏銳地捕捉到了市場趨勢,開始逐步轉型為光電二極管制造商。1980年,公司成功推出了Ge pn探測器產品,標志著其正式進入光電領域。這一轉型不僅拓寬了公司的業務范圍,也為其后續在光電領域的深入發展奠定了技術基礎。
故事三:InGaAs探測器的研發與推廣
為了進一步滿足市場對高性能光電探測器的需求,GPD Optoelectronics Corp.在1993年推出了InGaAs探測器產品。InGaAs探測器以其優異的光譜響應范圍和靈敏度,在光通信、光譜學等領域得到了廣泛應用。公司的這一舉措不僅鞏固了其在光電領域的領先地位,也為其贏得了更多客戶的青睞。
故事四:產能擴大與技術創新
進入21世紀,GPD Optoelectronics Corp.繼續保持著強勁的發展勢頭。2000年,公司搬遷至新罕布什爾州塞勒姆的新工廠,產能實現了翻倍增長。同時,公司不斷加大研發投入,推出了多款創新產品,如擴展波長InGaAs探測器、可定制的雙色探測器以及InGaAs象限光電二極管等。這些產品的推出不僅豐富了公司的產品線,也進一步提升了其市場競爭力。
故事五:表面貼裝封裝選項的引入
隨著電子產品的不斷小型化和集成化,GPD Optoelectronics Corp.緊跟市場趨勢,于2019年增加了表面貼裝封裝選項。這一舉措使得公司的光電二極管產品更加符合現代電子產品的設計要求,進一步拓寬了其在智能手機、平板電腦等消費電子領域的應用市場。同時,公司也繼續致力于為客戶提供量身定制的定制零件服務,以滿足不同客戶的特定需求。
意華在發展過程中,積極拓展國內外市場,與華為、中興、富士康等知名企業建立了長期穩定的合作伙伴關系。這些合作伙伴的加入,不僅為意華帶來了更多的訂單和業務機會,也促進了公司技術的交流和提升。通過與這些行業巨頭的合作,意華在電子連接器領域的影響力逐漸擴大。
近年來,ETA Electric Industry Co Ltd積極響應全球環保倡議,致力于實現可持續發展。他們優化了生產流程,減少了廢棄物和污染物的排放。同時,公司還加大了對環保型電子元器件的研發力度,推出了一系列節能、環保的新產品。這些舉措不僅提升了公司的社會形象,也為其在激烈的市場競爭中增添了新的優勢。
上述五個故事,講述了ETA Electric Industry Co Ltd在電子行業的發展歷程。從起步之初的艱難,到技術創新的突破,再到市場拓展和質量管理的成功,最后到對環保和可持續發展的追求,每一步都體現了公司的成長和進步。
隨著市場的擴大,Dynawave面臨著產品質量管理的挑戰。為了確保產品的穩定性和可靠性,公司決定引入國際先進的質量管理體系。他們聘請了專業的質量管理團隊,對生產流程進行嚴格的監控和把控。同時,公司還加大了對員工的培訓力度,提高了員工的質量意識。這些措施有效地提升了產品的質量水平,增強了客戶的信任度。
為了加速技術的商業化進程,Fractus積極尋求與全球領先企業的合作。自2000年以來,公司陸續與多家知名手機廠商、電信運營商以及設備制造商建立了戰略合作關系。這些合作不僅為Fractus帶來了穩定的收入來源,也促進了其技術的廣泛應用和持續改進。同時,Fractus還通過簽訂全球許可協議和建立戰略伙伴關系,進一步拓展了其業務范圍和市場影響力。
keil arm的代碼開發可能很復雜,但是其軟件的工程化其實不僅僅是編寫代碼,還包括了編寫文檔、軟件測試、第三方獨立測試等。 其過程主要如下: 1 編寫軟件的需求; 3 編寫軟件開發計劃; 4 編寫軟件代碼; 5 程序員的代碼走讀; 6 程 ...… 查看全部問答∨ |
數字用戶線接入復用器(DSLAM)是xDSL的局端設備。隨著xDSL業務在固網市場的迅速普及,DSLAM技術也在發展,本文旨在對目前的一個熱點問題-IP DSLAM技術進行探討。 一、IP DSLAM產生的背景 傳統的DSLAM是一個完全的ATM架構的設備, ...… 查看全部問答∨ |
前段時間幫朋友做電表用到了這個東東,今天正好無聊,況且這個網站的交流氣氛這么好,現在我把液晶這部分整理出來做了個測試小程序帖上來,以備大家急用。 這款液晶不如網站上那些點陣LCD的功能強大、應用靈活,但是在做些小產品的時候還是非常適 ...… 查看全部問答∨ |
|
永磁交流伺服電機的編碼器相位為何要與轉子磁極相位對齊 其唯一目的就是要達成矢量控制的目標,使d軸勵磁分量和q軸出力分量解耦,令永磁交流伺服電機定子繞組產生的電磁場始終正交于轉子永磁場,從而獲得最佳的出力效果,即“類直流特性”,這種控 ...… 查看全部問答∨ |
|
請教各位大俠,有沒有免費的能在PDA上實現局域網點點通話的軟件,謝謝! 請教各位大俠,有沒有免費的能在PDA上實現局域網點點通話的軟件,謝謝! PDA操作系統為Mobile6.0 局域網內通話,不需要連接外網,Skepe軟件必須連接外網才能通話,比較郁悶~… 查看全部問答∨ |
|