STM32的硬件I2C设计有BUG

发布者:HeavenlyWonder最新更新时间:2024-03-04 来源: elecfans关键字: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配置如下:

c3060f02-c3b9-11ec-bce3-dac502259ad0.png

这里的速度模式选择为标准模式,时钟为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  硬件I2C  BUG 引用地址:STM32的硬件I2C设计有BUG

上一篇:基于STM32平台实现SVPWM调制
下一篇:stm32单片机待机模式的设计

推荐阅读最新更新时间:2024-11-11 12:48

STM32 STM8开发工具(ST-LINK/V2)
简介: 这是一款完全兼容ST-LINK/V2的STM32 STM8开发工具,可以在线仿真、调试、下载全系列的STM8和STM32 MCU。并且拥有固件升级的功能,可支持ST公司未来的MCU开发。 本产品采用与官方版本完全一致的固件,所以完全兼容官方的ST-LINK/V2,具有相同的功能及使用方法。 并且,产品设计团队还对官方版本的硬件作了反复摸索、不断优化,使之既继承了官方版本优点,又对官方版本进行了超越;让用户使用起来更安全、更方便、更快捷、更高效! 创新的功能特点: 重新设计了电路架构及外壳,使工具更小巧、漂亮、易带,使用更安全、方便; 精心设计了内部电路,增加了多重保护措施,确保用户电脑、ST-
[单片机]
stm32定时器pwm模式输入捕获
stm32中的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能。这种模式通常用在对输入信号频率frequency、占空比duty、高低脉宽的计算中,具有很广泛的用途。 STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。 PWM模式捕获方法:利用TIM3_CH1作PWM输出,TIM2_CH2捕获上述PWM信号,并测出频率和占空比。设置PWM频率为1KHz,占空比50%。 具体步骤: 1. 为了实现PW
[单片机]
STM32 USB设计单片机程序篇
  首先,我们来看看usb的工作过程。   当usb设备接入到主机时,主机开始枚举usb设备,并向usb设备发出指令要求获取usb设备的相关描述信息,其中包括设备描述(device descriptor)、配置描述(configuration descriptor)、接口描述(interface descriptor)、端点描述(endpoint descriptor)等。这些信息是通过端点0(endpoint 0)传送到主机的。获取各种描述信息后,操作系统会为其配置相应的资源。这样主机就可以与设备之间进行通信了。   usb通讯有四种通讯方式控制(control)、中断(interrupt)、批量(bulk)和同步(sync
[单片机]
STM32外部中断具体解释
一、基本概念 ARM Coetex-M3内核共支持256个中断,当中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32眼下支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。 STM32可支持68个中断通道,已经固定分配给对应的外部设备,每一个中断通道都具备自己的中断优先级控制字节PRI_n(8位,可是STM32中仅仅使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级能够分成2组,从高位看,前面定义的是抢占式优
[单片机]
stm32之Cortex系统定时器(SysTick)
SysTick时钟,俗称“嘀嗒定时器”,它能按设定的时间产生一次中断。控制工程代码中随处可见形如delay_ms()之函数。但是一直不清楚其内在机制。今天花时间研究了一下。 首先还是在数据手册上看一下SysTick寄存器的配置,如图: 寄存器说明 stm32的时钟源 选择外部时钟源时,则Systick时钟为HCLK /8 选择内核时钟源时,则Systick时钟为HCLK 延时编程原理 systick定时器是24位的递减计数器,设定初值并使能它后,它会把每个系统时钟周期计数器减1, 计数到0 时,将从RELOAD 寄存器中自动重装载定时器初值。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息. 延时编程
[单片机]
<font color='red'>stm32</font>之Cortex系统定时器(SysTick)
STM32 关闭JTAG 使用相应GPIO口 简单记录
STM32 的PA13-PA14-PA15-PB3-PB4-PB5主要是用来JTAG调试用的,于是在默认下是启动后为JTAG模式,但是对于不需要JTAG而需要充分利用GPIO口时,就需要将JTAG关闭,设置为GPIO模式。 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开PA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开PB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFI
[单片机]
STM32驱动ST7920的12864液晶(串行方式)
/****************************************************************************************** * 文件名称 :12864.c * 版权 : * 模块名称 :st7920驱动的12864液晶的串行工作方式驱动程序 * cpu : stm32f103rct6 主频:72M * 作者 : * 创建日期 :2009-10-15 * 功能概要 : *----------------------------------------修改历史------------------------------------------
[单片机]
STM32GPIO——快速IO的使用
STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置'1'或置'0'。 GPIOx_BSRR的高16位中每一位对应端口x的每个位,对高16位中的某位置'1'则端口x的对应位被清'0';寄存器中的位置'0',则对它对应的位不起作用。 GPIOx_BSRR的低16位中每一位也对应端口x的每个位,对低16位中的某位置'1'则它对应的端口位被置'1';寄存器中的位置'0',则对它对应的端口不起作用。 简单地说
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved