STM32 I2C配置函数及实验

一、I2C配置函数

1. HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

**功能:**I2C主设备向从设备发送数据

参数说明:

复制代码
hi2c:I2C句柄指针,包含I2C外设配置信息
DevAddress:从设备地址(7位地址,库函数内部会自动左移1位)
pData:指向要发送数据缓冲区的指针
Size:要发送数据的字节数
Timeout:传输超时时间(毫秒)

返回值:

复制代码
HAL_OK:传输成功
HAL_ERROR:传输错误
HAL_BUSY:总线忙
HAL_TIMEOUT:传输超时

2. HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

**功能:**I2C主设备从从设备接收数据

参数说明:

复制代码
hi2c:I2C句柄指针
DevAddress:从设备地址(7位地址)
pData:指向接收数据缓冲区的指针
Size:要接收数据的字节数
Timeout:接收超时时间(毫秒)

二、示例实验

1. 实验现象

系统启动后,OLED屏幕会先全屏点亮显示白色(用于硬件测试),然后立即清屏变为全黑,最终屏幕保持黑色显示状态。整个过程中通过I2C总线成功与SSD1306 OLED驱动芯片通信,完成了显示屏的初始化和基本显示控制。

2. 示例代码

I2C初始化

复制代码
void MX_I2C1_Init(void)
{
    hi2c1.Instance = I2C1;                      // 使用I2C1外设
    hi2c1.Init.ClockSpeed = 400000;             // I2C时钟频率400kHz
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;     // 时钟占空比配置
    hi2c1.Init.OwnAddress1 = 0;                 // 主机模式地址设为0
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;  // 7位地址模式
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 禁用双地址
    hi2c1.Init.OwnAddress2 = 0;                 // 第二地址设为0
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 禁用通用呼叫
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;     // 允许时钟拉伸

    if (HAL_I2C_Init(&hi2c1) != HAL_OK)
    {
        Error_Handler();            // 初始化失败进入错误处理
    }
}

OLED初始化

复制代码
/**
  * @brief  检测I2C设备是否存在
  */
ErrorStatus OLED_CheckDevice(uint8_t slave_addr)
{
    uint8_t dummy = 0;
    
    // 发送0字节数据检测设备响应
    if (HAL_I2C_Master_Transmit(&hi2c1, (slave_addr << 1), &dummy, 0, IIC_TIMEOUT) == HAL_OK)
    {
        return SUCCESS;
    }
    
    return ERROR;
}

/**
  * @brief  向OLED写入单字节数据(命令或数据)
  */
ErrorStatus OLED_WriteByte(uint8_t cmd, uint8_t byte)
{
    uint8_t buf[2] = {cmd, byte};  // 数据包:控制字节+数据字节

    if (HAL_I2C_Master_Transmit(&hi2c1, OLED_SLAVER_ADDR << 1, buf, 2, IIC_TIMEOUT) == HAL_OK)
        return SUCCESS;

    printf("OLED_WriteByte 写入失败:cmd=0x%02X byte=0x%02X\r\n", cmd, byte);
    return ERROR;
}

/**
  * @brief  向OLED写入多字节数据
  */
ErrorStatus OLED_WriteBuffer(uint8_t cmd, uint8_t *buffer, uint32_t num)
{
    uint8_t buf[256];
    if(num > sizeof(buf) - 1)
    {
        printf("OLED_WriteBuffer 数据过长(%u)\r\n", num);
        return ERROR;
    }

    buf[0] = cmd;                   // 第一个字节为控制字节
    memcpy(&buf[1], buffer, num);   // 复制数据到缓冲区

    HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, OLED_SLAVER_ADDR << 1, buf, num + 1, IIC_TIMEOUT);

    if (status == HAL_OK)
        return SUCCESS;

    printf("OLED_WriteBuffer 写入失败:cmd=0x%02X len=%u\r\n", cmd, num);
    return ERROR;
}

/**
  * @brief  设置OLED显示位置
  */
void OLED_SetPos(uint8_t y, uint8_t x)
{
    uint8_t pos_buf[3] = {
        0xB0 + y,                   // 页地址命令
        ((x & 0xF0) >> 4) | 0x10,  // 列地址高4位
        (x & 0x0F)                 // 列地址低4位
    };

    OLED_WriteBuffer(OLED_WR_CMD, pos_buf, sizeof(pos_buf));
}

/**
  * @brief  填充整个屏幕
  */
void OLED_Fill(uint8_t fill_data)
{
    uint8_t data_buffer_temp[128] = {0};
    memset(data_buffer_temp, fill_data, 128);

    // 遍历8页,每页128列
    for(uint8_t m = 0; m < 8; m++)
    {
        OLED_SetPos(m, 0);
        OLED_WriteBuffer(OLED_WR_DATA, data_buffer_temp, OLED_ARRAY_SIZE(data_buffer_temp));
    }
}

/**
  * @brief  清屏函数
  */
void OLED_CLS(void)
{
    OLED_Fill(0x00);  // 填充0x00清屏
}

/**
  * @brief  全屏点亮函数
  */
void OLED_FillFull(void)
{
    OLED_Fill(0xFF);  // 填充0xFF全亮
}

/**
  * @brief  OLED初始化
  */
