第001節_I2C協議與EEPROM
I2C協議
I2C在硬件上的接法如下(圖19-1)所示,主控芯片引出兩條線SCL,SDA線,在一條I2C總線上可以接很多I2C設備,我們還會放一個上拉電阻(放一個上拉電阻的原因以后我們再說)。
我們怎么傳輸數據,我們需要發數據從主設備發送到從設備上去,也需要把數據從從設備傳送到主設備上去,數據涉及到雙向傳輸。
舉個例子:
體育老師:可以把球發給學生,也可以把球從學生中接過來。
1.發球:a.老師說:注意了(start)
b.老師對A學生說我要球發給你(地址)。
:: c.老師就把球發出去了(傳輸)。
:: d.A收到球之后,應該告訴老師一聲(回應)。
:: e.老師說下課(停止)
2.接球:
:: a.老師說注意了(start),
:: b.老師說:B把球發給我(地址)
:: c.B就把球發給老師(傳輸)
:: d.老師收到球之后,給B說一聲,表示收到球了(回應)。
:: e.老師說下課(停止)
我們就使用這個簡單的例子,來解釋一下IIC的傳輸協議。
* 老師說注意了,表示開始信號(start)
* 老師告訴某個學生,表示發送地址(address)
* 老師發球/接球,表示數據的傳輸
* 老師/學生收到球,回應表示:回應信號(ACK)
* 老師說下課,表示IIC傳輸接受(P)
IIC傳輸數據的格式
1.寫操作:
剛開始主芯片要發出一個start信號,然后發出一個設備地址(用來確定是往哪一個芯片寫數據),方向(讀/寫,0表示寫,1表示讀)。
回應(用來確定這個設備是否存在),然后就可以傳輸數據,傳輸數據之后,要有一個回應信號(確定數據是否接受完成),然后再傳輸下一個數據。
每傳輸一個數據,接受方都會有一個回應信號,數據發送完之后,主芯片就會發送一個停止信號。
:: 白色背景:主→從
:: 灰色背景:從→主
2.讀操作:
剛開始主芯片要發出一個start信號,然后發出一個設備地址(用來確定是從哪一個芯片讀取數據),方向(讀/寫,0表示寫,1表示讀)。
回應(用來確定這個設備是否存在),然后就可以傳輸數據,傳輸數據之后,要有一個回應信號(確定數據是否接受完成),然后在傳輸下一個數據。
每傳輸一個數據,接受方都會有一個回應信號,數據發送完之后,主芯片就會發送一個停止信號。
:: 白色背景:主→從
:: 灰色背景:從→主
傳輸是以8位為單元數據傳輸的,先傳輸最高位(MSB),主芯片發出start信號之后,然后發出9個時鐘傳輸數據。
(1)開始信號(S):SCL為高電平時,SDA山高電平向低電平跳變,開始傳送數據。
(2)結束信號(P):SCL為電平時,sDA由低電平向高電平跳變,結束傳送數據。
(3)響應信號(ACK):接收器在接收到8位數據后,在第9個時鐘周期,拉低SDA
SDA上傳輸的數據必須在SCL為高電平期間保持穩定,SDA上的數據只能在SCL為低電平期間變化。如圖
1.問題:如何在SDA上實現雙向傳輸?
答:主芯片通過一根SDA線既可以把數據發給從設備,也可以從SDA上讀取數據,連接SDA線的引腳里面必然有兩個引腳(發送引腳/接受引腳)。
2.問題:主設備(從設備)發送數據時,從設備(主設備)的發送引腳,不影響數據的發送,怎么做到呢?
答:里面放一個三極管,使用開極(極電集開發出去作為輸出)電路,如下圖
下面畫一個真值表:
從真值表和電路圖我們可以知道,當某一個芯片不行影響SDA線時,那就不驅動這個三極管。
想輸出高電平時;都不驅動(高電平就由上拉電阻決定)。
想輸出低電平,就驅動三極管。
從下面的例子可以看看數據是怎么傳的(實現雙向傳輸),比如:主設備發送(8bit)給從設備
1.前8個clk
* 從設備不要影響,從設備不驅動三極管;
* 主設備決定數據;
2.第9個clk,由從設備決定數據
* 主設備不驅動三極管;
* 從設備決定數據;
從上面的例子,就可以知道,怎樣在一條線上實現,雙向傳輸的辦法。這就是為什么在SDA,SCL上放上拉電阻的原因。
在第9個時鐘之后,如果有某一方處于繁忙狀態,它可以一直把SCL拉低當SCL為低電平時候,大家都不應該使用IIC總線,只有當SCL從低電平變為高電平的時候,IIC總線才能被使用。
從前圖我們也可以知道ACK信號應該是低電平。主設備不驅動三極管,如果從設備不驅動三極端的化SDA應該是高電平,當從設備接收數據之后,發出回應信號的時候,就會驅動三極管,讓SDA變為低電平。所以說:ACK信號是低電平。
對于IIC協議它只能規定怎么傳輸數據,數據什么含義它完全不能夠控制,數據的含義有從設備決定。
第002節_S3C2440的I2C控制器
在嵌入式系統里面的主控芯片一般都會有I2C控制器,要是沒有可以根據I2C協議用GPIO管腳模擬,但是非常麻煩,我們要發送數據時,可以把數據放到某個寄存器,它就會自動的發出時鐘,并且把數據發送給從設備,同時會等待從設備會返回回應信號。
當我們想發送一個數據的時候,要設置某個寄存器啟動傳輸,它也一樣會產生時鐘,然后從設備就會把數據通過SDA傳到I2C控制器里面,組裝進某個寄存器里面,最終寄存器會把接收到的8位數據返回給我們的程序,從這里可以看到I2C控制器簡化了I2C的操作。簡短電路連接圖,如圖:
根據上圖,我們首先設置IICCON(來設置時鐘),時鐘源是PCLK(是50MHZ)太快了我們需要設置這個分頻系數,把時鐘降低,降低到我們想要的SCL,然后我們要發出start信號,我們需要設置寄存器發出start信號,之后我們需要發出數據啊,我們的程序可以把數據寫入到IICDS寄存器,一寫入就會自動的發出時鐘,并且把這8位數據從SDA發送給從設備,數據發送之后,在第九個時鐘會收到回應信號,可以查詢IICSTAT是否有ACK(有ACK表示數據發送成功了),可以繼續發送數據,等發完數據之后,再來設置IICSTAT讓它發出P信號。
在第九個CLK,就會產生一個中斷,在中斷處理過程中SCL被拉為低電平,誰都不能再使用IIC總線,等待中斷處理完成.
怎樣處理中斷?
寫操作:
若無ACK,出錯,然后發出P信號結束,
:: 若有ACK信號表示上一個字節成功發送出去
:: 若仍有數據,寫入IICDS寄存器,然后清中斷,一清中斷就會釋放SCL信號,繼續發出時鐘,把數據再次發送出去。
:: 若沒有數據了,發出P信號結束。
讀操作:
讀到8位數時,應該回應一個ACK信號。
:: 還想讀數據,清中斷,啟動傳輸。等它再次發生中斷時,再來讀取IICDS寄存器,得到數據。不想讀取數據,發出P信號結束。
重點: 發生中斷時,我們的IIC控制器會把SCL拉低,阻止任何設備再使用IIC總線,清中斷之后才能繼續使用,這種機制就給我們中斷服務程序的執行提供了時間。
讀-寫操作
在發送模式:
:: 1.往寄存器IICDS寄存器放入一個val值。
:: 2.發完,產生中斷,并且會把 SCL拉低。
:: 3.在中斷程序里,判斷狀態,然后往IICDS里面寫入下一個數據,一旦寫入下一個數據IIC繼續操作,若再次發完,就會再次產生中斷。
在接受模式:
:: 1.我的程序發起傳輸,接受數據。
:: 2.接收到數據之后,產生中斷,SCL被拉低。
:: 3.中斷程序里,判斷數據是否要繼續接受等,如果還有繼續接受的話,再次設置,設置好之后讀IICDS寄存器,一但讀出來IIC。
:: 繼續接受下一個數據,收到新數據之后,又會產生一個中斷(就是這樣循環操作)。
(l)IICCON寄存器(Multi-masterIIC-buscontrol)
IICCON寄存器用于控制是否發出ACK信號、設置發送器的時鐘、開啟,i2c中斷,并標識中斷是否發生。它的各位含義如表:
使用IICCON寄存器時,有如下注意事項。
1.發送模式的時鐘頻率由位[6]、位[3:0]聯合決定,另外,llCCON[6]=0,IICCON[3:0]
不能取0或10
2.12c中斷在以下3種情況下發生:當發出地址信息或接收到一個從機地址并且吻合時,當總線仲裁失敗時,當發送/接收完一個字節的數據(包括響應位)時。
3.基于SDA、SCL線上時間特性的考慮,要發送數據時,先將數據寫入IICDS寄存器,然后再清除中斷。
4.如果IICCON[5]=0,IICCON14]將不能正常工作。所以,即使不使用12c中斷,也要將IICCON[5]設為1。
(2)IICSTAT寄存器(Multi-masterIIC-buscontrol/status)
IICSTAT寄存器用于選擇12c接口的工作模式,發出S信號、P信號,使能接收/發送功能,并標識各種狀態,比如總線仲裁是否成功、作為從機時是否被尋址、是否接收到0地址、是否接收到ACK信號等。IICSTAT寄存器的各位如表:
(3)IICADD寄存器(Multi-masterIlC-busaddress)
用到IICADD寄存器的位[7:11],表示從機地址。IICADD寄存器在串行輸出使能位
IICSTAT[4]為0時,才可以寫入:在任何時間都可以讀出。IICADD寄存器的各位如表:
(4)IICDS寄存器(Multi-masterIIC-busTx/Rxdatashift)
用到IICDS寄存器的位丨7:0],其中保存的是要發送或己經接收的數據。IICDS寄存器在串行輸出使能位IICSTAT()1為1時,叼可以寫入;在任何時間都可以讀出。IICDS寄存器的各位如表:
讀寫操作流程圖
主機發送器模式操作:
主機接收器模式操作:
第003節_程序框架
寫程序之前 考慮好程序的框架,我們想寫出一個結構比較好,比較容易擴展的程序
我們先要考慮清楚框架的設計。
IIC控制器的功能
IIC會做什么事情呢?
對于IIC控制器,它負責傳輸數據,不知道數據的含義,但是它要實現寫/讀操作
讀操作
寫操作
IIC設備的功能
很顯然,IIC控制器提供了傳輸數據的能力,至于數據有什么含義,IIC控制器并不知道,數據的含義有外接的IIC芯片決定,我們需要閱讀芯片手冊,才知道IIC控制器應該發出怎樣的數據,
AT24cxx的操作方法
顯然我們的程序應該分為兩層(IIC設備層,IIC控制器層),框架如下圖所示:
我們提供一個統一的接口i2c_transfer,不關使用哪個芯片,他最終都會調用i2c_transfer,來選擇某一款I2C控制器,把數據發送出去,或者從I2c設備讀到數據,對于每一次傳輸的數據都可以用一個i2c_msg結構體來表示。但是,讀某個地址的數據時,就要用兩個i2c_msg結構體來描述它,因為一個i2c_msg結構體只能描述一個傳輸方向(讀/寫),我們讀取ac24ccxx某個地址上的數據時,要先寫出要讀取的地址,然后來讀取設備地址上的數據。
我們想設計出以一個結構體比較容易擴展的框架,對于I2C控制器我們要抽象出一個結構體i2c_controller,我們構造這個結構體之后,把這個這個結構體,告訴上層(I2C控制器那一層),上層有個管理者i2c_contreller.c文件。
我們在s3c2440_i2c_controller.c這個文件中我們構造出一個i2c_controller結構體,把它放入上層文件中的數組里,以后就根據結構體的名字,把這個結構體取出來使用。
假設我們有一個TI的開發板,在ti_i2c_controller.c文件中,也要構造出一個i2c_controller結構體,同樣們也會把這個結構體放入上層的結構體數組(i2c_contreller.c文件中)中,以后根據名字先出來使用。
對于設備層中的at24cxx芯片我們寫出at24cxx.c文件在這個文件實現讀寫函數:
1.at24cxx_write函數
2.at24cxx_read。
函數讀寫函數都會調用i2c_transfer發起IIC傳輸,所以我們寫程序的時候主要的暫時會涉及到三個文件:
at24cxx.c, s3c2440_i2c_controller.c,i2c_contreller.c。在最上層會寫出一個i2c_test.c文件,它會提供菜單供我們選擇來測試。
下面我們寫一個程序框架,涉及到的文件有:i2c_test.c、at24cxx.c、i2c_controller.c、s3c2440_i2c_controller.c。
i2c_test.c文件
該文件的內容如下:
void i2c_test(void)
{
/* 初始化: 選擇I2C控制器 */
/* 提供菜單供測試 */
}
這個菜單最終會調用到at24cxx.c里面的函數。
at24cxx.c文件
在里面會使用標準的接口i2c_transfer來啟動I2C傳輸。該文件的內容如下:
int at24cxx_write(unsigned int addr, unsigned char *data, int len)
{
/* 構造i2c_msg */
/* 調用i2c_transfer */
}
int at24cxx_read(unsigned int addr, unsigned char *data, int len)
{
/* 構造i2c_msg */
/* 調用i2c_transfer */
}
i2c_controller.c文件
該文件的內容如下:
/* 有一個i2c_controller數組用來存放各種不同芯片的操作結構體 */
void register_i2c_controller()
{
}
/* 根據名字來選擇某款I2C控制器 */
void select_i2c_controller(char *name)
{
}
/* 實現 i2c_transfer 接口函數 */
int i2c_transfer(i2c_msg msgs, int num)
{
}
select_i2c_controller函數根據名字來選擇某款I2C控制器后,以后就會使用被選擇的I2C控制器來啟動傳輸。
有數組一定有注冊函數register_i2c_controller會把下面實現的I2C控制器結構體i2c_controller放到i2c_controller數組里面。
s3c2440_i2c_controller.c文件
對于具體的芯片,要實現自己的i2c_controller。該文件的內容如下:
/* 實現i2c_controller
.init
.master_xfer
.name
*/
第004節I2C控制器編程框架
我們現在來講I2C控制器怎么寫,它是I2C程序中最核心的地方,我們要先構造幾個結構體,這幾個結構體放在i2c_controller.h里面。
我們要發出I2c傳輸時,要構造出i2c_msg,把構造出的i2c_msg扔給下面的i2c_controller.c,i2c_controller.c會選擇某一個i2c控制器,使用里面的master_xfer來傳輸數據, 所以我們需要構造出一個i2c_controller結構體。
i2c_controller.h文件
文件的內容如下所示:
#ifndef _I2C_CONTROLLER_H
#define _I2C_CONTROLLER_H
typedef struct i2c_msg {
unsigned int addr; /* 7bits */
int flags; /* 0 - write, 1 - read */
int len;
int cnt_transferred;
unsigned char *buf;
}i2c_msg, *p_i2c_msg;
typedef struct i2c_controller {
int (*int)(void);
int (*master_xfer)(i2c_msg msgs, int num);
char *name;
}i2c_controller, *p_i2c_controller;
#endif /* _I2C_CONTROLLER_H */
解析:我們構造這兩個結構體,我們要把它放在i2c_controller.c把它用起來,
i2c_controller.c文件
文件的內容如下所示:
include "i2c_controller.h"
#define I2C_CONTROLLER_NUM 10
/* 有一個i2c_controller數組用來存放各種不同芯片的操作結構體 */
static p_i2c_controller p_i2c_controllers[I2C_CONTROLLER_NUM];
static p_i2c_controller p_i2c_con_selected;
void register_i2c_controller(p_i2c_controller *p)
{
int i;
for (i = 0; i < I2C_CONTROLLER_NUM; i++)
{
if (!p_i2c_controllers[i])
{
p_i2c_controllers[i] = p;
return;
}
}
}
解析:register_i2c_controller函數用于把參數中的結構體指針,注冊到p_i2c_controllers指針數組中。
/* 根據名字來選擇某款I2C控制器 */
int select_i2c_controller(char *name)
{
int i;
for (i = 0; i < I2C_CONTROLLER_NUM; i++)
{
if (p_i2c_controllers[i] && !strcmp(name, p_i2c_controllers[i]->name))
{
p_i2c_con_selected = p_i2c_controllers[i];
return 0;
}
}
return -1;
}
解析:select_i2c_controller函數根據參數中的名字(name) 從p_i2c_controllers指針數組中取出對應的結構體指針復制給p_i2c_con_selected結構體指針(靜態全局變量)。
/* 實現 i2c_transfer 接口函數 */
int i2c_transfer(i2c_msg msgs, int num)
{
return p_i2c_con_selected->master_xfer(msgs, num);
}
解析:i2c_transfer接口函數,調用選擇的p_i2c_con_selected成員中master_xfer函數。
void i2c_init(void)
{
/* 注冊下面的I2C控制器 */
s3c2440_i2c_con_add();
/* 選擇某款I2C控制器 */
/* 調用它的init函數 */
}
解析:s3c2440_i2c_con_add()函數,把定義的s3c2440_i2c_con結構體注冊到p_i2c_controllers數組中。
s3c2440_i2c_controller.c文件
中斷服務函數,當發成中斷是,就會調用中斷服務函數,代碼如下
void i2c_interrupt_func(int irq)
{
/* 每傳輸完一個數據將產生一個中斷 */
/* 對于每次傳輸, 第1個中斷是"已經發出了設備地址" */
}
s3c2440_i2c_con_init函數,用來初始化I2C,控制器代碼如下:
void s3c2440_i2c_con_init(void)
{
/* 設置時鐘 */
/* [7] : IIC-bus acknowledge enable bit, 1-enable in rx mode
* [6] : 時鐘源, 0: IICCLK = fPCLK /16; 1: IICCLK = fPCLK /512
* [5] : 1-enable interrupt
* [4] : 讀出為1時表示中斷發生了, 寫入0來清除并恢復I2C操作
* [3:0] : Tx clock = IICCLK/(IICCON[3:0]+1).
* Tx Clock = 100khz = 50Mhz/16/(IICCON[3:0]+1)
*/
IICCON = (0<<6) | (1<<5) | (30<<0);
/* 注冊中斷處理函數 */
register_irq(27, i2c_interrupt_func);
}
解析:
1).IICCON = (0<<6) | (1<<5) | (30<<0); 設置IICCON控制寄存器。選擇發送時鐘,使能中斷。
2).register_irq(27, i2c_interrupt_func):注冊中斷處理函數,當發生I2C中斷的時候就會調用i2c_interrupt_func中斷處理函數。
初始化完成后,就可以調用do_master_tx寫I2C從機了,這個函數僅僅啟動I2C傳輸,然后等待,直到數據在中斷服務程序中傳輸完畢后再返回。函數代碼如下:
void do_master_tx(p_i2c_msg msg)
{
msg->cnt_transferred = 0;
/* 設置寄存器啟動傳輸 */
/* 1. 配置為 master tx mode */
上一篇:ARM裸板程序及引申_點亮LED
下一篇:第001課 不要再用老方法學習單片機和ARM
推薦閱讀
史海拾趣
機頂盒,全稱數字視頻變換盒(Set Top Box,簡稱STB),是連接電視機與外部信號源的關鍵設備。它不僅能接收來自有線電纜、衛星天線、寬帶網絡及地面廣播的數字電視信號,還能將這些信號轉換成適合電視機播放的格式,極大地豐富了電視節目的選擇,提升了觀看體驗。
從技術層面看,機頂盒具備強大的媒體處理能力和交互功能。它能接收高清乃至4K的超高清電視節目,并通過內置的解碼器將數字信號轉換為電視可識別的視頻和音頻流,實現細膩的畫面和震撼的音效。此外,機頂盒還支持數據廣播、電子節目指南(EPG)、因特網接入、視頻點播等多種增值服務,使電視機成為了一個互動的智能終端。
隨著技術的不斷進步,機頂盒正朝著高清化、智能化方向發展。智能化技術如人工智能(AI)的集成,使機頂盒具備了語音助手、智能推薦等功能,為用戶提供了更為便捷、智能的使用體驗。同時,云計算和邊緣計算技術的應用,也進一步提升了內容分發和管理的效率。
綜上所述,機頂盒作為連接電視與外部世界的橋梁,不僅是現代家庭娛樂不可或缺的一部分,也是推動數字電視技術發展的重要力量。隨著技術的持續進步和市場需求的不斷增長,機頂盒的未來將更加豐富多彩,為用戶提供更加優質、便捷的觀影體驗。
背景:此故事基于假設存在一個專注于超級計算機研發的FRONTIER公司。
發展故事:近年來,隨著大數據和人工智能技術的飛速發展,超級計算機在科研、工業等領域的應用越來越廣泛。FRONTIER Supercomputing作為該領域的佼佼者,成功研發出了世界上首臺突破百億億次計算瓶頸的超級計算機——Frontier。該計算機以其卓越的性能和廣泛的應用價值,在多個領域取得了突破性成就,如太空探索、氣候建模、基因組學等。Frontier的成功不僅為公司贏得了國際聲譽,也為全球科技進步貢獻了重要力量。
Chesivale Electronics公司自成立以來,一直致力于電子技術的研發與創新。在早期,公司面臨市場競爭激烈、技術瓶頸等重重困難。然而,公司的研發團隊堅持不懈,最終成功研發出一款具有劃時代意義的芯片技術。這款芯片不僅性能卓越,而且成本大大降低,迅速在市場上獲得了廣泛的認可。這一技術突破為Chesivale Electronics公司贏得了大量的訂單和市場份額,也為公司的后續發展奠定了堅實的基礎。
在發展過程中,貝爾金也通過收購其他公司來增強自身實力。例如,2013年貝爾金正式完成對Linksys的收購,這一舉措進一步豐富了其產品線,并加強了在網絡設備領域的競爭力。此外,貝爾金還通過不斷整合內部資源,優化生產流程,提高產品質量和效率。
隨著公司的逐步發展,Everbuild開始注重技術研發和品牌建設。公司投入大量資金引進先進的生產設備和技術人才,不斷推出具有創新性的電子產品。其中,一款高性能的智能手機處理器在市場上引起了熱烈反響,成為公司的明星產品。同時,Everbuild還加強了品牌宣傳和推廣,提高了品牌的知名度和美譽度。
安路科技始終將技術創新作為公司發展的核心驅動力。公司不斷加大研發投入,引進高端人才,建立了一支具有強大研發實力的團隊。通過持續的技術創新,安路科技在FPGA領域取得了多項重要突破,推出了多款具有領先水平的產品,進一步鞏固了公司在市場中的地位。
windows下面,我們在一個目錄或文件上點擊右鍵,顯示屬性,里面有一項是“創建快捷方式...” 請問,如果我也想做wince下面實現這樣的功能,該怎么做呢? 自己開發代碼?如何開發?有沒有一個什么思路? 或者添加什么組件? 謝謝… 查看全部問答∨ |
求助:我是研二的學生,導師讓寫篇關于嵌入式的論文,自己搜索了一下,也沒找到什么合適的方向 如題,我比較菜,沒怎么編過程,本科就是混過來的。現在想把論文完成就行了,不知道哪一塊還是比較好寫的,希望高手指點。導師的意思是我只要能完成,要買什么工具了不用擔心,不要太貴就可以。… 查看全部問答∨ |
程序: flaot a,b,c,d,e; a=123.4; b=234.5 c=345.6; d=456.7; e=a*b*c*d; 計算運行e=a*b*c*d; 28335 用FPU&nbs ...… 查看全部問答∨ |
本帖最后由 ddllxxrr 于 2016-1-7 16:56 編輯 剛畢業,現在生活上出現困境,賣個板子解決下吃飯問題。各位看官嘴下留情哈。板子買了主要就是為了做畢業設計。做完了就閑置了。F107的芯片,具體的參數還有配件可以看淘寶。我也是淘寶天貓買的,加上 ...… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 顛覆iToF技術,安森美如何突破30米深度感知極限?
- 利用驗證框架 JAIST揭示開源自動駕駛系統的安全漏洞
- 現代汽車集團擬采用VR模擬器替代道路測試 提升未來車型的競爭力
- 研究人員開發光驅動致動器 可用于驅動水下機器人
- 吉利將發射“千里浩瀚”衛星,實現輔助駕駛系統與衛星功能深度融合
- 以鴻道工業操作系統為核心 打造工業智能機器人新生態
- UNIST研發出新表面處理技術 延長下一代鋰金屬電池的壽命
- 車載SerDes芯片行業的"DeepSeek"時刻——瑞發科HSMT SerDes閃耀2025上海車展
- 豐田顛覆傳統,固態電池明年就能量產,最受傷的將是中國?
- 基于恩智浦與onsemi的駕駛員監控系統方案