我正在从事一个电池管理系统(BMS)项目并使用了 BQ76952 AFE 芯片。 我已经成功配置好芯片、在正常情况下能够可靠地读取电压和电流寄存器。 不过、我遇到了一个问题、即 cortex M4控制器和 BQ76952之间的 I2C 通信会间歇性停止。 在该问题期间、SDA 线变为高电平、SCL 线保持低电平。 我使用了逻辑分析仪来监测 I2C 通信。
遗憾的是、由于我公司的专有政策、我无法分享特定的软件代码、但我会尽可能详细地介绍。 我已经确定、当 AFE 报告电芯欠压(CUV)警报并尝试控制放电 FET 时、会发生此 I2C 问题。 当 AFE 对警报做出响应时、它会在关断和导通 DSG FET 之间重复循环、并且我同时尝试通过 I2C 从微控制器读取电压和电流数据。
我已经尝试通过减少 I2C 超时值和清除错误标志来解决这一问题、但这些措施仍未解决问题。 如何确保 I2C 通信保持稳定和可靠、尤其是在触发 CUV 警报并且 AFE 快速连续控制 FET 时?
以下是 I2C 配置定义
#define I2C_TIMEOUT 0xFFF
#define I2Cx_SPEED 400000
#define I2Cx_ADDRESS 0x87
#define I2Cx_PORT I2C1
#define I2Cx_CLK CRM_I2C1_PERIPH_CLOCK
#define I2Cx_SCL_PIN GPIO_PINS_6
#define I2Cx_SCL_GPIO_PORT GPIOF
#define I2Cx_SCL_GPIO_CLK CRM_GPIOF_PERIPH_CLOCK
#define I2Cx_SDA_PIN GPIO_PINS_7
#define I2Cx_SDA_GPIO_PORT GPIOF
#define I2Cx_SDA_GPIO_CLK CRM_GPIOF_PERIPH_CLOCK
#define I2Cx_EVT_IRQn I2C1_EVT_IRQn
#define I2Cx_ERR_IRQn I2C1_ERR_IRQn
void i2c_config (i2c_handle_type* hi2c)
{
/*重置 i2c 外设*/
I2C_RESET (hi2c->i2cx);
/* i2c 外设初始化*/
I2C_lowlevel_init (hi2c);
/* i2c 外设启用*/
I2C_ENABLE (hi2c->i2cx、TRUE);
}
void i2c_lowlevel_init (i2c_handle_type* hi2c)
{
GPIO_init_type GPIO_initstructure;
// uint32_t sample_i2cx=hi2c->i2cx;
if (hi2c->i2cx == I2Cx_port)
// if (sample_i2cx == I2Cx_port)
{
/* i2c periph 时钟启用*/
crm_periph_clock_enable (I2Cx_CLK、true);
crm_periph_clock_enable (I2Cx_SCL_GPIO_CLK、true);
crm_periph_clock_enable (I2Cx_SDA_GPIO_CLK、true);
crm_periph_clock_enable (crm_IOMUX_Periph_clock、true);
GPIO_PIN_REMAP_CONFIG (I2C1_GMUX_0010、TRUE);
/* GPIO 配置*/
GPIO_initstructure.GPIO_OUT_TYPE = GPIO_OUTPUT_OPEN_DRAIN;
GPIO_initstructure.GPIO_pull = GPIO_PULL_UP;
GPIO_initstructure.GPIO_mode = GPIO_MODE_MUX;
GPIO_initstructure.GPIO_DRIVE_STRENGTH = GPIO_DRIVE_STENCE_MAXIMUM;
/*配置 i2c 引脚:SCL */
GPIO_initstructure.GPIO_pins = I2Cx_SCL_PIN;
GPIO_init (I2Cx_SCL_GPIO_port、&GPIO_initstructure);
/*配置 i2c 引脚:SDA */
GPIO_initstructure.GPIO_pins = I2Cx_SDA_PIN;
GPIO_init (I2Cx_SDA_GPIO_port、&GPIO_initstructure);
/*配置和启用 i2c 中断*/
NVIC_IRQ_ENABLE (I2Cx_EVT_IRQn、0、0);
NVIC_IRQ_ENABLE (I2Cx_ERR_IRQn、0、0);
I2C_init (hi2c->i2cx、I2C_FSMODE_DUTY_2_1、I2Cx_SPEED);
//i2c_clock_stract_enable (hi2c->i2cx、false);
//i2c_general_call_enable (hi2c->i2cx、false);
//i2c_own_address1_set (hi2c->i2cx、I2C_ADDRESS_MODE_7BIT、I2Cx_ADDRESS);
}
}
我使用的是 FreeRTOS 内核、读写寄存器是在一项关键任务中完成的。 我将分享关键任务持续调用代码的位置。 我可以说我的控制器没有卡在任何环路中、由于 CAN 通信和正在发生、LED 闪烁正在发生、状态机正在转换、以接受 I2C 总线按原样无响应。 每个 I2C 通信都会返回一些 I2C 错误、大部分时间它是总线错误。 因此、当我尝试了多次接近、但由于不了解其根本原因而无法解决它时、我几乎没有遇到困难。 请在这里帮助我。
{
if (flag == I2C_BUSYF_FLAG)
{
超时= 0xFFF;
while (i2c_flag_get (hi2c->i2cx、flag)!= reset)
{
time_check =超时;
/*检查超时*/
if ((timeout--=0)
{
hi2c->error_code = I2C_ERR_TIMEOUT;
//i2c_flag_clear (hi2c->i2cx、I2C_BUSYF_FLAG);
返回 I2C_ERR_TIMEOUT;
}
}
}
对于每个 i2c 读取和写入、都会反复调用此 I2C 等待标志。