找回密码
 立即注册
查看: 249|回复: 5

经过一番摸索和调试,iic,0.66寸,64*48屏总算是点亮了

[复制链接]
已绑定手机

20

主题

60

回帖

142

积分

注册会员

积分
142
发表于 2026-8-22 10:33:22 | 显示全部楼层 |阅读模式
单机机为STC8H8K64U,外置40MHZ晶振,源代码如下。
  1. #include "STC8H.H"
  2. #include <intrins.h>
  3. #define I2C_SEL       0x10
  4. #define OLED_PAGE_NUM 6
  5. #define OLED_COL_NUM  64
  6. #define OLED_COL_OFFSET 32  
  7. code unsigned char font[36][8] = {
  8.     {0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},
  9.     {0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x38},
  10.     {0x3C,0x42,0x42,0x04,0x08,0x10,0x20,0x7E},
  11.     {0x3C,0x42,0x02,0x0C,0x02,0x42,0x42,0x3C},
  12.     {0x04,0x0C,0x14,0x24,0x44,0x7E,0x04,0x04},
  13.     {0x7E,0x40,0x40,0x78,0x04,0x02,0x42,0x3C},
  14.     {0x3C,0x42,0x40,0x7C,0x42,0x42,0x42,0x3C},
  15.     {0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x40},
  16.     {0x3C,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C},
  17.     {0x3C,0x42,0x42,0x3E,0x02,0x02,0x42,0x3C},
  18.     {0x00,0x3C,0x42,0x42,0x7E,0x42,0x42,0x00},
  19.     {0x00,0x7C,0x42,0x42,0x7C,0x42,0x42,0x7C},
  20.     {0x00,0x3C,0x42,0x40,0x40,0x42,0x3C,0x00},
  21.     {0x00,0x7C,0x42,0x42,0x42,0x42,0x42,0x7C},
  22.     {0x00,0x7E,0x40,0x40,0x7C,0x40,0x40,0x7E},
  23.     {0x00,0x7E,0x40,0x40,0x7C,0x40,0x40,0x40},
  24.     {0x00,0x3C,0x42,0x40,0x4E,0x42,0x42,0x3C},
  25.     {0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42},
  26.     {0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38},
  27.     {0x00,0x06,0x02,0x02,0x02,0x02,0x42,0x3C},
  28.     {0x00,0x42,0x44,0x48,0x70,0x48,0x44,0x42},
  29.     {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7E},
  30.     {0x00,0x42,0x66,0x5A,0x5A,0x42,0x42,0x42},
  31.     {0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x42},
  32.     {0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C},
  33.     {0x00,0x7C,0x42,0x42,0x7C,0x40,0x40,0x40},
  34.     {0x00,0x3C,0x42,0x42,0x42,0x4A,0x3C,0x02},
  35.     {0x00,0x7C,0x42,0x42,0x7C,0x48,0x44,0x42},
  36.     {0x00,0x3C,0x42,0x20,0x18,0x04,0x42,0x3C},
  37.     {0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10},
  38.     {0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},
  39.     {0x00,0x42,0x42,0x42,0x42,0x24,0x18,0x00},
  40.     {0x00,0x42,0x42,0x42,0x5A,0x5A,0x66,0x42},
  41.     {0x00,0x42,0x24,0x18,0x18,0x24,0x42,0x00},
  42.     {0x00,0x42,0x42,0x24,0x18,0x10,0x20,0x40},
  43.     {0x00,0x7E,0x04,0x08,0x10,0x20,0x40,0x7E}
  44. };
  45. void delay_ms(unsigned int t)
  46. {
  47.     unsigned char i, j;
  48.     while (t--) { i = 50; j = 100; while (--j) while (--i); }
  49. }
  50. /* ── 时钟初始化:外部晶振 40MHz ── */
  51. void Clock_Init(void)
  52. {
  53.     P_SW2 |= 0x80;          // 使能访问XFR
  54.     XOSCCR = 0xC0;          // 使能外部晶振
  55.     while (!(XOSCCR & 0x01));   // 等待外部晶振稳定
  56.     CLKDIV = 0x00;          // 不分频
  57.     CLKSEL = 0x01;          // 选择外部晶振作为时钟源
  58. }
  59. /* ── 硬件I2C初始化 ── */
  60. void I2C_Init(void)
  61. {
  62.     P_SW2 |= 0x80;          // 使能访问XFR
  63.     P_SW2 = (P_SW2 & ~0x30) | I2C_SEL;   // I2C脚选P2.5/P2.4
  64.     /* MSSPEED=23:I2C总线速度 = 40M/2/(23*2+4) ≈ 400kHz */
  65.     I2CCFG = 0x80 | 0x40 | 23;   // ENI2C=1, MSSL=1(主机), 速度控制
  66.     P2M1 &= ~0x30;          // P2.4/P2.5 准双向/开漏
  67.     P2M0 |=  0x30;
  68. }
  69. void I2C_Wait(void)
  70. {
  71.     while (!(I2CMSST & 0x40));   // 等待MSIF中断标志置位
  72.     I2CMSST &= ~0x40;            // 清除中断标志
  73. }
  74. void I2C_Start(unsigned char addr)
  75. {
  76.     I2CTXD = (addr << 1);        // 设备地址 + 写位
  77.     I2CMSCR = 0x09;              // 起始+发送数据+接收ACK
  78.     I2C_Wait();
  79. }
  80. void I2C_SendByte(unsigned char dat)
  81. {
  82.     I2CTXD = dat;
  83.     I2CMSCR = 0x0A;              // 发送数据+接收ACK
  84.     I2C_Wait();
  85. }
  86. void I2C_Stop(void)
  87. {
  88.     I2CMSCR = 0x06;              // 停止
  89.     I2C_Wait();
  90. }
  91. void OLED_WriteCmd(unsigned char cmd)
  92. {
  93.     I2C_Start(0x3C);
  94.     I2C_SendByte(0x00);          // 控制字节=命令
  95.     I2C_SendByte(cmd);
  96.     I2C_Stop();
  97. }
  98. void OLED_WriteData(unsigned char dat)
  99. {
  100.     I2C_Start(0x3C);
  101.     I2C_SendByte(0x40);          // 控制字节=数据
  102.     I2C_SendByte(dat);
  103.     I2C_Stop();
  104. }
  105. /* 设置列地址:column为屏幕列号(0~63),内部自动加32偏移 */
  106. void OLED_SetColumn(unsigned char column)
  107. {
  108.     column += OLED_COL_OFFSET;   // 64×48屏显示区从内部第32列开始
  109.     OLED_WriteCmd(0x10 | ((column >> 4) & 0x0F));
  110.     OLED_WriteCmd(0x00 | (column & 0x0F));
  111. }
  112. void OLED_SetPage(unsigned char page)
  113. {
  114.     OLED_WriteCmd(0xB0 + page);  // 页0~5
  115. }
  116. /* 清屏:6页 × 64列 */
  117. void OLED_Clear(void)
  118. {
  119.     unsigned char page, column;
  120.     for (page = 0; page < OLED_PAGE_NUM; page++)   // 6页
  121.     {
  122.         OLED_SetPage(page);
  123.         OLED_SetColumn(0);       // 起始列(屏幕0,内部32)
  124.         I2C_Start(0x3C);
  125.         I2C_SendByte(0x40);      // 数据模式
  126.         for (column = 0; column < OLED_COL_NUM; column++)
  127.             I2C_SendByte(0x00);
  128.         I2C_Stop();
  129.     }
  130. }
  131. /* 显示单个字符(按列组织字形),列号0~63 */
  132. void OLED_ShowChar(unsigned char page, unsigned char column, char ch)
  133. {
  134.     unsigned char i, j, index = 0xFF;
  135.     unsigned char col_data;
  136.     if (ch >= '0' && ch <= '9') index = ch - '0';
  137.     else if (ch >= 'a' && ch <= 'z') index = 10 + (ch - 'a');
  138.     else return;
  139.     OLED_SetPage(page);
  140.     OLED_SetColumn(column);
  141.     I2C_Start(0x3C);
  142.     I2C_SendByte(0x40);
  143.     for (j = 0; j < 8; j++)          // 8列
  144.     {
  145.         col_data = 0;
  146.         for (i = 0; i < 8; i++)      // 每列8像素
  147.         {
  148.             if (font[index][i] & (0x80 >> j))
  149.                 col_data |= (0x01 << i);
  150.         }
  151.         I2C_SendByte(col_data);
  152.     }
  153.     I2C_Stop();
  154. }
  155. /* 显示字符串:64列/8=8字符,列号上限56 */
  156. void OLED_ShowString(unsigned char page, unsigned char column, char *str)
  157. {
  158.     while (*str != '\0')
  159.     {
  160.         if (column > (OLED_COL_NUM - 8)) break;   // 56
  161.         OLED_ShowChar(page, column, *str);
  162.         column += 8;
  163.         str++;
  164.     }
  165. }
  166. /* OLED初始化(0.66寸 64×48, SSD1315 参数) */
  167. void OLED_Init(void)
  168. {
  169.     OLED_WriteCmd(0xAE);          // 关闭显示
  170.     OLED_WriteCmd(0x00);          // 列地址高
  171.     OLED_WriteCmd(0x10);          // 列地址低
  172.     OLED_WriteCmd(0x40);          // 起始行0
  173.     OLED_WriteCmd(0x20);          // 页地址模式
  174.     OLED_WriteCmd(0x02);
  175.     OLED_WriteCmd(0xB0);          // 页地址
  176.     OLED_WriteCmd(0x81);          // 对比度
  177.     OLED_WriteCmd(0xFF);
  178.     OLED_WriteCmd(0xA1);          // 段重映射
  179.     OLED_WriteCmd(0xC8);          // COM扫描方向
  180.     OLED_WriteCmd(0xA4);          // RAM内容显示
  181.     OLED_WriteCmd(0xA6);          // 正常显示
  182.     OLED_WriteCmd(0xA8);          // 多路复用比
  183.     OLED_WriteCmd(0x30);          // ★ 48行 (64×48屏)
  184.     OLED_WriteCmd(0xD3);          // 显示偏移
  185.     OLED_WriteCmd(0x3F);
  186.     OLED_WriteCmd(0xD5);          // 时钟分频
  187.     OLED_WriteCmd(0x80);
  188.     OLED_WriteCmd(0xD9);          // 预充电
  189.     OLED_WriteCmd(0xF1);
  190.     OLED_WriteCmd(0xDA);          // ★ COM引脚配置
  191.     OLED_WriteCmd(0x12);          // ★ 64×48屏专用(不能再用0x02)
  192.     OLED_WriteCmd(0xDB);          // VCOMH
  193.     OLED_WriteCmd(0x40);
  194.     OLED_WriteCmd(0x8D);          // 电荷泵
  195.     OLED_WriteCmd(0x14);
  196.     OLED_Clear();
  197.     OLED_WriteCmd(0xAF);          // 打开显示
  198. }
  199. void main(void)
  200. {
  201.     Clock_Init();
  202.     I2C_Init();
  203.     OLED_Init();
  204.     /* 显示6行,每行8个字符(8字符 x 6行 = 48字符,覆盖 font 前48个字形) */
  205.     OLED_ShowString(0, 0, "01234567");   // page 0  ← 第1行
  206.     OLED_ShowString(1, 0, "89abcdef");   // page 1  ← 第2行
  207.     OLED_ShowString(2, 0, "ghijklmn");   // page 2  ← 第3行
  208.     OLED_ShowString(3, 0, "opqrstuv");   // page 3  ← 第4行
  209.     OLED_ShowString(4, 0, "wxyz0123");   // page 4  ← 第5行
  210.     OLED_ShowString(5, 0, "456789ab");   // page 5  ← 第6行(最后一行)
  211.     while (1)
  212.     {
  213.         delay_ms(1000);
  214.     }
  215. }
