IIC EEPROM讀取解析
1. 編譯錯誤處理(這里可以忽略)
在解壓包解壓了程序后,直接編譯,出現如下錯誤。
*** WARNING L14: INCOMPATIBLE MEMORY MODEL
MODULE: .\EZUSB.LIB (RESUME)
MODEL: SMALL
*** WARNING L14: INCOMPATIBLE MEMORY MODEL
MODULE: .\EZUSB.LIB (DISCON)
MODEL: SMALL
*** WARNING L14: INCOMPATIBLE MEMORY MODEL
MODULE: .\EZUSB.LIB (EZREGS)
MODEL: SMALL
*** WARNING L14: INCOMPATIBLE MEMORY MODEL
MODULE: .\EZUSB.LIB (GET_STRD)
MODEL: SMALL
*** ERROR L102: EXTERNAL ATTRIBUTE MISMATCH
SYMBOL: PSTRINGDSCR
MODULE: .\EZUSB.LIB (GET_STRD)
*** WARNING L14: INCOMPATIBLE MEMORY MODEL
MODULE: .\EZUSB.LIB (DELAY)
MODEL: SMALL
*** ERROR L107: ADDRESS SPACE OVERFLOW
SPACE: CODE
SEGMENT: ?C_INITSEG
LENGTH: 16BFH
*** ERROR L107: ADDRESS SPACE OVERFLOW
SPACE: CODE
SEGMENT: ?C_INITSEG
LENGTH: 16BFH
*** ERROR L120: CONTENT BELONGS TO ERRONEOUS SEGMENT
SEGMENT: ?C_INITSEG
MODULE: periph.obj (PERIPH)
*** ERROR L118: REFERENCE MADE TO ERRONEOUS EXTERNAL
SYMBOL: PSTRINGDSCR
MODULE: .\EZUSB.LIB (GET_STRD)
ADDRESS: 0B27H
*** ERROR L118: REFERENCE MADE TO ERRONEOUS EXTERNAL
SYMBOL: PSTRINGDSCR
MODULE: .\EZUSB.LIB (GET_STRD)
ADDRESS: 0B29H
*** ERROR L120: CONTENT BELONGS TO ERRONEOUS SEGMENT
SEGMENT: ?C_INITSEG
MODULE: firmware.obj (FIRMWARE)
*** ERROR L119: REFERENCE MADE TO ERRONEOUS SEGMENT
SEGMENT: ?C_C51STARTUP
MODULE: E:\SOFTWAREINSTALL\PROJECT\KEIL_FOR_51\C51\LIB\C51L.LIB (?C_INIT)
ADDRESS: 0838H
*** ERROR L120: CONTENT BELONGS TO ERRONEOUS SEGMENT
SEGMENT: ?C_INITSEG
MODULE: E:\SOFTWAREINSTALL\PROJECT\KEIL_FOR_51\C51\LIB\C51L.LIB (?C_INIT)
面對錯誤,首先是百度了下,甚至還翻牆google,好多說是keil為不完全版本,只能編譯2kB的程序,超出會報錯overflow,給出的方案是
方案一:下載完整版keil,重裝試一下。
方案二:對圖 1中的箭頭位置進行修改,在這里看出,方案一不適用。

圖 1 修改配置
按照方案二試着修改(各種實驗修改)配置后,warming消除了,但是對error沒有什么卵用。后來發現圖 2中所示的Device沒有選對。

