坊間一直流傳著一個傳說~STM32的硬件I2C設計有BUG,最好不要用,用軟件I2C比較靠譜。長久以來,為了不必要的麻煩,我也一直沒有用過硬件I2C,主要是軟件I2C也比較方便,基本上任意端口都可以用。
最近畫了塊板子,正好用到了I2C,就順便來測試一下硬件I2C是不是真的像有些人說的不好用。
測試硬件:STM32F407VET6+AT24C64測試軟件:STM32CubeMX v6.1.1HAL庫:STM32CubeF4 Firmware Package V1.25.2
STM32CubeMX配置 使用STM32CubeMX配置很方便,時鐘等基礎配置不再詳細介紹,直接看I2C配置如下:
這里的速度模式選擇為標準模式,時鐘為100K。要求高的可以選擇Fast模式,400K時鐘。 配置完成后生成代碼。
編寫代碼 代碼生成后,直接調用讀寫數據的函數即可: HAL_I2C_Mem_Read HAL_I2C_Mem_Write 函數參數可參考代碼注釋。 24CXX系列的EEPROM進行寫操作時需要注意,跨頁寫入時,要有一定的延時,否則會寫入不成功。不同容量的頁大小也不一樣。 另外,24C16以下容量的地址為8位,24C32以上容量的地址為16位,在調用讀寫函數時需要注意,選擇I2C_MEMADD_SIZE_8BIT或者I2C_MEMADD_SIZE_16BIT。測試使用的是24C64,所以選擇I2C_MEMADD_SIZE_16BIT。 為了方便操作,將讀寫函數再封裝一層,將跨頁寫入的各種情況都考慮到,實現任意地址連續寫入。程序如下:
#include “at24c64.h”#include “i2c.h”
#define AT24CXX_ADDR_READ
0xA1#define AT24CXX_ADDR_WRITE
0xA0#define PAGE_SIZE
32/** * @brief
AT24C64任意地址連續讀多個字節數據 * @param
addr —— 讀數據的地址(0-65535) * @param
dat —— 存放讀出數據的地址 * @retval
成功 —— HAL_OK*/uint8_t At24cxx_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size){
return HAL_I2C_Mem_Read(&hi2c2, AT24CXX_ADDR_READ, addr, I2C_MEMADD_SIZE_16BIT, recv_buf, size, 0xFFFFFFFF);}
/** * @brief
AT24C64任意地址連續寫多個字節數據 * @param
addr —— 寫數據的地址(0-65535) * @param
dat —— 存放寫入數據的地址 * @retval
成功 —— HAL_OK*/uint8_t At24cxx_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size){
uint8_t i = 0; uint16_t cnt = 0;
//寫入字節計數
/* 對于起始地址,有兩種情況,分別判斷 */
if(0 == addr % PAGE_SIZE )
{
/* 起始地址剛好是頁開始地址 */
/* 對于寫入的字節數,有兩種情況,分別判斷 */
if(size 《= PAGE_SIZE)
{
//寫入的字節數不大于一頁,直接寫入
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, size, 0xFFFFFFFF);
}
else
{
//寫入的字節數大于一頁,先將整頁循環寫入
for(i = 0;i 《 size/PAGE_SIZE; i++)
{
HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], PAGE_SIZE, 0xFFFFFFFF);
HAL_Delay(3);
addr += PAGE_SIZE;
cnt += PAGE_SIZE;
}
//將剩余的字節寫入
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], size - cnt, 0xFFFFFFFF);
}
}
else
{
/* 起始地址偏離頁開始地址 */
/* 對于寫入的字節數,有兩種情況,分別判斷 */
if(size 《= (PAGE_SIZE - addr%PAGE_SIZE))
{
/* 在該頁可以寫完 */
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, size, 0xFFFFFFFF);
}
else
{
/* 該頁寫不完 */
//先將該頁寫完
cnt += PAGE_SIZE - addr%PAGE_SIZE;
HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, cnt, 0xFFFFFFFF);
addr += cnt;
HAL_Delay(3);
//循環寫整頁數據
for(i = 0;i 《 (size - cnt)/PAGE_SIZE; i++)
{
HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], PAGE_SIZE, 0xFFFFFFFF);
HAL_Delay(3);
addr += PAGE_SIZE;
cnt += PAGE_SIZE;
}
//將剩下的字節寫入
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], size - cnt, 0xFFFFFFFF);
}
}}
測試結果經過測試硬件I2C讀寫EEPROM正常。沒有發現所謂的BUG,當然這只是M4內核的針對EEPROM一種器件的測試,對于其它內核(M3等)和其它I2C器件,還有待驗證。
總結硬件I2C使用起來比較簡單,不需要自己去調節時序,但是只能使用固定的幾個引腳。軟件模擬I2C可以使用任意引腳,針對不同的MCU,移植起來比較方便,但對于不同頻率的MCU,時序調節比較麻煩。
兩者各有其優缺點,需要根據實際需求去選擇。
審核編輯 :李倩
-
STM32
+關注
關注
2270文章
10904瀏覽量
356409 -
I2C
+關注
關注
28文章
1489瀏覽量
123908 -
函數
+關注
關注
3文章
4333瀏覽量
62708
原文標題:STM32的硬件I2C有BUG嗎?
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論