void OLED_Init(void)
{
    HAL_Delay(100);  // 电源稳定延时

    // 等待设备响应
    while (OLED_CheckDevice(OLED_SLAVER_ADDR) != SUCCESS);

    // OLED初始化命令序列
    OLED_WriteByte(OLED_WR_CMD, 0xAE); // 关闭显示
    OLED_WriteByte(OLED_WR_CMD, 0x20); // 设置内存寻址模式
    OLED_WriteByte(OLED_WR_CMD, 0x02); // 页面寻址模式
    OLED_WriteByte(OLED_WR_CMD, 0xB0); // 设置页起始地址
    OLED_WriteByte(OLED_WR_CMD, 0xA1); // 设置列扫描方向正常
    OLED_WriteByte(OLED_WR_CMD, 0xC8); // 设置行扫描方向正常
    OLED_WriteByte(OLED_WR_CMD, 0x00); // 设置列地址低位
    OLED_WriteByte(OLED_WR_CMD, 0x10); // 设置列地址高位
    OLED_WriteByte(OLED_WR_CMD, 0x40); // 设置起始行地址
    OLED_WriteByte(OLED_WR_CMD, 0x81); // 设置对比度控制
    OLED_WriteByte(OLED_WR_CMD, 0xFF); // 对比度最大值
    OLED_WriteByte(OLED_WR_CMD, 0xA1); // 设置列映射
    OLED_WriteByte(OLED_WR_CMD, 0xA6); // 设置正常显示
    OLED_WriteByte(OLED_WR_CMD, 0xA8); // 设置多路复用率
    OLED_WriteByte(OLED_WR_CMD, 0x3F); // 1/64占空比
    OLED_WriteByte(OLED_WR_CMD, 0xA4); // 整个显示开启
    OLED_WriteByte(OLED_WR_CMD, 0xD3); // 设置显示偏移
    OLED_WriteByte(OLED_WR_CMD, 0x00); // 无偏移
    OLED_WriteByte(OLED_WR_CMD, 0xD5); // 设置显示时钟分频
    OLED_WriteByte(OLED_WR_CMD, 0xF0); // 设置振荡器频率
    OLED_WriteByte(OLED_WR_CMD, 0xD9); // 设置预充电周期
    OLED_WriteByte(OLED_WR_CMD, 0x22); // 
    OLED_WriteByte(OLED_WR_CMD, 0xDA); // 设置COM引脚硬件配置
    OLED_WriteByte(OLED_WR_CMD, 0x12); // 
    OLED_WriteByte(OLED_WR_CMD, 0xDB); // 设置VCOMH电平
    OLED_WriteByte(OLED_WR_CMD, 0x20); // 
    OLED_WriteByte(OLED_WR_CMD, 0x8D); // 设置电荷泵
    OLED_WriteByte(OLED_WR_CMD, 0x14); // 使能电荷泵
    OLED_WriteByte(OLED_WR_CMD, 0xAF); // 开启显示

    OLED_CLS();         // 清屏
    OLED_FillFull();    // 全屏点亮测试
}

主函数

复制代码
int main(void)
{
    HAL_Init();                     // 初始化HAL库
    SystemClock_Config();           // 配置系统时钟为72MHz
    MX_USART1_UART_Init();          // 初始化串口用于调试信息输出
    DWT_Init();                     // 启动DWT计数器用于精确延时
    MX_I2C1_Init();                 // 初始化I2C1总线
    OLED_Init();                    // 初始化OLED显示屏

    while (1)
    {
        // 主循环
    }
}
相关推荐
BSD_CGQ5 小时前
FSR传感器STM32 DMA高速采样工程实现(高精度、低CPU占用)
stm32·单片机·嵌入式硬件·压力传感器·源头工厂·柔性薄膜压力传感器·可变电阻压力传感器
芯岭技术郦8 小时前
32 位 ARM® Cortex®-M0+ 内核MCU普冉MS32C001-C
单片机·嵌入式硬件
骑着毛驴数星星8 小时前
STM32 CAN波特率与采样点计算,基于HAL库
stm32·单片机·嵌入式硬件
zhangrelay9 小时前
Arduino-MEGA-ESP单片机理论课笔记02-硬件-2026
笔记·单片机·嵌入式硬件
艾芯微科技9 小时前
钰泰 ETA5055V330DD1E|SOT-223 3.3V LDO,低压差、大电流线性稳压选型分享
网络·单片机·嵌入式硬件·集成测试·51单片机
新晨单片机设计10 小时前
S023A-基于STM32单片机智能插座【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·单片机智能插座
EatFans11 小时前
全栈自造 Status Deck(四):硬件终于到了,从点亮屏幕到跑通第一个 Demo
单片机·物联网
qq_4017004111 小时前
STM32 GPIO 精讲|推挽 / 开漏 / 上拉浮空,工程选型避坑
stm32·单片机·嵌入式硬件
创界工坊工作室12 小时前
19-基于单片机的宠物喂养控制系统设计
stm32·单片机·嵌入式硬件·proteus·宠物
兴通物联科技14 小时前
自助终端涉外证件核验选型:XT2010MRZ 嵌入式护照识别模块技术解析
单片机·嵌入式硬件·计算机视觉·硬件架构