圖 2 選擇設備
修改圖 2中的設備,選為CY7C68013×××-×后,還要在圖 2中的可選項Use Extended Linker(LX51) instead of BL51選中,這樣就可以編譯通過了。
但是吧,這個雖然編譯通過了,但是程序好像是錯誤的。因為通過0xED vendor command進行讀取EEPROM的數據時,提示錯誤!
我之前用的是歷程中已經解壓的程序,后來講例程中的壓縮包程序解壓后,編譯直接通過,上面兩處錯誤(設備和選項)沒有改,下進了CY7C68013A中后,通過0xED vendor command進行讀取EEPROM時,會有數據返回,雖然返回的不是預期的,再查證。
2. 程序解析
首先初始化:TD_init();
然后是設備描述符的相關處理;
接着是循環執行:TD_Poll()函數,在這個函數里,往IIC接口的EEPROM里面寫入數據(寫入是一次寫一個),同時在EEPOM里面讀出數據(讀出是一次將寫入的3個同時讀出),並存入到寄存器中。
在循環函數中,檢測控制傳輸令牌包的到來,一旦接收到令牌包,就會將存放IIC讀書數據的寄存器中的數傳到主機。
3. 運行錯誤處理
這個程序可以直接用。並且將1錯誤處理中的device改為CY7C68013和option選上了。
其實PDF(CE63180)文檔里面已經寫得非常詳細。
就是在上電之前,將EEPROM的跳線帽拔下來,不讓他在EEPROM中啟動,這樣PC才可以識別到設備,上電后,下載程序前將跳線帽插上,這樣在下載了程序后,會自動的往EEPROM中寫數據。
在PC的上位機軟件中做如圖 3配置,點擊Vend Req按鈕,即可讀取程序自動寫入EEPROM中的數據。但是不知道是沒有寫入,還是讀取不成功,返回來的數據都是00,00,00 ,顯然,這是不正確的。經過示波器測試IIC的數字信號,發現發出的都是10100000。再結合IIC的通信協議,發現這是發送的IIC 芯片的地址。讀出來的數據時00,00,00是因為程序是按照官方的開發板寫的,但是淘寶的開發板和官方的有點區別。圖 3和圖 4對比所示。由兩個不同IC(24LC00和24L128)的datasheet可以看出,他們IIC地址的前4為均為1010,后面三位由電平決定。圖 3中A2,A1,A0均為0,所以地址為1010_0000(0xA0)。而淘寶開發板的A0被拉高,所以地址為1010_0010(0xA2)。因為用的是淘寶的開發板,所以這里要修改。
在程序中Periph.c文件中有一個宏定義:#define EEPROM_ADDR 0x50,這個宏在TD_init()函數中賦值給了IIC地址:I2C_Addr = EEPROM_ADDR;
因為在寫地址時,先把地址左移一位(I2DAT = I2C_Addr << 1),所以這里的宏定義為地址的右移一位值:0x50 = 0xA0 >> 1。
由於使用了淘寶貨,這里沒有改的話,就不能往EEPROM中寫入數據,也不能讀取,所以返回來的是00,00,00,如圖 5。這里要在程序中將宏的值改為EEPROM地址的右移一位值:0x51 = 0xA2 >> 1。
圖 3 官方開發板原理圖

圖 4 淘寶開發板原理圖

圖 5 上位機的配置
進行了如上修改之后,再次燒錄,讀取。發現讀出來的數據不正確如圖 6所示,用示波器測試,發現現在不只是發送0xA0那么簡單了,具體是什么也沒有細究。
接下來繼續看程序。在圖 7所示的TD_init()中的注釋引起了注意,DB_Addr = 1 if the EEPROM is double byte addressing(雙字節尋址)

圖 6 修改地址后的讀取值

圖 7 TD_init()函數
將TD_init()中的DB_Addr = 0改為DB_Addr = 1后,下載讀取,可以實現將TD_Poll()中寫入EEPROM中的數據讀出來並返回到host。如圖 8所示

圖 8 讀取正確數據
通過此實驗可以證明,開發板上用的ATMEL的24C128 EEPROM是雙字節尋址。下了數據手冊,看數據手冊,在第7頁的Device addressing中,如圖 9所示,但是這里的8bit是device addressing,是IIC的地址,不是我們寫入和讀取的存儲空間的地址。所以不是看這里。
圖 9 datasheet 的描述
接着往下看,在第8頁和第9頁中,寫入時序和讀取時序分別如圖 10和圖 11所示,可以明確看出,前面方框中的device address與上面的描述對應,橢圓中的word address分為了1st,2nd兩個字節byte,為double byte addressing(雙字節尋址),可以與24LC00 datasheet中的時序圖作對比,發現它是單字節尋址,因此官方例程中的DB_Addr = 0。完美解決。睡
圖 10 寫入時序

圖 11 讀取時序
此問題的解決,也是通過翻牆,在google搜索中,搜到的別人的答案。連接為:https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=17590
在連接中有啟發的回答為圖 12所示

圖 12 有啟示的回答
