首页 > 其他分享 >记一次STM32使用I2C PinRemap引脚重映射出现卡死现象

记一次STM32使用I2C PinRemap引脚重映射出现卡死现象

时间:2024-08-05 21:16:26浏览次数:16  
标签:SCL 引脚 PinRemap STM32 OLED IIC GPIO I2C define

在移植WouoUI到STMF103C8 BluePill board时,发现会出现上电卡死在I2C检查函数(如下图)
image

本人遇到的现象:在习惯使用的(SWI2C / HWI2C)@(PB8->SCL PB9->SDA)连接OLED的情况下,大多数情况使用江科大的SWI2C,一切正常。

今天跑某开源基于u8g2库的UI框架 WouoUI(HWI2C)@(PB6->SCL PB7->SDA) 遇到了一旦连接OLED的正负极跳线就会导致STM32卡死的现象。意识到可能这就是传说中的标准库 I2C Bug,网上搜寻方案后成功解决,但是I2C的通信速率不能调的和非重映射的一样高,原因未知。

主要原因:加入的OLED供电正负极跳线会导致PB6 PB7被动受到外部电平影响,STM32芯片硬件I2C接口支持多主设备同时使用,内核检测到当出现非自己发出的电平变化等情况后,芯片判定为有其他的主机在操作总线,这样STM32的BUSY(总线忙标志)则会置位,只有在检查到一次I2C协议的停止位后才会硬件清除该标志,此时总线当然只有该芯片单个主机,不会有对应的停止位信号到来,故卡死在等待函数中。
解决方法:在初始化之前使用软件复位,或更换 HAL 库

步骤
① 重映射配置
在GPIO的RCC使能函数下,加入如下语句:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE); 	//重映射到PB8/PB9

② 在所有I2C1有关的配置寄存器写入任何数据之前,加入如下语句:

    I2C1->CR1 |= (1 << 15);
    I2C1->CR1 &= ~(1 << 15);

完整的I2C初始化代码如下:

#define IIC_OLED_SCL_Pin        	GPIO_Pin_8
#define IIC_OLED_SCL_GPIO       	GPIOB
#define IIC_OLED_SCL_GPIO_CLK		RCC_APB2Periph_GPIOB


#define IIC_OLED_SDA_Pin        	GPIO_Pin_9
#define IIC_OLED_SDA_GPIO       	GPIOB
#define IIC_OLED_SDA_GPIO_CLK		RCC_APB2Periph_GPIOB

/*引脚初始化*/
void OLED_I2C_Init(void)
{
    I2C_InitTypeDef I2C_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};		//定义GPIO结构体

    I2C1->CR1 |= (1 << 15);
    I2C1->CR1 &= ~(1 << 15);   // 防止重定义之前,V与G连接PB6 PB7导致的I2C卡死

    RCC_APB2PeriphClockCmd(IIC_OLED_SDA_GPIO_CLK, ENABLE);		//开启GPIO模块的时钟
    RCC_APB2PeriphClockCmd(IIC_OLED_SCL_GPIO_CLK, ENABLE);		//开启GPIO模块的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE); 	//重映射到PB8/PB9需要加这两行(无关位置)

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 285 * 1000; // N*1000
    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);

    GPIO_InitStructure.GPIO_Pin = IIC_OLED_SDA_Pin;					//配置SDA端口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 				// 设置GPIO的模式为输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(IIC_OLED_SDA_GPIO, &GPIO_InitStructure); 				// 初始化GPIO为高速开漏输出模式

    GPIO_InitStructure.GPIO_Pin = IIC_OLED_SCL_Pin;					//配置SCL端口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 				// 设置GPIO的模式为输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 				// 配置 I/O 口的速度为:50MHz,还可选:GPIO_Speed_2MHz,GPIO_Speed_10MHz
    GPIO_Init(IIC_OLED_SCL_GPIO, &GPIO_InitStructure); 				// 初始化GPIO为高速开漏输出模式
}

标签:SCL,引脚,PinRemap,STM32,OLED,IIC,GPIO,I2C,define
From: https://www.cnblogs.com/yuewusayuri/p/18344042

