• 正文
    • 一、為什么要用模擬 IIC
    • 二、實現模擬 IIC 的代碼封裝
    • 三、實現模擬 IIC 的簡要說明
  • 推薦器件
  • 相關推薦
申請入駐 產業(yè)圖譜

I2C 驅動及其 Checksum在 BMS系統中的應用

2024/02/27
2975
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

各位好,從今天開始,我的 BMS 電池保護板系列開始聊一下軟件相關的話題。

首先要關注的,就是我們的主控芯片如何控制 AFE,如何從 AFE 中讀取到想要的信息,這就離不開 AFE 的通信接口。

AFE 的通信接口有很多種類,比如 Uart,IIC,SPI 等。其中 Uart 不多見,以 IIC 和 SPI 最為常見,因為這兩個通信協議是板級通信中最常用的,邏輯簡單,線路少。SPI 有一種菊花鏈模式,這個模式在分布式 BMS 系統中使用普遍,基本各個AFE 廠家都設計了相應的隔離芯片,有保障他們的AFE 可以被更好得使用。我的 Demo 中選擇的 AFE的通信是 IIC 接口,因此這一篇文章主要講述 IIC 的實現。

一、為什么要用模擬 IIC

在我設計的 Demo 中,我選擇了使用 IO 口來模擬 IIC 總線,這種選擇經歷了很久的思考。首先,這個行業(yè)的伙伴都應該了解,早期的 STM32F1 系列 MCU,在 IIC 的硬件設計上出現過 bug,在中斷打斷 IIC 的時候會導致 IIC 總線無端掛起,或者有些標志位無法置位,這是選擇模擬 IIC 的最初的原因。

隨后,經過幾個項目的磨煉,這個 IIC 使用模擬 IO 實現還是非選不可的,原因如下:

    在 BMS 項目中,MCU 并不需要特別快速的運行,因為快速響應的過流保護短路保護都有 AFE 的硬件直接操作,而讀取 AFE 采樣的數據也不需要很頻繁,想想,AFE 的 ADC 普遍的采樣頻率才 5Hz。從多陣列產品開發(fā)的角度,我們經常會遇到更換 MCU 的情況,原因不乏成本,缺貨,或者看原廠不順眼等。那么如果使用硬件的 IIC 模式,面對各家的 MCU 的外設驅動,還需要一定的學習成本和移植風險,所以模擬的 IIC 總線直接使用兩個 IO 口和一個簡單的延時函數即可。

當然,硬件 IIC 是有一定的好處的,除了通信的可靠性和容錯性外,相對于模擬 IIC 最大的好處是,在單字節(jié)接收的過程中,我們可以利用中斷來讓 MCU 干些其他事情,也僅此而已。所以,如果你的系統運行頻率很高,CPU 負荷比較高的情況下,肯定首選硬件 IIC。

二、實現模擬 IIC 的代碼封裝

封裝一個代碼,首先要將模塊的功能抽象出來,確定模塊的輸入輸出邏輯,從而確定如何封裝代碼成一個通用的庫,或者說利于移植的模塊。我個人在這一塊有一個整體的思路,就是按照 C++的面向對象編程思想來規(guī)劃這個類,雖然 C 無法寫成類的形式,但是大體的封裝思想是可以實現的。

首先我們確定,要模擬 IIC 通信總線,需要兩個 IO,這兩個 IO 的通信速率不必太高,因為 IIC 一般的通信速率才 400Khz,現在有一些 1Mhz 的。其次,我們需要一個延時函數,來控制總線的時鐘延時,這個延時最好使用定時器來實現,這樣可以調整出比較好的 IIC 波形,但是這樣會引入一個復雜的 TIMER 模塊,因此我選擇了代碼延時,只需要確定好主時鐘調試一次即可。有了上面的兩個 IO 口和延時函數,我們就可以通過控制兩個引腳的高低和時序來模擬 IIC 通信了?,F在,我們已經有了足夠的輸入來對模擬 IIC 這個類進行構造函數的編寫。那么,進一步的,我們確定 IIC 這個類的方法和屬性。我們可以把 IIC 總線通信的一些錯誤和狀態(tài)作為屬性來定義,可以讓調用者通過調用類的屬性來獲取總線的狀態(tài),是空閑,還是忙狀態(tài)。也可以通過屬性來獲取上一次通信的結果。其次,對于方法就比較明確了,我們需要查詢忙狀態(tài)的方法,需要最基本的向設備-地址的讀寫操作,然后再在上層實現多字節(jié)的讀寫操作。

OK,看一下代碼吧

下面是硬件相關的定義,定義了兩個引腳和兩個延時函數,因為在 IIC 通信中,有控制時鐘的延時和控制時序的延時。

