原創(chuàng)聲明:
本原創(chuàng)教程由芯驛電子科技(上海)有限公司(ALINX)創(chuàng)作,版權(quán)歸本公司所有,如需轉(zhuǎn)載,需授權(quán)并注明出處(http://www.alinx.com)。
適用于板卡型號:
PGL22G/PGL12G
1. 實(shí)驗(yàn)簡介
本實(shí)驗(yàn)通過使用開源軟件opencores上的I2C master控制器去控制I2C接口的EEPROM讀寫,練習(xí)如何有效的使用開源代碼提升開發(fā)效率。
2. 實(shí)驗(yàn)原理
2.1 硬件電路
在開發(fā)板上,FPGA芯片通過I2C總線連接EEPROM 24LC04, I2C的兩根總線各上拉一個4.7K的電阻到3.3V,所以當(dāng)總線上沒有輸出時會被拉高, 24LC04的寫保護(hù)沒有使能,不然FPGA會無法寫入數(shù)據(jù)。因?yàn)樵陔娐飞螦0~A2都為低,所以24LC04的設(shè)備地址為0xA0。
開發(fā)板部分電路
2.2 I2C的總線協(xié)議和時序
I2C標(biāo)準(zhǔn)速率為100kbit/s,快速模式400kbit/s,支持多機(jī)通訊, 支持多主控模塊,但同一時刻只允許有一個主控。由數(shù)據(jù)線SDA和時鐘SCL構(gòu)成串行總線; 每個電路和模塊都有唯一的地址。
在這里以AT24C04為例說明I2C讀寫的基本操作和時序,I2C設(shè)備的操作可分為寫單個存儲字節(jié),寫多個存儲字節(jié),讀單個存儲字節(jié)和讀多個存儲字節(jié)。各個操作如下圖所示。
下面對I2C總線通信過程中出現(xiàn)的幾種信號狀態(tài)和時序進(jìn)行分析。
①總線空閑狀態(tài)
I2C總線總線的SDA和SCL兩條信號線同時處于高電平時,規(guī)定為總線的空閑狀態(tài)。此時各個器件的輸出級場效應(yīng)管均處在截止?fàn)顟B(tài),即釋放總線,由兩條信號線各自的上拉電阻把電平拉高。
②啟動信號(Start)
在時鐘線SCL保持高電平期間,數(shù)據(jù)線SDA上的電平被拉低(即負(fù)跳變),定義為I2C總線總線的啟動信號,它標(biāo)志著一次數(shù)據(jù)傳輸?shù)拈_始。啟動信號是由主控器主動建立的,在建立該信號之前I2C總線必須處于空閑狀態(tài),如下圖所示。
③停止信號(Stop)
在時鐘線SCL保持高電平期間,數(shù)據(jù)線SDA被釋放,使得SDA返回高電平(即正跳變),稱為I2C總線的停止信號,它標(biāo)志著一次數(shù)據(jù)傳輸?shù)慕K止。停止信號也是由主控器主動建立的,建立該信號之后,I2C總線將返回空閑狀態(tài)。
④數(shù)據(jù)位傳送
在I2C總線上傳送的每一位數(shù)據(jù)都有一個時鐘脈沖相對應(yīng)(或同步控制),即在SCL串行時鐘的配合下,在SDA上逐位地串行傳送每一位數(shù)據(jù)。進(jìn)行數(shù)據(jù)傳送時,在SCL呈現(xiàn)高電平期間,SDA上的電平必須保持穩(wěn)定,低電平為數(shù)據(jù)0,高電平為數(shù)據(jù)1。只有在SCL為低電平期間,才允許SDA上的電平改變狀態(tài)。
⑤應(yīng)答信號(ACK和NACK)
I2C總線上的所有數(shù)據(jù)都是以8位字節(jié)傳送的,發(fā)送器每發(fā)送一個字節(jié),就在時鐘脈沖9期間釋放數(shù)據(jù)線,由接收器反饋一個應(yīng)答信號。應(yīng)答信號為低電平時,規(guī)定為有效應(yīng)答位(ACK簡稱應(yīng)答位),表示接收器已經(jīng)成功地接收了該字節(jié);
應(yīng)答信號為高電平時,規(guī)定為非應(yīng)答位(NACK),一般表示接收器接收該字節(jié)沒有成功。對于反饋有效應(yīng)答位ACK的要求是,接收器在第9個時鐘脈沖之前的低電平期間將SDA線拉低,并且確保在該時鐘的高電平期間為穩(wěn)定的低電平。
如果接收器是主控器,則在它收到最后一個字節(jié)后,發(fā)送一個NACK信號,以通知被控發(fā)送器結(jié)束數(shù)據(jù)發(fā)送,并釋放SDA線,以便主控接收器發(fā)送一個停止信號。
3. 程序設(shè)計(jì)
I2C時序雖然簡單,但是寫的不好也會出現(xiàn)很多問題,在開源網(wǎng)站http://opencores.org/上我們可以找到很多非常好的代碼,這些代碼大部分都提供詳細(xì)的文檔和仿真。俗話說,他山之石,可以攻玉,恰當(dāng)?shù)氖褂瞄_源代碼,不光能提升我們的開發(fā)效率,也能學(xué)習(xí)別人的開發(fā)思路。由于代碼大部分都是經(jīng)過很長時間反復(fù)修改,反復(fù)精煉后的,所以有些代碼理解起來可能比較困難,在不能很好的理解別人代碼的時候,最好的辦法就是仿真。
從IP core文檔得知,i2c_master_byte_ctrl模塊主要完成一個字節(jié)的讀寫,我們只需要按照I2C讀寫的要求,完成設(shè)備地址、寄存器地址、數(shù)據(jù)等讀寫即可。
i2c_master_top模塊是對i2c_master_byte_ctrl模塊的再次封裝,完成一個寄存器的讀寫,由于不同的設(shè)備寄存器可能是8bit,也可能是16bit,這里i2c_addr_2byte信號來控制寄存器地址是8位還是16位。
i2c_master_top模塊狀態(tài)機(jī),如果是寫寄存器操作,先寫一個字節(jié)設(shè)備地址(寫操作),再寫1個字節(jié)或2個字節(jié)的寄存器地址,再寫一個字節(jié)的數(shù)據(jù);如果是讀操作,先寫一個字節(jié)的設(shè)備地址(寫操作),再寫1個字節(jié)或2字節(jié)的寄存器地址,完成地址的寫入,再次寫設(shè)備地址(讀操作),然后讀取一個字節(jié)的數(shù)據(jù)。不管怎么說,程序設(shè)計(jì)都是要滿足芯片時序要求的,所以在閱讀程序之前最好先把芯片的數(shù)據(jù)手冊仔細(xì)閱讀一遍。
i2c_master_top狀態(tài)機(jī)
信號名稱 | 方向 | 說明 |
clk | in | 時鐘輸入 |
rst | in | 異步復(fù)位輸入,高復(fù)位 |
clk_div_cnt | in | I2C時鐘分頻因子,等于系統(tǒng)時鐘頻率/(5 * I2C時鐘頻率) - 1。例如50Mhz系統(tǒng)時鐘,100Khz的I2C,配置為99,400Khz的I2C,配置為24。 |
scl_pad_i | in | I2C時鐘數(shù)據(jù)輸入,本實(shí)驗(yàn)可忽略 |
scl_pad_o | out | I2C時鐘輸出 |
scl_padoen_o | out | I2C時鐘輸出使能,低有效,I2C外部有上拉電阻,如果輸出高阻態(tài),則會被拉到高電平,在本實(shí)驗(yàn)中,高電平輸出時輸出高阻 |
sda_pad_i | in | I2C數(shù)據(jù)輸入 |
sda_pad_o | out | I2C數(shù)據(jù)輸出 |
sda_padoen_o | out | I2C數(shù)據(jù)輸出使能,低有效。在本實(shí)驗(yàn)中,高電平輸出時輸出高阻。 |
i2c_addr_2byte | in | 寄存器地址是8位還是16位,1:16位,0:8位 |
i2c_read_req | in | I2C寄存器讀請求 |
i2c_read_req_ack | out | I2C寄存器讀請求應(yīng)答 |
i2c_write_req | in | I2C寄存器寫請求 |
i2c_write_req_ack | out | I2C寄存器寫請求應(yīng)答 |
i2c_slave_dev_addr | in | I2C設(shè)備地址,8bit,最低位忽略,有效數(shù)據(jù)位是高7位。 |
i2c_slave_reg_addr | in | 寄存器地址,8位地址時,低8位有效 |
i2c_write_data | in | 寫寄存器數(shù)據(jù) |
i2c_read_data | out | 讀寄存器數(shù)據(jù) |
error | out | 設(shè)備無應(yīng)答錯誤 |
i2c_master_top模塊端口
i2c_eeprom_test模塊完成EEPROM的讀寫,EEPROM設(shè)備地址是A0,程序中將地址00的數(shù)據(jù)讀出,然后通過LED顯示,在KEY2 按下時,數(shù)字加一并再次寫入EEPROM并顯示出來。在I2C控制器中,代碼的大部分功能在備注中也有很多批注。
4. 實(shí)驗(yàn)現(xiàn)象
下載實(shí)驗(yàn)程序后,可以看到LED顯示一個二進(jìn)制數(shù)字,這個數(shù)字是存儲在EEPROM中00地址的數(shù)據(jù),數(shù)據(jù)是隨機(jī)的,這個時候按鍵KEY2按下,數(shù)字加一,并寫入了EEPROM,再次下載程序,可以看到直接顯示更新后的數(shù)據(jù)。
5. 使用在線調(diào)試Fabric Debugger觀察信號
使用Fabric Debugger可以非常直觀的看到程序在開發(fā)板上運(yùn)行時各個信號的變化,在本例程中添加一個Debug Core來觀察程序運(yùn)行時各數(shù)據(jù)線的變化情況。
按紅色標(biāo)記,在單擊“Inserter":
在彈出如下界面下選擇New DebugCore Unit來新建一個Debug Core:
單擊U0:DebugCore:
會跳到參數(shù)設(shè)置界面,在"Trigger Parameters"欄中Sample Depth采樣深度自己根據(jù)需求選擇,這里選擇默認(rèn),其它的設(shè)置保持不變。
在"Net Connections"欄中選擇Modify Connections,進(jìn)行Net修改;
彈出的界面中首先對TriggerPort欄中觀測信號關(guān)聯(lián),在這里,選擇左側(cè)read_data,然后單擊Make Connections,可以在TriggerPort欄中看到關(guān)聯(lián)的觀測信號read_data;
以同樣的方式對Clock欄中時鐘信號關(guān)聯(lián),選擇左側(cè)sys_clk_c,然后單擊Make Connections,可以在Clock欄中看到關(guān)聯(lián)的觀測信號sys_clk_c,然后單擊OK;
再在如下界面中單擊保存按鈕進(jìn)行保存并關(guān)閉即可。
接下來重新生成.sbit文件,雙擊Generate Bitstream,會生成帶有在線調(diào)試的DebugCore。
上面的工作準(zhǔn)備好后,接下來才是正式開始調(diào)試, 單擊Debugger(確保開發(fā)板上電并連接了下載器),
單擊JTAG 掃描按鈕,在找到后單擊OK;
右擊DEV:0MyDevice0,在下拉菜單中單擊Configure Bitstream File
再按如下圖中進(jìn)行設(shè)置,設(shè)置完成后按OK鍵;
到此,程序已下載到FPGA 中,可以在線觀察所需要的信號,選擇 Waveform,選擇觸發(fā)模式為連續(xù),并單擊run;
可以看到read_data數(shù)據(jù),每按一次KEY2鍵運(yùn)行一次可以看到數(shù)據(jù)增加1。
-
FPGA
+關(guān)注
關(guān)注
1625文章
21625瀏覽量
601248 -
EEPROM
+關(guān)注
關(guān)注
9文章
1008瀏覽量
81336 -
開源
+關(guān)注
關(guān)注
3文章
3218瀏覽量
42329 -
I2C接口
+關(guān)注
關(guān)注
1文章
124瀏覽量
25106 -
紫光同創(chuàng)
+關(guān)注
關(guān)注
5文章
79瀏覽量
27475
發(fā)布評論請先 登錄
相關(guān)推薦
評論