坊間一直流傳著一個(gè)傳說(shuō)~STM32的硬件I2C設(shè)計(jì)有BUG,最好不要用,用軟件I2C比較靠譜。長(zhǎng)久以來(lái),為了不必要的麻煩,我也一直沒(méi)有用過(guò)硬件I2C,主要是軟件I2C也比較方便,基本上任意端口都可以用。
最近畫(huà)了塊板子,正好用到了I2C,就順便來(lái)測(cè)試一下硬件I2C是不是真的像有些人說(shuō)的不好用。
測(cè)試硬件:STM32F407VET6+AT24C64測(cè)試軟件:STM32CubeMX v6.1.1HAL庫(kù):STM32CubeF4 Firmware Package V1.25.2
STM32CubeMX配置 使用STM32CubeMX配置很方便,時(shí)鐘等基礎(chǔ)配置不再詳細(xì)介紹,直接看I2C配置如下:
這里的速度模式選擇為標(biāo)準(zhǔn)模式,時(shí)鐘為100K。要求高的可以選擇Fast模式,400K時(shí)鐘。 配置完成后生成代碼。
編寫(xiě)代碼 代碼生成后,直接調(diào)用讀寫(xiě)數(shù)據(jù)的函數(shù)即可: HAL_I2C_Mem_Read HAL_I2C_Mem_Write 函數(shù)參數(shù)可參考代碼注釋。 24CXX系列的EEPROM進(jìn)行寫(xiě)操作時(shí)需要注意,跨頁(yè)寫(xiě)入時(shí),要有一定的延時(shí),否則會(huì)寫(xiě)入不成功。不同容量的頁(yè)大小也不一樣。 另外,24C16以下容量的地址為8位,24C32以上容量的地址為16位,在調(diào)用讀寫(xiě)函數(shù)時(shí)需要注意,選擇I2C_MEMADD_SIZE_8BIT或者I2C_MEMADD_SIZE_16BIT。測(cè)試使用的是24C64,所以選擇I2C_MEMADD_SIZE_16BIT。 為了方便操作,將讀寫(xiě)函數(shù)再封裝一層,將跨頁(yè)寫(xiě)入的各種情況都考慮到,實(shí)現(xiàn)任意地址連續(xù)寫(xiě)入。程序如下:
#include “at24c64.h”#include “i2c.h”
#define AT24CXX_ADDR_READ
0xA1#define AT24CXX_ADDR_WRITE
0xA0#define PAGE_SIZE
32/** * @brief
AT24C64任意地址連續(xù)讀多個(gè)字節(jié)數(shù)據(jù) * @param
addr —— 讀數(shù)據(jù)的地址(0-65535) * @param
dat —— 存放讀出數(shù)據(jù)的地址 * @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任意地址連續(xù)寫(xiě)多個(gè)字節(jié)數(shù)據(jù) * @param
addr —— 寫(xiě)數(shù)據(jù)的地址(0-65535) * @param
dat —— 存放寫(xiě)入數(shù)據(jù)的地址 * @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;
//寫(xiě)入字節(jié)計(jì)數(shù)
/* 對(duì)于起始地址,有兩種情況,分別判斷 */
if(0 == addr % PAGE_SIZE )
{
/* 起始地址剛好是頁(yè)開(kāi)始地址 */
/* 對(duì)于寫(xiě)入的字節(jié)數(shù),有兩種情況,分別判斷 */
if(size 《= PAGE_SIZE)
{
//寫(xiě)入的字節(jié)數(shù)不大于一頁(yè),直接寫(xiě)入
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, size, 0xFFFFFFFF);
}
else
{
//寫(xiě)入的字節(jié)數(shù)大于一頁(yè),先將整頁(yè)循環(huán)寫(xiě)入
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;
}
//將剩余的字節(jié)寫(xiě)入
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], size - cnt, 0xFFFFFFFF);
}
}
else
{
/* 起始地址偏離頁(yè)開(kāi)始地址 */
/* 對(duì)于寫(xiě)入的字節(jié)數(shù),有兩種情況,分別判斷 */
if(size 《= (PAGE_SIZE - addr%PAGE_SIZE))
{
/* 在該頁(yè)可以寫(xiě)完 */
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, size, 0xFFFFFFFF);
}
else
{
/* 該頁(yè)寫(xiě)不完 */
//先將該頁(yè)寫(xiě)完
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);
//循環(huán)寫(xiě)整頁(yè)數(shù)據(jù)
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;
}
//將剩下的字節(jié)寫(xiě)入
return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], size - cnt, 0xFFFFFFFF);
}
}}
測(cè)試結(jié)果經(jīng)過(guò)測(cè)試硬件I2C讀寫(xiě)EEPROM正常。沒(méi)有發(fā)現(xiàn)所謂的BUG,當(dāng)然這只是M4內(nèi)核的針對(duì)EEPROM一種器件的測(cè)試,對(duì)于其它內(nèi)核(M3等)和其它I2C器件,還有待驗(yàn)證。
總結(jié)硬件I2C使用起來(lái)比較簡(jiǎn)單,不需要自己去調(diào)節(jié)時(shí)序,但是只能使用固定的幾個(gè)引腳。軟件模擬I2C可以使用任意引腳,針對(duì)不同的MCU,移植起來(lái)比較方便,但對(duì)于不同頻率的MCU,時(shí)序調(diào)節(jié)比較麻煩。
兩者各有其優(yōu)缺點(diǎn),需要根據(jù)實(shí)際需求去選擇。
審核編輯 :李倩
-
STM32
+關(guān)注
關(guān)注
2291文章
11022瀏覽量
363490 -
I2C
+關(guān)注
關(guān)注
28文章
1538瀏覽量
127416 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4377瀏覽量
64553
原文標(biāo)題:STM32的硬件I2C有BUG嗎?
文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
STM32H7CubeMX配置硬件I2C,讀寫(xiě)失敗是什么問(wèn)題呀?
I2C總線通信原理 如何設(shè)計(jì)I2C總線電路
I2C總線的優(yōu)缺點(diǎn)分析
I2C總線與Arduino的接口示例
I2C總線的工作模式介紹
I2C總線故障排除技巧
I2C總線設(shè)備地址設(shè)置方法
I2C總線應(yīng)用實(shí)例分析
RISC V的I2C操作
I2C協(xié)議的基礎(chǔ)知識(shí)

評(píng)論