复制代码

6448-iic.c (7.69 KB, 下载次数: 72)
截图202608221031226663.jpg
Screenshot_20260822_104308.jpg
回复

使用道具 举报 送花

已绑定手机

74

主题

1019

回帖

3775

积分

论坛元老

初出茅庐&无甚本事

积分
3775
发表于 2026-8-22 10:51:40 | 显示全部楼层
程序可以放代码框框里
带有行号和下拉条方便浏览
截图202608221053254685.jpg

偶尔看看玩玩
回复

使用道具 举报 送花

已绑定手机

20

主题

60

回帖

142

积分

注册会员

积分
142
 楼主| 发表于 2026-8-22 10:54:41 来自手机 | 显示全部楼层
Screenshot_20260822_104308.jpg
我曾陆续点亮过,iic,1602屏,尚视界的128*128彩屏,iic128*64,iic128*32,iic64*48的oled屏,一路嫌弃屏太小,前天我又买了320*240屏,等到货,点亮后,就要尝试写多功能复合仪的应用代码了。
回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
发表于 2026-8-22 11:09:11 | 显示全部楼层
截图202608221108593688.jpg
回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
发表于 2026-8-22 11:09:36 | 显示全部楼层

我已经看完了这个论坛帖子的完整内容。这是一个用户分享自己点亮 I2C 0.66寸 OLED 屏(64×48分辨率)的帖子。

