在线时间151 小时
UID116713
ST金币0
蝴蝶豆0
注册时间2009-3-17
金牌会员
- 最后登录
- 2020-7-10
|
a0a.1 32b0c
最近正在使用一个加速度传感器做设计,正好赶上论坛搞活动,有幸抢到一块STM32L4的板子,今天写一篇开发笔记,分享一下开发心得。如果处理器正在与I2C总线的器件通讯时,处理器异常复位(例如在线调试reset),那么I2C从器件未跑完要求的输出时序,从而异常锁死IC2总线的SDA,此时问题表现为总线一直为busy,只能断电复位才可正常工作。
解决思路为,让从器件跑完他该有的时序,自然释放SDA,那么每次复位初始化时,不能直接初始化处理器的I2C外设,而是要先查询SDA是否处于锁死状态,不多说,先上图。
先秀一下开发板哈,我看大家对此很热衷
下面是连接,使用I2C1的PB6,PB7
现在都进入懒人模式了,有了STM32CUBE还是很方便的,首先要PB6,PB7进入GPIO OC模式,下图为GPIO模式截图
查询I2C总线是否占用,如果占用则解锁,解锁后进入I2C初始化函数(代码在最后)。下图为I2C cube 截图
下面通过代码简述流程
//首先初始化PB6,PB7为集电极开路的输出状态,注意此时不能初始化I2C外设//
//因为一旦初始化了I2C外设,PB6,PB7就不跟你玩了,直接被I2C接管了//
////以下是MX_GPIO_Init()的内容////////////////////////////////////////////////
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOB_CLK_ENABLE();
/*Configure GPIO pins : PB6 PB7 */
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_PB6);
HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_PB7);
////////////////////////初始化完GPIO模式/////////////////////////////////////////////////////
HAL_GPIO_WritePin(GPIOB,GPIO_Pin_6,GPIO_PIN_SET); //置PB6为集电极开路状态,外部上拉电阻高电平//
HAL_GPIO_WritePin(GPIOB,GPIO_Pin_7,GPIO_PIN_SET); //置PB7为集电极开路状态,外部上拉电阻高电平//
unsigned char timeout=0; //防止解锁失败导致程序锁死的循环变量//
//下面这个循环不断在SCL送出时钟,直到I2C从器件退出输出状态,即释放I2C SDA总线//
while(HAL_GPIO_ReadPin(GPIOB,GPIO_Pin_7)== GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB,GPIO_Pin_6,GPIO_PIN_SET); //SCL输出时钟//
delay_us(100);
HAL_GPIO_WritePin(GPIOB,GPIO_Pin_6,GPIO_PIN_RESET);
delay_us(100);
timeout++;
if(timeout==0)
{
//失败//
break;
}
}
/////////////////////////////////////////////////////////////////////////////
///////////////////I2C从器件释放总线后,正式进入I2C外设初始化函数////////////
MX_I2C1_Init();
//可以访问I2C器件了//
.
.
.
.
////////////////////////////////////////////////////////////////////////////////
////////下面函数为cube生成的I2C1初始化代码,根据需要自己改/////////
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00000000;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
HAL_I2C_Init(&hi2c1);
/**Configure Analogue filter
*/
HAL_I2CEx_AnalogFilter_Config(&hi2c1, I2C_ANALOGFILTER_ENABLED);
}
小结:I2C总线被从器件锁死的原因比较多,这只是我在开发中遇到的一种情况,希望对朋友们有用。
|
评分
-
查看全部评分
|