I2C總線是Philips公司在八十年代初推出的一種串行、半雙工的總線,主要用于近距離、低速的芯片之間的通信。本篇文章首先從理論講起,介紹了英飛凌TC3x系列芯片對應MCAL中對I2C驅動的定義與介紹,建議讀者在閱讀本篇文章之前對I2C有個簡單的認識,協議本身比較簡單,筆者就不在文章中贅述了。文章后邊主要介紹了I2c的EB配置,如果是異步則需要配置中斷和回調函數。文章的最后還是老樣子給讀者介紹了I2C驅動的調試代碼和測試結果,因為本系列是基于KIT_A2G_TC397XA_TFT開發板做的調試,所以就直接使用了開發板上接的MCP79411芯片來驗證I2C是否調通。PS:關于MCP79411芯片的一些I2C參數要求都源自其芯片手冊,文中就不截相關的圖了。
目錄
概述
依賴模塊?
I2C
SCU
Port
SRC
環境與目標
EB tresos配置
MCU
Port?
I2C?
General
I2cChannelconfiguration
IRQ
I2C驅動調試
測試代碼
測試結果
概述
MCAL實現的I2c驅動程序負責初始化I2c硬件模塊。它還提供將數據寫入從機并從從機讀取數據的服務,實現方式支持同步(數據傳輸不會發生中斷調用)和異步(數據將通過中斷調用傳輸)的讀寫操作模式。MCAL實現的I2c驅動程序不支持從機模式。
該驅動程序支持:
- 主機模式
- 標準模式數據傳輸速率高達100k bit/s(20k bit/s~100k bit/s)
- 快速模式數據傳輸速率高達400k bit/s(100k bit/s~400k bit/s)
- 7位I2c總線尋址
模塊軟硬件接口如下圖所示。
依賴模塊?
I2C
12C驅動程序使用的I2C硬件單元的關鍵特性有:
- 主機模式
- 標準模式數據傳輸速率高達100k bit/s(20k bit/s~100k bit/s)
- 快速模式數據傳輸速率高達400k bit/s(100k bit/s~400k bit/s)
- 7位I2c總線尋址
- I2C時鐘的預分頻器(從0到255)
- 通過分數除法器生成比特率
驅動使用的硬件事件包括(涉及的大寫標志位相關寄存的位域名稱):
- 發送/接收完成時的TX_END標志。
- 從發送模式切換到接收模式時的RX標志。
- LSREQ_INT,SREQ_INT,LBREQ_INT,BREQ_INT標志,用于用確定的數據數填充FIFO。
- 傳輸和接收過程中出現錯誤時的錯誤標志。
SCU
kernel_clk由來自fl2C的MCU驅動程序設置。內核時鐘對于保持l2C協議指定的比特率是必需的。
interface_clk直接連接到fSPB。interface_clk需要驅動FIFO、SFR和服務請求塊。
SCU模塊為所有外圍設備提供時鐘。MCU驅動程序負責時鐘樹的配置。
I2C驅動程序依賴于MCU驅動程序進行時鐘生成。fI2C定義了I2C核心的應用時鐘頻率。從PLL2(200MHZ)導出的fI2C獨立于fSPB,允許I2C以恒定的波特率(頻率)運行。此配置可以使用Tresos中MCU模塊中的Mcul2Cfrequency完成。頻率需要在MCU模塊配置參數McuClockRefSelection中簡歷對應引用,而McuClockRefSelection最終由Tresos中的I2C配置引用。
Port
I2C外圍設備的SCL、SDA引腳的方向和模式選擇由Port驅動器配置。PORT驅動程序配置整個微控制器的端口引腳。用戶必須在調用I2C初始化之前通過PORT配置引腳,并初始化端口引腳。
I2C驅動程序需要配置兩個引腳,SCL和SDA。SCL代表時鐘,SDA代表數據。由于I2C協議允許多主,因此需要將SDA配置為開漏以實現線與邏輯。
SRC
I2C可以在多種事件發生時觸發中斷,每種I2C模塊的中斷情況都不同。對于這些中斷,I2C驅動程序依賴于中斷路由器進行中斷傳遞。中斷路由器的任何功能塊都不由I2C驅動程序管理。中斷路由器完全由IRQ驅動程序管理。中斷優先級和服務類型(TOS)在IRQ 驅動程序中集中配置,從而避免了資源沖突。I2C模塊有三個中斷線:
- Protocol Interrupt:這個中斷源有七種,分別是:發送結束、接收模式、仲裁丟失、沒有ACK、地址匹配、通用調用和主碼構成。服務請求線SRC_I2C0P被用作協議中斷。MCAL提供的中斷處理函數為I2c_IsrI2cProtocol,用作在讀取且地址已經發出的情況下,進行包括I2C_NO_ACK、I2C_ARBITRATION_LOST等協議狀態獲取,并回調對應通道的通知函數。
- Error Interrupt:這個中斷有四個來源。這個中斷是由傳輸溢出、傳輸下溢、接收下溢。服務請求線SRC_I2C0ERR用于錯誤中斷。用戶必須確保在發生錯誤中斷時調用12c驅動程序提供的錯誤中斷服務例程。MCAL提供的錯誤中斷實現函數為I2c_IsrI2cError。
- Data transfer Interrupt:這個中斷有四個來源。這個中斷由任何類型突發請求、上次突發請求、單次請求、上次單次請求生成。服務請求線SRC_I2C0DTR用于數據傳輸中斷。MCAL提供的中斷處理函數為I2c_IsrI2cDtr,它負責處理I2C數據的連續寫入和讀取。
環境與目標
本文使用的為英飛凌提供的開發板KIT_A2G_TC397XA_TFT,使用X102上排針的P15.4和P15.5作為I2C使用引腳。
在TC397 KIT開發板上,P15.4和P15.5,不僅從X102引出,還連接到了RTC MCP79411。
涉及的軟件如下:
- EB-tresos:用于生成動態代碼,具體工程搭建參考《【AUTOSAR MCAL】MCAL基礎與EB tresos工程新建》。
- HighTech:用于編譯生成elf文件,具體的工程搭建參考《【MCAL】HighTec集成TC3xx對應MCAL的Demo》。
- UDE 5.2:用于下載和調試程序。
涉及的參考文檔如下表。
序號 | 參考資料 | 內容 |
1 | 《Infineon-AURIX_TC39x-UserManual-v02_00-EN》 | 英飛凌TC39x用戶手冊 |
2 | 《Infineon-AURIX_TC3xx_Part1-UserManual-v02_00-EN.pdf》 | 英飛凌TC3xx用戶手冊 |
3 | 《Infineon-AURIX_TC3xx_Part2-UserManual-v02_00-EN.pdf》 | 英飛凌TC3xx用戶手冊 |
4 | 《Infineon-TC39x-DataSheet-v01_00-EN》 | 英飛凌TC39x數據手冊 |
5 | 《ApplicationKitManual-TC3X7-ADAS-V21.pdf》 | 開發板KIT_A2G_TC397XA_TFT說明 |
6 | 《MC-ISAR_TC3xx_UM_I2c.pdf》 | 英飛凌提供的TC3xx芯片I2C用戶手冊 |
7 | 《DS22266A_CN》 | MCP79410/MCP79411/MCP79412芯片手冊 |
配置目標如下:
- 通過I2C同步/異步讀取MCP79411芯片中6字節長度的ID值。
EB tresos配置
MCU
配置fI2C的頻率。
Port?
上圖是Port口的配置信息,根據的是下圖芯片DataSheet信息。
注意SDA需要配置成開漏輸出。?
I2C?
General
跟其他的模塊差不多,都是包含了一些API使能,錯誤檢測以及時鐘選擇等。
I2cChannelconfiguration
我們需要關注的配置項包括:
- I2cHwUnit:此參數選擇要分配給通道的硬件單元。
- I2cSDASelect:該參數選擇SDA對應的引腳端口。
- I2cSCLSelect:該參數選擇SCL對應的引腳端口。
- I2CSpeed:定義了數據傳輸速度的模式信息,包括STANDARD_MODE、FAST_MODE、HIGH_SPEED_MODE。
- I2cAddressingMode:這個參數定義了尋址模式(7/10位),需要尋址slave。
- I2cFractionalDividerDec:該參數包含了小數分法器的DEC值。
- I2cFractionalDividerInc:此參數包含了小數分發器的INC值。它跟I2cFractionalDividerDec、I2CSpeed共同決定了I2C的通信速率,下面是手冊中包含的計算方法。
- I2cRmc:該參數包含CLC1寄存器的I2cRmc值。
- I2cAsyncNotification?:是否啟用回調函數。
- I2cPacketEndNotification:回調函數名。
- I2cTxTimeOut:該參數包含寫操作的超時值。
- I2cRxTimeOut:該參數包含讀操作的超時值。
IRQ
配置對應中斷優先級,打開相應中斷。
I2C驅動調試
測試代碼
測試代碼如下,可以看到它給MCP79411發送完I2C設備地址1010111(0x57)之后,在寫入了要讀取的EEPROM地址0xF2之后,然后再向同樣的設備地址發送讀取6字節ID數據。代碼分別實現了異步和同步I2C操作,通過條件編譯宏I2CASYENABLE區分。I2cDemoInit實現了I2C的初始化,異步的需要完成中斷的配置,I2C_DemoFunction完成使用I2C讀取MCP79411中設備的6字節ID數據(分為同步和異步),IoHwAb_I2cNotification0則是中斷的回調函數,若協議中斷的返回不是I2C_NO_ERR,則進入死循環。
void I2cDemoInit()
{
#if I2CASYENABLEIrqI2c_Init();SRC_I2C0DTR.B.SRE = 1;SRC_I2C0ERR.B.SRE = 1;SRC_I2C0P.B.SRE = 1;
#endifI2c_Init(&I2c_Config);
}#define MCP79411_EEPROM_ADDRESS 0x57 /* 7 bit slave device address for reading from EEPROMof MCP79411 is 0b1010111 which is 0x57. */
#define ADDRESS_OF_MAC_ADDRESS 0xF2 /* Location of EUI-48 node address (MAC address) */
#define LENGTH_OF_ADDRESS 1 /* Length of address of the register, in which therequested MAC address is stored in bytes */
#define LENGTH_OF_MAC_ADDRESS 6 /* Length of the MAC address in bytes */uint8 g_macAddr[LENGTH_OF_MAC_ADDRESS] = {0, 0, 0, 0, 0, 0}; /* Global parameter for 6-byte EUI-48 MAC address */#define I2C_USER_CHANNEL0 (0)
I2c_ChannelStatusType I2c_GetStatuss = I2C_UNINIT;void I2C_DemoFunction(void)
{/* Address of 6-byte EUI-48 MAC address location */uint8 i2cTxBuffer[1] = {ADDRESS_OF_MAC_ADDRESS};#if I2CASYENABLE//Async read operationI2c_AsyncWrite(I2C_USER_CHANNEL0, &i2cTxBuffer[0], LENGTH_OF_ADDRESS, MCP79411_EEPROM_ADDRESS);//write read addresswhile(I2c_GetStatus(I2C_USER_CHANNEL0) == I2C_BUSY);I2c_AsyncRead(I2C_USER_CHANNEL0, &g_macAddr[0], LENGTH_OF_MAC_ADDRESS, MCP79411_EEPROM_ADDRESS);//read registerwhile(I2c_GetStatus(I2C_USER_CHANNEL0) == I2C_BUSY);
#elseI2c_SyncWrite(I2C_USER_CHANNEL0, &i2cTxBuffer[0], 1, MCP79411_EEPROM_ADDRESS);//write read addressI2c_SyncRead(I2C_USER_CHANNEL0, &g_macAddr[0], 6, MCP79411_EEPROM_ADDRESS);//read register#endif}
#endifvoid IoHwAb_I2cNotification0(I2c_ErrorType ErrorId)
{count++;if(ErrorId){while(1);}
}
測試結果
我們連接X102引出的引腳之后,可以通過邏輯分析儀測量實際的信號,可以得到如下的結果:
- 發送:0xAE 0xF2
- 接收:0xAF 0xE8 0xD6 0x36 0x11 0x04 0x66?
發送的地址為0x57,左移一位為0xAE,寫的話最低位為0,則發送的第一個字節為0xAE,然后再發送我們想發送的EEPROM地址為0xF2,接收發送的第一個字節為0xAE+1(最低位為1表示接收),然后后邊的6個字節即為地址0xF2下的6字節設備ID。
當然,您也可以在UDE觀察g_macAddr數組的值。一般讀取ID都是調試I2C的第一階段,讀到了就代表I2C已經通了。
十六宿舍 原創作品,轉載必須標注原文鏈接。
?2023 Yang Li. All rights reserved.
歡迎關注?『十六宿舍』,大家喜歡的話,給個👍,更多關于嵌入式相關技術的內容持續更新中。