`from machine import Pin, SoftI2C
import time
import framebuf
import urandom as random
========== SSD1306 I2C 驱动 ==========
class SSD1306_I2C:
def __init__(self, width, height, i2c, addr=0x3C):
self.width = width
self.height = height
self.i2c = i2c
self.addr = addr
self.buffer = bytearray(self.height * self.width // 8)
self.fb = framebuf.FrameBuffer(self.buffer, width, height, framebuf.MONO_VLSB)
self._init_display()
def _write_cmd(self, cmd):
self.i2c.writeto(self.addr, b'\x00' + bytes([cmd]))
def _init_display(self):
cmds = [
0xAE, 0xD5, 0x80, 0xA8, self.height - 1,
0xD3, 0x00, 0x40, 0x8D, 0x14, 0x20, 0x00,
0xA1, 0xC8, 0xDA, 0x02 if self.height == 32 else 0x12,
0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40,
0xA4, 0xA6, 0xAF
]
for c in cmds:
self._write_cmd(c)
self.clear(); self.show()
def clear(self):
self.fb.fill(0)
def show(self):
for page in range(self.height // 8):
self._write_cmd(0xB0 + page)
self._write_cmd(0x00)
self._write_cmd(0x10)
s = page * self.width
self.i2c.writeto(self.addr, b'\x40' + self.buffer[s:s + self.width])
========== I2C 扫描 ==========
def find_oled():
for scl, sda in [(22,21),(22,18),(4,5),(14,27),(15,2)]:
i2c = SoftI2C(scl=Pin(scl), sda=Pin(sda), freq=400000)
devs = i2c.scan()
if 0x3C in devs or 0x3D in devs:
a = 0x3C if 0x3C in devs else 0x3D
print("OLED: SCL=%d SDA=%d 0x%02X" % (scl, sda, a))
return i2c, a
print("全扫...")
for scl in range(0, 40):
for sda in range(0, 40):
if scl == sda: continue
try:
i2c = SoftI2C(scl=Pin(scl), sda=Pin(sda), freq=400000)
devs = i2c.scan()
if 0x3C in devs or 0x3D in devs:
a = 0x3C if 0x3C in devs else 0x3D
print("OLED: SCL=%d SDA=%d 0x%02X" % (scl, sda, a))
return i2c, a
except: pass
return None, 0
print("=== OLED 暴力刷新率测试 ===")
i2c, addr = find_oled()
if i2c is None:
print("没找到 OLED,检查接线")
raise SystemExit
W, H = 128, 64
oled = SSD1306_I2C(W, H, i2c, addr)
fb = oled.fb
========== 测试函数 ==========
def run_test(name, draw_func, frames=200):
"""跑一个测试,返回 FPS"""
oled.clear(); oled.show()
oled.fb.text(name, 0, 28)
oled.show()
time.sleep(0.5)
t0 = time.ticks_ms()
for i in range(frames):
draw_func(i)
oled.show()
t1 = time.ticks_ms()
elapsed = time.ticks_diff(t1, t0) / 1000.0
fps = frames / elapsed if elapsed > 0 else 0
# 显示结果
oled.clear()
oled.fb.text(name, 0, 0)
oled.fb.text("FPS: %.1f" % fps, 0, 20)
oled.fb.text("%d frames" % frames, 0, 36)
oled.fb.text("%.2f sec" % elapsed, 0, 50)
oled.show()
print("[%s] %.1f FPS %d帧 %.2f秒" % (name, fps, frames, elapsed))
time.sleep(2)
return fps
--- 测试1: 纯填充翻转 ---
def test_fill(i):
fb.fill(i & 1)
--- 测试2: 随机像素点 ---
def test_random_pixel(i):
fb.fill(0)
for _ in range(200):
fb.pixel(random.randint(0, W-1), random.randint(0, H-1), 1)
--- 测试3: 扫描线 ---
def test_scanline(i):
fb.fill(0)
y = i % H
fb.hline(0, y, W, 1)
fb.hline(0, (y + H // 2) % H, W, 1)
--- 测试4: 弹跳方块 ---
def test_bounce_box(i):
fb.fill(0)
bx = (i * 3) % (W - 30)
by = (i * 2) % (H - 15)
fb.fill_rect(bx, by, 30, 15, 1)
--- 测试5: 全屏随机噪点 ---
def test_noise(i):
for y in range(H):
for x in range(0, W, 8):
fb.fill_rect(x, y, 8, 1, random.getrandbits(1))
--- 测试6: 旋转线段 ---
def test_lines(i):
fb.fill(0)
cx, cy = W // 2, H // 2
a = i % 64
fb.line(cx, cy, a * 2, 0, 1)
fb.line(cx, cy, W - a * 2, H, 1)
fb.line(cx, cy, 0, a, 1)
fb.line(cx, cy, W, H - a, 1)
--- 测试7: 文字刷屏 ---
def test_text_flood(i):
fb.fill(0)
for row in range(8):
fb.text("TEST%03d" % (i + row), 0, row * 8)
--- 测试8: 矩形套娃 ---
def test_rect_nest(i):
fb.fill(0)
s = (i % 16) + 1
for r in range(0, min(W, H) // 2, s):
fb.rect(r, r, W - r * 2, H - r * 2, 1)
========== 跑全部测试 ==========
tests = [
("Fill", test_fill),
("Pixel", test_random_pixel),
("ScanLine", test_scanline),
("BounceBox", test_bounce_box),
("Noise", test_noise),
("Lines", test_lines),
("TextFlood", test_text_flood),
("RectNest", test_rect_nest),]
results = []
for name, func in tests:
fps = run_test(name, func, frames=200)
results.append((name, fps))
========== 汇总 ==========
oled.clear()
oled.fb.text("== RESULTS ==", 0, 0)
for idx, (name, fps) in enumerate(results):
y = 12 + idx * 6
if y > 56:
break
oled.fb.text("%s %.1f" % (name, fps), 0, y)oled.show()
print()
print("========== 汇总 ==========")
avg = sum(f for _, f in results) / len(results)
best = max(results, key=lambda x: x[1])
worst = min(results, key=lambda x: x[1])
for name, fps in results:
print(" %-10s %.1f FPS" % (name, fps))print("--------------------------")
print(" 平均: %.1f FPS" % avg)
print(" 最快: %s %.1f FPS" % (best[0], best[1]))
print(" 最慢: %s %.1f FPS" % (worst[0], worst[1]))
print("========== 完成 ==========")
`
觉得内容不错?我要