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)
    {
        // 主循环
    }
}
相关推荐
小李独爱秋1 天前
“bootmgr is compressed”错误:根源、笔记本与台式机差异化解决方案深度指南
运维·stm32·单片机·嵌入式硬件·文件系统·电脑故障
进击的小头1 天前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机
宵时待雨1 天前
STM32笔记归纳8:时钟
笔记·stm32·单片机·嵌入式硬件
JJRainbow1 天前
SN75176 芯片设计RS-232 转 RS-485 通信模块设计原理图
stm32·单片机·嵌入式硬件·fpga开发·硬件工程
不做无法实现的梦~1 天前
PX4编译环境配置和qgc配置安装教程(2)
linux·stm32
宁静致远20211 天前
STM32模拟IIC读取PCF8563
stm32·单片机·嵌入式硬件
三佛科技-134163842121 天前
宠物洗澡打泡机方案,宠物泡泡机MCU方案开发设计分享
单片机·嵌入式硬件·物联网·智能家居·pcb工艺·宠物
芯岭技术1 天前
低成本315/433M接收芯片 XL420 SOP8封装,支持 1527 等常见 OOK编码
单片机·嵌入式硬件
Wangshanjie_981 天前
【通讯协议】-01、Modbus协议
单片机·信息与通信
听风吹雨yu1 天前
STM32F407-MD5码计算/Digest认证计算
stm32·单片机·嵌入式硬件