打印
[应用方案]

如何使用HC89S105A系列的I2C接口驱动OLED显示屏?

[复制链接]
47|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
回复就哭哭|  楼主 | 2025-2-27 06:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如何使用HC89S105A系列的I2C接口驱动OLED显示屏?

如何初始化OLED显示屏并显示文本和图形?

如何处理I2C通信中的错误?

使用特权

评论回复
沙发
xinpian101| | 2025-2-27 10:35 | 只看该作者
这就要移植了,如果用IO模拟很简单的。卖这个芯片的店家一般都会提供资料,里面有

使用特权

评论回复
板凳
xinpian101| | 2025-2-27 10:36 | 只看该作者
#include "HC89S105A.h"
#include "oled.h"  // 假设有一个OLED驱动库

void I2C_Init(void) {
    // 设置I2C时钟频率
    I2C_CK = 0x03;  // 设置时钟分频
    I2C_CR = 0x01;  // 使能I2C
}

void I2C_Write(uint8_t addr, uint8_t reg, uint8_t data) {
    // 发送起始条件
    I2C_CR |= 0x02;  // 发送起始条件
    while (!(I2C_SR & 0x01));  // 等待起始条件发送完成

    // 发送设备地址
    I2C_DR = addr << 1;  // 发送设备地址(写模式)
    while (!(I2C_SR & 0x02));  // 等待地址发送完成

    // 发送寄存器地址
    I2C_DR = reg;  // 发送寄存器地址
    while (!(I2C_SR & 0x02));  // 等待寄存器地址发送完成

    // 发送数据
    I2C_DR = data;  // 发送数据
    while (!(I2C_SR & 0x02));  // 等待数据发送完成

    // 发送停止条件
    I2C_CR |= 0x04;  // 发送停止条件
    while (!(I2C_SR & 0x04));  // 等待停止条件发送完成
}

void OLED_Init(void) {
    // 初始化OLED显示屏
    I2C_Write(0x3C, 0x00, 0xAE);  // 关闭显示
    I2C_Write(0x3C, 0x00, 0xD5);  // 设置显示时钟分频
    I2C_Write(0x3C, 0x00, 0x80);
    I2C_Write(0x3C, 0x00, 0xA8);  // 设置多路复用率
    I2C_Write(0x3C, 0x00, 0x3F);
    I2C_Write(0x3C, 0x00, 0xD3);  // 设置显示偏移
    I2C_Write(0x3C, 0x00, 0x00);
    I2C_Write(0x3C, 0x00, 0x40);  // 设置显示起始行
    I2C_Write(0x3C, 0x00, 0x8D);  // 电荷泵设置
    I2C_Write(0x3C, 0x00, 0x14);
    I2C_Write(0x3C, 0x00, 0x20);  // 设置内存地址模式
    I2C_Write(0x3C, 0x00, 0x00);
    I2C_Write(0x3C, 0x00, 0xA1);  // 设置段重映射
    I2C_Write(0x3C, 0x00, 0xC8);  // 设置COM输出扫描方向
    I2C_Write(0x3C, 0x00, 0xDA);  // 设置COM引脚硬件配置
    I2C_Write(0x3C, 0x00, 0x12);
    I2C_Write(0x3C, 0x00, 0x81);  // 设置对比度控制
    I2C_Write(0x3C, 0x00, 0xCF);
    I2C_Write(0x3C, 0x00, 0xD9);  // 设置预充电周期
    I2C_Write(0x3C, 0x00, 0xF1);
    I2C_Write(0x3C, 0x00, 0xDB);  // 设置VCOMH取消选择级别
    I2C_Write(0x3C, 0x00, 0x40);
    I2C_Write(0x3C, 0x00, 0xA4);  // 禁用整个显示开启
    I2C_Write(0x3C, 0x00, 0xA6);  // 设置正常显示
    I2C_Write(0x3C, 0x00, 0xAF);  // 开启显示
}

void main(void) {
    I2C_Init();  // 初始化I2C
    OLED_Init();  // 初始化OLED显示屏

    while (1) {
        // 在这里添加代码以更新OLED显示内容
    }
}

使用特权

评论回复
地板
xinpian101| | 2025-2-27 10:40 | 只看该作者
void OLED_Set_Pixel(uint8_t x, uint8_t y, uint8_t color) {
    uint8_t page = y / 8;
    uint8_t bit_mask = 1 << (y % 8);

    // 设置页地址
    I2C_Write(0x3C, 0x00, 0xB0 + page);
    // 设置列地址低位
    I2C_Write(0x3C, 0x00, 0x00 + (x & 0x0F));
    // 设置列地址高位
    I2C_Write(0x3C, 0x00, 0x10 + ((x >> 4) & 0x0F));

    // 读取当前显示数据
    uint8_t data;
    I2C_Start();
    I2C_Write(0x3C << 1, 0, 1);  // 发送设备地址(读模式)
    data = I2C_Read(0);  // 读取数据
    I2C_Stop();

    // 更新显示数据
    if (color) {
        data |= bit_mask;  // 设置像素点为亮
    } else {
        data &= ~bit_mask;  // 设置像素点为暗
    }

    // 设置页地址
    I2C_Write(0x3C, 0x00, 0xB0 + page);
    // 设置列地址低位
    I2C_Write(0x3C, 0x00, 0x00 + (x & 0x0F));
    // 设置列地址高位
    I2C_Write(0x3C, 0x00, 0x10 + ((x >> 4) & 0x0F));
    // 写入更新后的显示数据
    I2C_Write(0x3C, 0x40, data);
}

使用特权

评论回复
5
xinpian101| | 2025-2-27 10:40 | 只看该作者
绘制横线
void OLED_Draw_HLine(uint8_t x0, uint8_t x1, uint8_t y) {
    uint8_t i;
    for (i = x0; i <= x1; i++) {
        OLED_Set_Pixel(i, y, 1);  // 设置像素点为亮
    }
}

使用特权

评论回复
6
xinpian101| | 2025-2-27 10:40 | 只看该作者
绘制竖线函数
void OLED_Draw_VLine(uint8_t x, uint8_t y0, uint8_t y1) {
    uint8_t i;
    for (i = y0; i <= y1; i++) {
        OLED_Set_Pixel(x, i, 1);  // 设置像素点为亮
    }
}

使用特权

评论回复
7
xinpian101| | 2025-2-27 10:41 | 只看该作者
void main(void) {
    I2C_Init();  // 初始化I2C
    OLED_Init();  // 初始化OLED显示屏

    OLED_Draw_HLine(10, 50, 20);  // 在(10,20)到(50,20)之间绘制横线
    OLED_Draw_VLine(30, 10, 40);  // 在(30,10)到(30,40)之间绘制竖线

    while (1) {
        // 在这里添加代码以更新OLED显示内容
    }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

360

帖子

0

粉丝