四针脚0.96英寸OLED显示屏模块的具体参数如下表所示。
参数名称 | 参数特性 |
分辨率 | 128x64像素 |
通信方式 | IIC |
驱动芯片 | SSD1306 |
屏幕颜色 | 白色、蓝色或黄蓝双色 |
元件:
- 四针脚0.96英寸OLED显示屏模块
- ESP32 DEVKIT_C开发板
- 杜邦线
- USB Type-C
接线:
ESP32 DEVKIT_C | DHT11 |
VIN或3V3 | VCC |
GND | GND |
D25 | SCL |
D26 | SDA |
注:OLED中的SCL和SDA引脚也可以连接到ESP32中的其他硬/软件IIC引脚,只需在代码中做出相应的配置。
制作任意字符点阵:
取模软件:
https://download.csdn.net/download/qq_44955826/90075081?spm=1001.2014.3001.5501
取模方法可参考该博客:
micropython oled中文_MicroPython实例之TPYBoard开发板控制OLED显示中文-CSDN博客
代码:
OLED.py
import time
from machine import Pin
from SSD1306 import SSD1306_I2Cfrom machine import I2C
#i2c = I2C(0) #初始化IIC0,使用默认引脚“SCL=18、SDA=19”,传输速度:400 Kbps
i2c = I2C(1) #初始化IIC1,使用默认引脚“SCL=25、SDA=26”,传输速度:400 Kbps#from machine import SoftI2C
#i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
#i2c = SoftI2C(scl=Pin(33), sda=Pin(32), freq=400000)OLED = SSD1306_I2C(128, 64, i2c) #屏幕长度:128像素;屏幕宽度:64像素#用到的UTF-8编码字库
fonts = {0xE6B8A9: #“温”的UTF-8编码[0x00,0x23,0x12,0x12,0x83,0x42,0x42,0x13,0x10,0x27,0xE4,0x24,0x24,0x24,0x2F,0x00,0x00,0xF8,0x08,0x08,0xF8,0x08,0x08,0xF8,0x00,0xFC,0xA4,0xA4,0xA4,0xA4,0xFE,0x00], #温0xE6B9BF:[0x00,0x27,0x14,0x14,0x87,0x44,0x44,0x17,0x11,0x21,0xE9,0x25,0x23,0x21,0x2F,0x00,0x00,0xF8,0x08,0x08,0xF8,0x08,0x08,0xF8,0x20,0x20,0x24,0x28,0x30,0x20,0xFE,0x00], #湿0xE5BAA6:[0x01,0x00,0x3F,0x22,0x22,0x3F,0x22,0x22,0x23,0x20,0x2F,0x24,0x42,0x41,0x86,0x38,0x00,0x80,0xFE,0x20,0x20,0xFC,0x20,0x20,0xE0,0x00,0xF0,0x10,0x20,0xC0,0x30,0x0E], #度0xE58589:[0x01,0x21,0x11,0x09,0x09,0x01,0xFF,0x04,0x04,0x04,0x04,0x08,0x08,0x10,0x20,0xC0,0x00,0x08,0x08,0x10,0x20,0x00,0xFE,0x40,0x40,0x40,0x40,0x42,0x42,0x42,0x3E,0x00], #光0xE785A7:[0x00,0x7D,0x44,0x44,0x44,0x44,0x7D,0x44,0x44,0x44,0x44,0x7C,0x00,0x48,0x44,0x84,0x00,0xFC,0x44,0x44,0x44,0x94,0x08,0xFC,0x84,0x84,0x84,0xFC,0x00,0x88,0x44,0x44], #照0xE7839F:[0x10,0x13,0x12,0x16,0x5A,0x52,0x53,0x92,0x12,0x12,0x12,0x2A,0x27,0x42,0x43,0x82,0x00,0xFE,0x02,0x22,0x22,0x22,0xFE,0x22,0x22,0x52,0x4A,0x8A,0x02,0x02,0xFE,0x02], #烟0xE99BBE:[0x00,0x3F,0x01,0x7F,0x49,0x01,0x1D,0x08,0x1F,0x68,0x07,0x7A,0x0F,0x04,0x18,0x00,0x00,0xF8,0x00,0xFC,0x24,0x00,0x70,0x00,0xF0,0x20,0xC0,0x3C,0xE0,0x20,0xC0,0x00], #雾0xE28483: [0x00,0x00,0x00,0x00,0x20,0x33,0x04,0x08,0x08,0x08,0x08,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x40,0x80,0x00,0x00,0x00,0x00], #℃
}#先找出字符的utf-8编码,再在fonts中找到对应的点阵,最后将点阵输出到OLED上,从而实现在OLED上显示汉字和特殊字符
def chinese(ch_str, x_axis, y_axis): offset_ = 0 for k in ch_str: code = 0x00 # 将中文转成16进制编码 data_code = k.encode("utf-8")code |= data_code[0] << 16code |= data_code[1] << 8code |= data_code[2]byte_data = fonts[code]for y in range(0, 16):a_ = bin(byte_data[y]).replace('0b', '')while len(a_) < 8:a_ = '0'+ a_b_ = bin(byte_data[y+16]).replace('0b', '')while len(b_) < 8:b_ = '0'+ b_for x in range(0, 8):OLED.pixel(x_axis + offset_ + x, y+y_axis, int(a_[x])) OLED.pixel(x_axis + offset_ + x +8, y+y_axis, int(b_[x])) offset_ += 16while True:chinese('温度', 0, 0)OLED.text(':23.67', 32, 5) #在第35行和第5列像素的位置存入字符“:23.67”chinese('℃', 80, 0)chinese('湿度', 0, 16)OLED.text(':53%', 32, 21)OLED.show() #将上述存入到SSD1306芯片中的字符显示到屏幕上time.sleep(1)OLED.fill(0) # 清屏chinese('光照', 0, 32)OLED.text(':12345LX', 32, 37)chinese('烟雾', 0, 48)OLED.text(':1234', 32, 53)OLED.show()time.sleep(1)OLED.fill(0)OLED.text('NO CLEAR SCREEN', 0, 5) #不清屏的后果
SSD1306.py
#MicroPython SSD1306 OLED driver, I2C and SPI interfaces created by Adafruitimport time
import framebuf# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xa4)
SET_NORM_INV = const(0xa6)
SET_DISP = const(0xae)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xa0)
SET_MUX_RATIO = const(0xa8)
SET_COM_OUT_DIR = const(0xc0)
SET_DISP_OFFSET = const(0xd3)
SET_COM_PIN_CFG = const(0xda)
SET_DISP_CLK_DIV = const(0xd5)
SET_PRECHARGE = const(0xd9)
SET_VCOM_DESEL = const(0xdb)
SET_CHARGE_PUMP = const(0x8d)class SSD1306:def __init__(self, width, height, external_vcc):self.width = widthself.height = heightself.external_vcc = external_vccself.pages = self.height // 8# Note the subclass must initialize self.framebuf to a framebuffer.# This is necessary because the underlying data buffer is different# between I2C and SPI implementations (I2C needs an extra byte).self.poweron()self.init_display()def init_display(self):for cmd in (SET_DISP | 0x00, # off# address settingSET_MEM_ADDR, 0x00, # horizontal# resolution and layoutSET_DISP_START_LINE | 0x00,SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0SET_MUX_RATIO, self.height - 1,SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0SET_DISP_OFFSET, 0x00,SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,# timing and driving schemeSET_DISP_CLK_DIV, 0x80,SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,SET_VCOM_DESEL, 0x30, # 0.83*Vcc# displaySET_CONTRAST, 0xff, # maximumSET_ENTIRE_ON, # output follows RAM contentsSET_NORM_INV, # not inverted# charge pumpSET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,SET_DISP | 0x01): # onself.write_cmd(cmd)self.fill(0)self.show()def poweroff(self):self.write_cmd(SET_DISP | 0x00)def contrast(self, contrast):self.write_cmd(SET_CONTRAST)self.write_cmd(contrast)def invert(self, invert):self.write_cmd(SET_NORM_INV | (invert & 1))def show(self):x0 = 0x1 = self.width - 1if self.width == 64:# displays with width of 64 pixels are shifted by 32x0 += 32x1 += 32self.write_cmd(SET_COL_ADDR)self.write_cmd(x0)self.write_cmd(x1)self.write_cmd(SET_PAGE_ADDR)self.write_cmd(0)self.write_cmd(self.pages - 1)self.write_framebuf()def fill(self, col):self.framebuf.fill(col)def pixel(self, x, y, col):self.framebuf.pixel(x, y, col)def scroll(self, dx, dy):self.framebuf.scroll(dx, dy)def text(self, string, x, y, col=1):self.framebuf.text(string, x, y, col)class SSD1306_I2C(SSD1306):def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):self.i2c = i2cself.addr = addrself.temp = bytearray(2)# Add an extra byte to the data buffer to hold an I2C data/command byte# to use hardware-compatible I2C transactions. A memoryview of the# buffer is used to mask this byte from the framebuffer operations# (without a major memory hit as memoryview doesn't copy to a separate# buffer).self.buffer = bytearray(((height // 8) * width) + 1)self.buffer[0] = 0x40 # Set first byte of data buffer to Co=0, D/C=1self.framebuf = framebuf.FrameBuffer1(memoryview(self.buffer)[1:], width, height)super().__init__(width, height, external_vcc)def write_cmd(self, cmd):self.temp[0] = 0x80 # Co=1, D/C#=0self.temp[1] = cmdself.i2c.writeto(self.addr, self.temp)def write_framebuf(self):# Blast out the frame buffer using a single I2C transaction to support# hardware I2C interfaces.self.i2c.writeto(self.addr, self.buffer)def poweron(self):passclass SSD1306_SPI(SSD1306):def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):self.rate = 10 * 1024 * 1024dc.init(dc.OUT, value=0)res.init(res.OUT, value=0)cs.init(cs.OUT, value=1)self.spi = spiself.dc = dcself.res = resself.cs = csself.buffer = bytearray((height // 8) * width)self.framebuf = framebuf.FrameBuffer1(self.buffer, width, height)super().__init__(width, height, external_vcc)def write_cmd(self, cmd):self.spi.init(baudrate=self.rate, polarity=0, phase=0)self.cs.high()self.dc.low()self.cs.low()self.spi.write(bytearray([cmd]))self.cs.high()def write_framebuf(self):self.spi.init(baudrate=self.rate, polarity=0, phase=0)self.cs.high()self.dc.high()self.cs.low()self.spi.write(self.buffer)self.cs.high()def poweron(self):self.res.high()time.sleep_ms(1)self.res.low()time.sleep_ms(10)self.res.high()