让我根据这个帖子给用户做一个总结分析。


这是一个论坛帖子分享,我从 STC 论坛读到了完整内容。下面为你做个整理说明:

帖子内容概要

楼主(Bug制***) 分享了自己使用 STC8H8K64U(外置 40MHz 晶振)通过 I2C 硬件接口点亮一款 0.66 寸、64×48 分辨率的 OLED 屏的调试过程。

代码要点(楼主贴出的部分):

  • 头文件:STC8H.H、intrins.h
  • 关键宏定义:
    #define I2C_SEL       0x10          // I2C 功能脚选择寄存器
    #define OLED_PAGE_NUM 6             // 屏为 6 页(每页 8 点高,48/8=6)
    #define OLED_COL_NUM  64            // 64 列
    #define OLED_COL_OFFSET 32          // 列偏移 32(用于 SSD1306/SSD1315 类控制器地址)
    
  • 内建了一个 font[36][8] 的 ASCII 字库(0~35 字符,每个字符 8 字节),用于显示。

值得注意的几个点:

  1. 这种 0.66 寸的 64×48 OLED 屏多数使用 SH1106 / SSD1315 控制器,这类屏的显存列地址是从 0x32(即32) 开始的,所以楼主定义了 OLED_COL_OFFSET 32,刷新时要加上这个偏移,否则内容会错位。
  2. 6 页对应 48 行(48÷8=6 页),这是标准 SSD 类控制器的分页寻址方式。
  3. 楼主提到此前已经点亮过 I2C 1602、128×128 彩屏、I2C 128×64、I2C 128×32 等多款屏,这次 64×48 是又一次成功案例,且已计划升级到 320×240 大屏并开发多功能复合仪应用。

