I2C由SDA在收發資料,由SCL來傳送資料的Clock,Clock讓I2C傳送端與接收端可以
同步,每一個Clock代表一個bit。如下圖,TM320320F28335包含了control、status、
interrupt等暫存器,讓使用者可以藉由設置或讀取這這些暫存器來客制化I2C功能。
I2C發送與接收
當CPU要從SDA資料線傳送資料出去,是將資料寫入I2CDXR,I2CDXR會再將資料
轉到I2CXSR後,發送中斷信號XRDY,讓CPU知道資料已經被發送出去。
CPU要從SDA接收資料,資料是先被存到I2CRSR,在I2CRSR將資料更新到I2CDRR
後,發出中斷信號RRDY,讓CPU知道I2C module接收到新的資料,可以去讀取。
I2C Clock設定
當TMS320F28335被設為I2C Master,要設置I2C SCL的Clock頻率,從下圖Figure 3
看到從Device input clock經過PLLCR,再到I2C Moudle IPSC、ICCL/ICC這三個除
頻器,最後產生出Master clock做為SCL的clock。TMS320F28335支援I2C頻率
10K~400KHz,為了要符合這個頻率區間,Moudule clock需要在7-12MHz。
在設定IPSC時,I2CMDR裡的IRS要設為"0"(reset state),如果在IRS為"1"時,修
改IPSC是無效的。
Master clock公式
要得到Tmst(Master clock period),就要先得到Tmod(module clockperiod)、ICCL
、ICCH與d的值。而module clock由input clock除以 (IPSC+1)得出。另外d (delay)
的值如Table 15, 可以得知與IPSC的值有關,為5、6、7其中之1。
IPSC由暫存器I2CPSC.bit7:0來設定,範圍是 0~255。當IPSC設為"0",就表示
module clock=I2C input clock。在TI的Example code裡,I2C input clock有100MHz
、150MHz兩種設定,為了讓Module clock降到10MHz,符合7~12MHz的範圍,
在I2C input clock為100MHz時,就設IPSC為9,在150MHz時,設IPSC為14。
再來因為IPSC>1,所以d(delay)=5。
Tmod周期時間為module clock的倒數,Tmmod=1/10MHz=0.1us,再設置ICCL與
ICCH就可以得到Tmst。在TI的Example code裡,設置ICCL=10, ICCH=5,代入
公式,可以得到Tmst=Tmod x [(10+5) + (5+5)]=0.1us x 25= 2.5us,最後得出
Master clock= 1/ Tmst= 400KHz。
從Figure22可以看到,Tmst是Tmod所計算出來的。
I2C中斷事件
I2C有7個中斷事件,在Figure13可以看到,每個中斷事件,可以由I2CIER去設置
enable/disable,被設為disable的中斷事件,在事件發生時,就不會去通知CPU。
I2CSTR(I2C status register)裡面所對應的bit會會被設"1"。
XRDYINT:用來通知CPU,原來I2CDXR內資料已經傳送出去,可以再寫入新的
資料到I2CDXR。這個中斷不適用於FIFO模式。
RRDYINT:用來通知CPU,I2CDRR接收到新的資料,CPU可以來讀取。這個中
斷不適用於FIFO模式。
ARDYINT:當I2C Port做為Master,ARDYINT用來通知CPU,前一段I2C命令已
終止,可以再寫入新的命令到I2C module register。
NACKINT:當I2C Port做為Master,在傳送資料給接收端,接收端要在ACK/NACK
bit將SDA訊號下拉,來表示ACK,有接收到資料。如果接收端沒反
應ACK,NACKINT就會被SET,通知CPU,接收端沒接收到資料。
ALINT:Arbitration-lost為仲裁丟失,當I2C BUS上有兩個或多個I2C Master,企圖
去發送資料時,但I2C Bus上,只能有一個Master,所以需要去仲裁是那個
I2C Master搶到發言權。在TMS320F28335的I2C Master Port沒搶到發信權,
ALINT就會被SET來通知CPU,並由I2C Master轉為Slaver。
SCDINT:在I2C傳送資料的最後,會有個Stop bit,讓I2C Bus上其他的I2C Module在
,在偵測到這個stop事件,可以知道資料傳送結束,否則I2C Bus就是在
busy狀態。SCDINT用來通知CPU,有Stop condition被偵測到。
AASINT:當I2C Port做為Slave,在I2C Bus上接收到另一個I2C Master發送出來位址
資料是這個I2C Port所設定的Slave位址(I2COAR),也就是這個命令是要
傳給自已的 ,則ASSINT會被SET,通知CPU,要去接收後面由I2C Master
傳來的資料。
I2C相關暫存器
I2COAR:設置在做為Slaver時的address位址。
I2CIER:用來設置那些中斷是有效的。
I2CSTR:用來判斷I2C的狀態,其中有些暫存器要寫入"1"來清除狀態旗標。
I2CCLKL/I2CCLKH:用來設置I2C Master clock的周期時間與頻率。
I2CCNT:用來設置I2C Master是要傳多少Byte或接收傳輸多少Byte的data。
I2CDRR:CPU讀取這個暫存器來接收另一端傳送來的資料。
I2CSAR:在做為I2C Master,設置I2CSAR來設定要操作的Slave address。
I2CMDR:控制I2C進入Start、Stop、Nack、Repeak、Reset等模式,在I2C
收發資料的過程中,需要去設定I2CMDR裡面的bits。
I2CISRC:CPU在收收到中斷通知後,會先讀取I2CISRC來得知是那個
中斷事件發生,再去執行對應的處理程序。讀完I2CISRC後,
在I2CSTR內的Flag會被清除,但I2CSTR的ARDY、RRDY、
XRDY是需要寫入"1"去清除的。
I2CDXR:CPU寫入資料到這個暫存器,來傳送資料給另一端。
I2CEMDR:設置BCM (Backwards compatibility mode),在做為Slave端
並在發送資料時,BCM設置為"0" or "1"會影響I2CSTR
暫存器裡XRDY, XSMT的動作方式。
I2CPSC:設置I2C input clock的除頻多少來轉為I2C module clock。
I2CFFTX/I2CFFRX:在FIFO模式下,TX與RX的控制與狀態暫存器。
void I2CA_Init(void)
{
// Initialize I2C
I2caRegs.I2CMDR.all = 0x0000; //將I2C模式設為Reset/Disable mode
I2caRegs.I2CFFTX.all = 0x0000; // 將FIFO模式關閉,Reset FFTX。。
I2caRegs.I2CFFRX.all = 0x0040; // Reset FFRX, FFRX中斷功能關閉。
#if (CPU_FRQ_150MHZ) // 當CPU頻率(SYSCLKOUT)為150MHz,就設置
I2caRegs.I2CPSC.all = 14; // PSC為14,module clk (150/15 = 10MHz)
#endif
#if (CPU_FRQ_100MHZ) //當CPU頻率(SYSCLKOUT)為150MHz,就設置
I2caRegs.I2CPSC.all = 9; //PSC為9,module clk (100/10 = 10MHz)
#endif
I2caRegs.I2CCLKL = 10; // 注意:不能設為"0"
I2caRegs.I2CCLKH = 5; // 注意:不能設為"0"
I2caRegs.I2CIER.all = 0x24; // 啟動SCD與ARDY中斷的偵測
I2caRegs.I2CMDR.all = 0x0020; // 設置I2C peripheral(裝置)離開Reset mode,
//可以接收Host在I2C Bus發送的命令。
//可以接收Host在I2C Bus發送的命令。
I2caRegs.I2CFFTX.all = 0x6000; // 啟動I2C FIFO模式與TX FIFO運作。
I2caRegs.I2CFFRX.all = 0x2040; // 動作 RXFIFO,清除RXFFINT旗標。
return;
}
Reference:
1.TI TMS320x2833x, 2823x Inter-Integrated Circuit (I2C) Module Reference Guide (Rev. B)