STM32的硬件I2C设计有BUG

坊间一直流传着一个传说~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,时序调节比较麻烦。
两者各有其优缺点,需要根据实际需求去选择。


华南地区首个AI公园项目已正式启动
易华录提出面向数据湖的数据安全治理框架
澳大利亚公司已扫清太阳能电池的主要障碍之一,利用铜代替银
STM32按键控制LED的亮灭
怎样使用Arduino和按钮自动重复按键
STM32的硬件I2C设计有BUG
大联大友尚集团推出基于onsemi产品的65W PD电源适配器方案
物联网网关如何配置云里物里IoT网关-G1操作说明
三星Galaxy Fold 2折叠屏手机添加新配色,采用6.7英寸显示屏
全球能源互联网的实质是智能电网+特高压电网+清洁能源
电源设计说明:开关模式解决方案中的声学噪声抑制
全球首款碳纤维智能手机发布,比一袋薯片还轻
IGBT:走虚拟IDM之路
Amphenol Commercial SAS/PCIe 4.0连接器的特性和应用
cam350层的编辑
恩智浦半导体加入互联照明联盟
零跑汽车全系降价,最高综合优惠4万元
米尔科技荣获ARM公司颁发的“2013年亚太区最佳代理商大奖”
五分钟了解奇瑞全新SUV平台——T1X平台概念
升级煤矿安全监测监控系统的原因是什么