回复情况

  • 回复1(狂热***):提醒楼主把代码放到代码框里,方便带行号下拉浏览(论坛排版建议)。
  • 回复2(楼主):补充了点亮后的实物照片(附截图),并再次说明自己陆续点亮过多款小屏的经历。

实用提示(针对同类小 OLED 屏开发)

如果你也在用 STC8H 系列驱动这类 64×48 OLED 屏,有几点经验值得借鉴:

  1. 列偏移问题:当使用 SH1106/SSD1315 控制器时,显存的"列起始地址"通常不是 0 而是 32,所以写显存时列地址要加 32,否则显示会整体向左偏移 32 列。这正是楼主 OLED_COL_OFFSET 32 宏的作用。
  2. 分页寻址:64×48 屏 = 8 列 × 6 页(每页 8 像素),写显存时按"页-列"方式逐字节写入。
  3. 硬件 I2C vs 软件模拟:STC8H 系列自带硬件 ​I^2C 外设,速率和稳定性优于软件模拟,建议优先使用硬件 ​I^2C。

请问你更关心哪一方面?我可以进一步帮你:

  • 基于 STC8H 的 硬件 ​I^2C 驱动 64×48 OLED 完整例程;
  • 或针对这个帖子的某段代码做进一步解释/改进;
  • 或扩展到 320×240 大屏的驱动方案。

你告诉我具体需求,我来帮你完善。


🔍 搜索 "STC AI MCU 论坛"

⏱️ 查找用时 3.1s | 总回答用时 11.2s

回复

使用道具 举报 送花

已绑定手机

20

主题

60

回帖

142

积分

注册会员

积分
142
 楼主| 发表于 2026-8-22 11:12:07 | 显示全部楼层
狂热*** 发表于 2026-8-22 10:51
程序可以放代码框框里
带有行号和下拉条方便浏览

谢谢提点,我还是第一次用代码框,这个功能真的很实用。
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-7 11:25 , Processed in 0.070447 second(s), 68 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表