相关文章

  • stm32入门-----硬件I2C读写MPU6050
     目录前言 一、stm32中I2C库函数介绍(stm32f10x_i2c.h)1.初始化2.使能操作3.生成起始位和结束位标志4.发送I2C从机地址5.发送数据和接收数据6.发送应答位7.状态检测二、硬件I2C读取MPU60501.电路连线图2.主要工程文件 3.MPU6050.c代码剖析(1)检测步骤超时操作(2)指......
  • 时钟(STM32F103)
    时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波时钟是单片机的脉搏时钟源:              频率         材料              用途高速外部振荡器(HSE)   4-16MHz     晶体/陶瓷       ......
  • 【stm32】软件定时器
    【stm32】软件定时器文章目录【stm32】软件定时器@[toc]为什么软件定时器相关代码使用例程参考链接为什么为什么会想着搞个软件定时器呢?之前的esp8266模块的通信,用的延时阻塞去实现的,对主程序影响挺大的。想着改改,不想上freertos啥的操作系统,就想着之前看4G模......
  • STM32学习记录(一):STM32概述
    STM32F10x系统结构图STM32F10x的系统结构图如下[1]:框图中名词解释,按A~Z的顺序排列:AHB(AdvancedHighperformanceBus):先进高性能总线APB(AdvancedPeripheralBus):先进外设总线ADC(Analog-to-DigitalConverter):模拟/数字转换器BKP(Backupregisters):备份寄存器CAN(Cont......
  • STM32之GPIO(General Purpose Input/Output,通用型输入输出)
    文章目录前言一、GPIO简介二、GPIO结构2.1GPIO基本结构2.2GPIO位结构2.2.1输入部分2.2.1输出部分四、GPIO模式4.1浮空/上拉/下拉输入4.2模拟输入4.3开漏/推挽输出4.4复用开漏/推挽输出前言提示:本文主要用作在学习江协科大STM32入门教程后做的归纳总结笔......
  • 基于stm32f103c8t6的蓝牙小车(可以控制车速,以及有数码管显示速度)
    蓝牙模块的理解:蓝牙可以理解为一个无线的串口,手机和单片机之间可以通过蓝牙来发送数据,控制单片机IO口,进而来控制小车,总体的逻辑是,手机发送数据给蓝牙,蓝牙将这个数据再发送给单片机。另外蓝牙的代码跟我们学的串口通信差不多。usart2.c#include"usart2.h" voiduart......
  • STM32H7 HAL库CubeMX 双重ADC模式同步采样详细配置+FFT计算相位差
    前言在电赛备赛期间琢磨了一下ADC同步采样的实现方式,本来是打算直接用AD7606来着,但是搞了半天也没把驱动整出来...考虑到AD7606本身采样率也拉不到太高,于是就花了几天时间把片上ADC配出来了。查资料的时候我发现关于STM32双重ADC模式的资料是真的少,用FFT算两路信号相位差的实例代......
  • STM32Cubemx在FreeRTOS中使用面向对象的方式使用串口
    文章目录前言一、创建FreeRTOS工程二、创建文件对串口进行封装三、代码编写总结前言本篇文章将带大家来学习使用面向对象的方式在FreeRTOS中使用串口,使用面向对象的方法非常适合编写可移植性强的代码,那么这篇文章就带大家来看一下这个代码要怎么写。一、创建FreeRT......
  • Qt串口助手滑块与STM32进行通信,控制步进电机正反转以及转动固定距离
    一、Qt滑块发送端1、简介QT中滑动条的控件叫QSlider,继承自QAbstractSlider类。主要用途是通过滑块的滑动的方式在一定范围内调节某个值。根据调节的后得到的结果去执行一些处理,比如将值写入或者用这个值进行计算,或者进行值传输等等。 通常使用这个控件是希望我们调节滑块......
  • 基于STM32-OLED多级菜单(LCD等等屏幕均可移植)
    一,内容概括:不使用长篇大论1:多级菜单介绍2:实现思路3:代码编写4:总结二,正文1.多级菜单介绍:想必大家看到这里,也知道多级菜单大概是什么;对于还不太清楚的朋友说明以下,多级菜单就是将一块屏幕原本只能显示一种内容,扩展到可以显示很多内容。依据自己的设定显示内容。2.实现思路......