STM32硬件I2C的注意事项

文章目录

最近在研究I2C的屏幕使用。
有两种使用方式,软件模拟I2C、硬件HAL使用I2C。

软件模拟I2C

发送数据是通过设置引脚的高低电平实现的。

c 复制代码
/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)(x))
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_7, (BitAction)(x))

/*引脚初始化*/
void OLED_I2C_Init(void)
{
	// 先关闭 I2C1 避免 PB6/PB7 被干扰
   // RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, DISABLE);
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i++)
	{
		OLED_W_SDA(Byte & (0x80 >> i));
		OLED_W_SCL(1);
		OLED_W_SCL(0);
	}
	OLED_W_SCL(1);	//额外的一个时钟,不处理应答信号
	OLED_W_SCL(0);
}

硬件的实现方式

c 复制代码
/**
 * @brief 向OLED发送指令
 */
void OLED_SendCmd(uint8_t cmd) {
  static uint8_t sendBuffer[2] = {0};
  sendBuffer[1] = cmd;
  OLED_Send(sendBuffer, 2);
}

/**
 * @brief 向OLED发送数据的函数
 * @param data 要发送的数据
 * @param len 要发送的数据长度
 * @return None
 * @note 此函数是移植本驱动时的重要函数 将本驱动库移植到其他平台时应根据实际情况修改此函数
 */

#define I2C_TIMEOUT 100  // 超时时间(单位:ms)
uint8_t OLED_Send(uint8_t *data, uint8_t len) {
//  HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDRESS, data, len, HAL_MAX_DELAY);

	HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDRESS, data, len, I2C_TIMEOUT);

	  if (status != HAL_OK) {
	    // 打印错误(如果你有串口)
	    // printf("I2C Error: %d\n", status);

	    // 重置 I2C
	    I2C_Reset(&hi2c1);

	    // 尝试重发一次
	    status = HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDRESS, data, len, I2C_TIMEOUT);

	    // 如果还是不行,返回失败
	    if (status != HAL_OK) {
	      return 0;  // 失败
	    }
	  }
	  return 1;  // 成功

}

HAL_I2C_Master_Transmit 会引起卡死的操作,所以要设置一下超时时间为100ms。

也不知道底层是怎么配置的。

驱动 IC 为 SSD1306,程序重启的时候需要重新配置一下I2C,不然对应的硬件端口会卡死。

相关推荐
恒锐丰小瑞2 小时前
率能SS8841T 40V/2.5A/双通道H桥驱动芯片,PWM控制接口与低导通电阻(350mΩ),用于POS打印机/安防相机/机器人
单片机·嵌入式硬件·机器人
zcmodeltech3 小时前
钢铁冶金沙盘模型控制系统设计与实现:高炉-连铸-热轧多工序联动方案
分布式·stm32·单片机·嵌入式硬件·交互
徽京人4 小时前
VS Code 接入Esp 32步骤
vscode·单片机·嵌入式硬件
QH139292318805 小时前
Keysight N5183B N5183B 微波模拟信号发生器
网络·单片机·嵌入式硬件·集成测试·信息与通信
笨笨饿6 小时前
#110_SCH3000 平台图传系统配置指南:从 DVP 摄像头到 UVC/WiFi 双通道传输
c语言·stm32·单片机·嵌入式硬件·物联网·vim
捷瑞电子工坊6 小时前
FreeRTOS事件组:多任务同步的利器
stm32·嵌入式·freertos·实时操作系统·标准外设库·事件组·任务同步
笨笨饿7 小时前
#109_BK7258 蓝牙 A2DP 音频数据通路深度解析
python·stm32·单片机·mcu·物联网·编辑器·音视频
千秋岁rr8 小时前
5.0 TIM
单片机·嵌入式硬件
qq_401700418 小时前
ADC基准电压与参考电压详细解读:以STM32和28335为例
stm32·单片机·嵌入式硬件
小僧景贤8 小时前
STM32 startup.s 启动文件与 .map 映射文件深度技术解析(md/hd 版本差异化对比)
stm32·内存映射·startup.s·map 文件·单片机启动流程