指甲盖大小的 ESP32S3 SuperMini

Esp32s3 Supermini是一块仅有指甲盖大小的超级迷你开发板,非常适合开发小东西的。还是我买早了,现在都有自带液晶屏的那种组合一体板了。

  • 开启芯片内部的虚拟串口

因为这块板子为了追求小体积,所以直接把常规的串口芯片给省略了,而是改用芯片内部自带的虚拟串口,因此我们在操作之前要先把虚拟串口的功能激活起来。否则很可能会造成程序虚假写入的现象,就是表面上看我们已经把程序成功写入到芯片了,但是程序没有跑起来(根本就没有成功写入到芯片内部)

我们在Arduino IDE 中编写一个串口打印消息和闪烁板载LED等的程序(这个板载LED灯是TypeC插口旁边红色的LED,连接的是芯片的第48号端口)

我们选择芯片类型为“ESP32S3 Dev Momule”,注意芯片三叔的选择设置,一定要把“USB CDC On Boot”设置为“Enable”激活状态。然后把程序烧写到开发板中,就可以看到串口回传的打印消息、LED灯不断闪烁了。

    二.写入micropython固件

    从micropython.org官网中下载固件,注意下载ESP32S3下面的4M存储的固件就可以,下载完成后,就可以用乐鑫的烧写软件 flash_download_tools.exe软件,把固件烧写到芯片中了。

    把固件烧写到芯片后,需要拔出芯片,再重新插入,打开thonny(注意了,需要最新版本的,从官网上下载,否则可能无法识别插入的设备),这样我们就能在设备中看到这块esp32s3 supermini了。

    三.Python编程

为了开发效果,我给ESP32S3 Supermini配上一块迷你液晶屏,这款液晶屏是SD1306驱动的64x16的,系统自带的英文字库大小是8x8大小的,所以这款屏幕每行可以显示8个英文字符,一共显示2行。

我们把开发板插入到电脑中,打开Thonny编辑软件,就可以编写这个屏幕的显示驱动程序了。

迷你液晶屏驱动文件源代码:  main.py

from machine import I2C, Pin

from ssd1306mini import SSD1306_I2C

import time

def main():

    i2c = I2C(1, scl=Pin(9), sda=Pin(8))

    oled = SSD1306_I2C(i2c, 0x3c, 64, 16)

    oled.show()

    time.sleep(2)

   

    oled.fill()

    oled.text("Hello", 0, 0)

    oled.text("World", 0, 8)

    oled.show()

   

if __name__ == "__main__":

    main()

四.迷你液晶屏的显示避坑

这个ssd1306mini.py液晶屏驱动库文件是我自己改编的。这款液晶屏的驱动过程是有一个很大的坑:

这块液晶屏是64x16,但是在芯片的内部,其实用的是128x16的驱动完全一致,软件部分完全一样的。不同的其实是硬件部分,工厂在生产这款液晶屏时,把原来的128个列的控制引脚,取中间的64个列连接到屏幕中,而把两旁的64个列的控制引脚直接忽略了。

因此我们在写这个迷你屏的驱动库是,完全可以参考128x16的标准库来进行修改,这样很快就能写出自己的驱动库文件了

迷你屏的驱动库文件  ssd1306mini.py 的源代码:

##   ssd1306mini.py  #######################################################

# MicroPython SSD1306 64x16 (128x16)

# ssd1306 64x16的屏幕内部实际上是128x16(仅把其中间的64个控制连接到屏幕上,两边的控制直接忽略)

import time

import framebuf

class SSD1306_I2C():

    def __init__(self, i2c, addr=0x3c, width=128, height=16, external_vcc=False):

        if width==64:

            self.width=128   #强制把64x16更改为128x16

        else:

            self.width=128

        self.height = 16

        self.external_vcc = external_vcc

        self.i2c = i2c

        self.addr = addr

        self.buffer = bytearray()   # 创建空数据,然后往里面填上256个数据  相当于创建一个有初始值的长度256的字节数组

        # 第0页 前面的0——127个数据  真正显示在屏幕上的是中间的 32——95 数据,两边的数据补 0

        self.buffer.extend(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

        self.buffer.extend(b'\x01\x01\x01\x01\x01\x01\x01\x01\x11\x11\x11\x11\x11\x11\x11\x11\x03\x03\x03\x03\x03\x03\x03\x03\x33\x33\x33\x33\x33\x33\x33\x33\x07\x07\x07\x07\x07\x07\x07\x07\x77\x77\x77\x77\x77\x77\x77\x77\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\xff\xff\xff\xff')

        self.buffer.extend(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

        # 第1页 后面的128——255个数据  真正显示在屏幕上的是中间的 160——223 数据,两边的数据补 0

        self.buffer.extend(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

        self.buffer.extend(b'\x01\x01\x01\x01\x01\x01\x01\x01\x11\x11\x11\x11\x11\x11\x11\x11\x03\x03\x03\x03\x03\x03\x03\x03\x33\x33\x33\x33\x33\x33\x33\x33\x07\x07\x07\x07\x07\x07\x07\x07\x77\x77\x77\x77\x77\x77\x77\x77\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\xff\xff\xff\xff')

        self.buffer.extend(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

        self.framebuf = framebuf.FrameBuffer(self.buffer, 128, 16, framebuf.MONO_VLSB) # 再创建一个128 x 16 的帧缓冲区

       

        self.init_display()

    def init_display(self):

        for cmd in [

            0xAE,       # 关闭显示

            0x20, 0x00, # 页寻址模式

            0xB0,       # 设置页起始地址

            0xC8,       # COM扫描方向

            0x00,       # 设置低列地址

            0x10,       # 设置高列地址

            0x40,       # 设置显示开始行

            0x81, 0xFF, # 设置对比度

            0xA1,       # 段重映射

            0xA8, 0x0F, # 设置多路复用率(16-1)

            0xD3, 0x00, # 设置显示偏移

            0xD5, 0xF0, # 设置显示时钟分频

            0xD9, 0x22, # 设置预充电周期

            0xDA, 0x02, # 设置COM引脚硬件配置

            0xDB, 0x49, # 设置VCOMH

            0x8D, 0x14, # 电荷泵设置

            0xA4,       # 全局显示开启

            0xA6,       # 正常显示

            0xAF        # 开启显示

        ]:

            self.write_cmd(cmd)

        #self.fill(0)

        self.show()

   

    def show(self):

        self.write_cmd(0xB0)  # 第0页

        self.write_cmd(0x10)

        self.write_cmd(0x01)

        self.write_data(self.buffer[0:96])

       

        self.write_cmd(0xB1)  # 第1页

        self.write_cmd(0x10)

        self.write_cmd(0x01)

        self.write_data(self.buffer[128:224])

    def write_cmd(self, cmd):

        self.i2c.writeto(self.addr, bytearray([0x80, cmd]))

    def write_data(self, data):

        self.i2c.writeto(self.addr, b'\x40' + data)

    def fill(self, col=0):

        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+32, y, col)

更多推荐