//===========硬件相關的定義==================================================
#include "cw32l031.h"#include "cw32l031_gpio.h"// I2C的引腳定義#define I2C_SDA_PIN     GPIO_PIN_0#define I2C_SCL_PIN     GPIO_PIN_1
//I2C 的軟件延時,這個需要根據系統時鐘進行調整#define    I2C_DELAY_INIT()        u8 _counter = 0;#define    I2C_DELAY()             for( _counter = 0; _counter < 20;  ) {_counter++; }    //100K 重新測試#define    I2C_DELAY_SHORT()       for( _counter = 0; _counter < 10;  ) {_counter++; }    //
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

然后,我們需要定義一些類的屬性,在這里其實就是一些關于通信模塊的設置,比如通信的重發(fā)嘗試次數,比如 IIC 總線的狀態(tài)和錯誤標志等,這里我們直接使用宏定義來設定,沒有在提供變量給調用者進行實例化的時候進行構建,因為這在 C語言中就相當于脫褲子放屁。

//===============IIC 軟件層相關(2023.11.11整理)======================================// I2C的一些錯誤宏定義#define    I2C_SUCCESS                 0#define    I2C_ARBITRATION_LOST        0x11#define    I2C_NACK                    0x12#define    I2C_TIMEOUT                 0x13#define    I2C_WRITEFAIL               0x14#define    I2C_CRC                     0x15#define    I2C_OTHER                   0x16

#define    I2C_MAX_ATTEMPTS            1000   //嘗試次數

最后,我們需要給調用者提供一個可以調用的列表,從類的角度看,無非就是構造函數,析構函數和幾個方法屬性。這里我們只有一個充當構造函數的初始化函數和兩個方法:讀方法和寫方法。

// I2C對外接口的聲明void i2c_init(void); //I2C的初始化函數
//多字節(jié)的讀寫u8 i2c_write(u8 addr, u8 reg_addr, u8* txBuff, int count);u8 i2c_read( u8 addr, u8 reg_addr, u8* rxBuff, int count);

好啦,有了以上的一個頭文件,我們就可以使用這個 IIC 模塊,使用的步驟很簡單,先確定 IO 口,然后確定延時函數,最后在我們的初始化過程中將 i2c_init()調用一下,就可以在我們的系統中使用讀寫方法了。我建了一個微信群,供大家來討論 BMS 相關技術,為了保證討論質量,請先加我的個人微信,備注 “BMS” ,我來拉大家入群。

三、實現模擬 IIC 的簡要說明

當我們定義好模擬 IIC 模塊的外觀后,也就是對外接口后,我們就需要思考如何在這個封裝層下來實現邏輯,其實這是一種自頂向下的設計模式。咱們先把 IO 的拉高拉低變換成總線上的一些狀態(tài),對于 SCL 引線還好,他負責產生時鐘,可以直接拉高拉低,而對于 SDA 引線就稍微復雜一些,因為他除了可以拉高拉低的輸出外,還需要從總線上讀取電平。

GPIO_TypeDef* m_I2C_PORT = CW_GPIOA; //定義I2C的IO指針,默認為GPIOB
//I2C的一些信號狀態(tài),不同的硬件需要重新定義#define i2cSetSDA_highZ()    (m_I2C_PORT->ODR |= I2C_SDA_PIN)#define i2cGetSDA()          ((m_I2C_PORT->IDR & I2C_SDA_PIN) ? 1 : 0)#define i2cSetSCL_highZ()    (m_I2C_PORT->ODR |= I2C_SCL_PIN)#define i2cGetSCL()          ((m_I2C_PORT->IDR & I2C_SCL_PIN) ? 1 : 0)#define i2cClearSDA()        (m_I2C_PORT->ODR &= (~I2C_SDA_PIN))#define i2cClearSCL()        (m_I2C_PORT->ODR &= (~I2C_SCL_PIN))

以上,我們將 IO 的狀態(tài)轉換成了 IIC 總線上的多態(tài)端口。

推薦器件

更多器件
器件型號 數量 器件廠商 器件描述 數據手冊 ECAD模型 風險等級 參考價格 更多信息
A3981KLPTR-T 1 Allegro MicroSystems LLC Stepper Motor Controller, PDSO28, 9.70 X 4.40 MM, 1.20 MM HEIGHT, LEAD FREE, MO-153AET, TSSOP-28

ECAD模型

下載ECAD模型
$3.2 查看
L6206PD 1 STMicroelectronics DMOS dual full bridge driver

ECAD模型

下載ECAD模型
$10.13 查看
ADG749BKSZ-REEL7 1 Rochester Electronics LLC 1-CHANNEL, SGL POLE DOUBLE THROW SWITCH, PDSO6, ROHS COMPLIANT, PLASTIC, MO-203AB, SC-70, 6 PIN
$2.36 查看

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