LPC23XX之I2C使用總結
--- 原野之狼寫于2010年重陽節之時
近來由于項目需要,玩了玩LPC23XX系列的I2C,這么一個小小的東西費了我一周的時間,實在是令人崩潰!
首先要指出的是,原廠的LPC23XX的User Manual存在著嚴重的誤導作用,另外給的Sample程序也存在著誤導作用。很不幸,俺手頭上擁有的正好是這兩份資料,所以走了許多彎路。
關于I2C的官方Specification諸位最好先看看,我就提醒一點:I2C硬件上要求各I2C器件不管是作為Master還是作為Slave使用時都要采用OC或者OD模式作為IO接口,然后在外部用電阻上拉到電源,這樣才能使得當總線沖突時高電平和低電平不會互相拼個你死我活。目前Internet上的一些關于I2C的參考程序一般都是采用IO模擬I2C協議來實現的,這當然是可以的,但是記得要把MCU的IO口配置成OC、OD或者弱上拉模式,不要弄成推挽輸出哦。不過采用IO模擬方式比較占資源系統資源,本文描述的是采用MCU自帶的I2C控制器來實現。
LPC23XX支持3個I2C接口,這三者并不是完全一樣的,I2C0是嚴格遵守I2C協議的,而I2C1和I2C2并不嚴格遵守I2C協議,這體現在IO口的結構上,這點需要引起注意。
接下來說說User Manual的問題,我設置I2C控制器作為Master使用,并且是Single Master,外部掛了個RTC器件,因此本文的描述以此為前提條件。
User Manual關于I2C控制器的描述主要體現在這么一些資料:
資料1:狀態遷移圖Fig116和Fig117(P520~521)。
資料2:狀態表Table451和Table452(P452~453)。
資料3:關于軟件編寫指導性的文字描述(P533)。
這三者本來應該是關聯性很強并互為指導的的文檔資料,但是我看了好幾天都沒有明白寫的是啥子意思,無奈只好憑著感覺先把代碼寫完,然后一邊調試程序一邊對著資料看,旁邊還架上示波器來看波形。
關于資料3,諸位看個大概就行了,如果你按照這個細節去做估計會死得很慘。
關于資料2,這個資料倒是沒問題,但是得弄明白才行。
關于資料1,這個資料非常重要,但是很不好理解,要是沒有按照它所指定的路線操作就會出莫名其妙的問題。
先解讀一下資料1的Fig116,用以輔助理解,當然諸位首先得看看User Manual,要不然俺說了也是白說,解讀如下:
1、 程序設置S位到相關寄存器,控制器會嘗試著去獲得I2C的操作權,獲得特權后就會發送起始信號。
2、 成功完成起始信號的發送后控制器會產生中斷并返回0X08(注意不要理解錯了,此返回并不是指中斷程序返回,而是指控制器的狀態寄存器的信息,下同)。
3、 程序寫入SLA+W信息到相關寄存器。
4、 發送成功后會產生中斷并返回0X18。
5、 程序寫入要發送的數據到到相關寄存器。
6、 發送成功后會產生中斷并返回0X28。
7、 如果還要繼續發送請回到5,否則寫入P到相關寄存器。
8、 在7時,如果數據已經發送完但是并不想寫P以停止I2C操作,而需要繼續進行別的操作。舉個例子,比如在讀取RTC的時間信息時,先寫入要訪問的寄存器地址信息,然后在讀出數據信息,這是一個連貫的動作,并不需要插入P操作的,具體請查看RTC數據手冊。那么這個時候程序再次設置S位到相關寄存器,使得控制器發送起始信號。
9、 上一步再次發送S成功后會產生中斷并返回0X10。此時程序寫入SLA+R信息到相關寄存器。
10、 接下來就轉到了Fig117了。
接下來,解讀一下Fig117:
1、 程序設置S位到相關寄存器,控制器會嘗試著發送起始信號。
2、 成功完成起始信號的發送后控制器會產生中斷并返回0X08。
3、 程序寫入SLA+R信息到相關寄存器。
4、 發送成功后會產生中斷并返回0X40,注意Fig116第10條也就是這里的第4條。這個時候我們該做什么了呢,顯然是需要讀取數據。但是請注意,并不是現在就讀取數據,因為本條的0X40僅僅表示了SLA+R發送完畢了,我們想要的其它數據還在后頭呢,中斷程序退出后控制器才會產生時鐘去外部I2C器件那里取數據。
5、 如上所述,當讀取數據成功后控制器會產生中斷并返回0X50,這時就可以從控制器的數據寄存器拷貝數據了。根據I2C協議,此時主機還需要向從機提供應答信號,如果接下來還需要讀取數據,那么應答ACK,否則應答NO ACK。如果應答ACK,請繼續第5條,否則就是第6條的事情了。應答操作由程序完成。
6、 如果之前應答的是NO ACK,應答完后控制器會產生中斷并返回0X58。寫入P到相關寄存器完成此次I2C操作。
以上兩篇解讀僅以狀態遷移圖的主線為例,其它分支因為比較簡單所以沒有做解讀,編程的時候需要考慮其它分支情況。
關于資料1就說這么多,一定要先把這個狀態遷移圖搞明白,要不然會死得不明不白。資料1理解透了,看資料2就輕松許多了,無非是一些細節嘛。記住一條就是了,該設置的位要設置,該清除的位要清除,不能多也不能少,會帶來什么問題俺也不清楚,沒有逐個測試,調試的過程發現不正確的設置會導致狀態遷移不按規定的路徑走。
在調試的過程中可以通過跟蹤中斷程序中讀來的狀態碼來確定狀態遷移路徑,要是路徑不對多半就是俺在上一個段落中提到的原因了。還有一點尤其注意,有些I2C器件存在超時的問題,就是說一次完整的I2C操作(從S開始算起,以P作為結束)需要在規定的時間內完成,所以諸位千萬不要在中斷程序里設置斷點來觀察寄存器信息,除非你能保證你眼睛夠犀利手腳夠麻利能夠在超時時間之內完成想要做的事情。
OK,該打住了,就說這么多,不要向我要源代碼,不是本狼不夠OPEN,是因為俺自己都搞不到。
聯系我:y_y_z_l 愛她 163.com
版權聲明:歡迎轉載,但請保留本文的完整性。