最近正在使用一个加速度传感器做设计,正好赶上论坛搞活动,有幸抢到一块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总线被从器件锁死的原因比较多,这只是我在开发中遇到的一种情况,希望对朋友们有用。 |
STM32L4 超低功耗微系列及相关探索学习板介绍
STM32L476程序烧录
【NUCLEO-L476RG开发】使用STM32L4开发板玩转心率传感器
[Nucleo-L4R5] STM32L4R5 驱动OLED
[Nucleo-L4R5] STM32L4R5 基于OLED显示二维码
STM32L432KC开箱测评------OLED显示
STM32L476建工程及点亮LED
【评测站】STM32L496G-DISCO - 高性价比的智能手表解决方案
【超低功耗STM32L4系列首秀】 收到板子了,
STM32L496G-DISCO的出厂源码在哪儿可以下载?
因为仿真时,电路板的电源是atlink供给的,不想总是插拔,再者,实际产品中通常有处理器复位按键,你不希望按了一下复位键后,设备失控了吧。
原来如此……工程文件能分享下吗?
不完全是,很多时候是时序问题