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)
    {
        // 主循环
    }
}
相关推荐
LaoZhangGong12323 分钟前
学习TCP/IP的第1步:ARP数据包
网络·stm32·学习·tcp/ip·以太网·arp·uip
三佛科技-187366133971 小时前
KP521405LGA低功耗5V1A易用高性能BUCK同步降压转换器芯片解析
单片机·嵌入式硬件
Dillon Dong2 小时前
STM32嵌入式:如何使用keil 来获取flash块数据并转换成可视化的数据 来判断源头数据是否错误
stm32·单片机·嵌入式硬件
雨疏风骤12403 小时前
ROM与RAM,储存地址、链接地址以及运行地址
linux·stm32·嵌入式·linux嵌入式
深耕AI4 小时前
【恍然大悟】8位单片机如何处理大数与二进制乘法?
单片机·嵌入式硬件
z20348315204 小时前
智能台灯控制面板
单片机·嵌入式硬件
钿驰科技4 小时前
TC-BL3650驱动板在无刷减速电机的应用
单片机·嵌入式硬件
深耕AI4 小时前
【单片机】解密STC89C52
单片机·嵌入式硬件
三佛科技-134163842124 小时前
FT32F072xx、FT32F072xB、FT32F072x6/x8基于ARM Cortex-M0内核32位单片机分析
arm开发·单片机·嵌入式硬件·智能家居·pcb工艺
清风6666664 小时前
基于单片机的火焰与温度联动检测及声光灭火控制系统
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业