[其它] FireBeetle 2 ESP32 P4 开发板的显示屏驱动

[复制链接]
189|0
Lily李 发表于 2025-10-3 08:42 | 显示全部楼层 |阅读模式
本帖最后由 Lily李 于 2025-10-3 09:07 编辑

申请原创
@21小跑堂

FireBeetle 2 ESP32 P4 开发板上缺少必要的显示器件,为它配上一款占用资源少的OLED屏是一个合理的选择。
为此,可选取I2C接口的OLED屏为驱动目标。驱动方式有2中,即以硬件方式和软件模拟方式,从通用性的角度出发,这里选取的是软件模拟方式。
显示屏与开发板的连接关系为:
SDA----GPIO7
SCL----GPIO8
为此,在选取python编程的情况下,其相应的设计前提是导入 Pin timeutime
from machine import Pin
import time
import utime

此外,为了显示信息的需要还需配置相应的字库支持,其结构如下:

F8X16=[
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,#0
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,#1
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,#2
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,#3
...

为了,模拟I2C发送控制信号,所使用的引脚被配置为输出模式:
sda_pin = Pin(7, Pin.OUT)
scl_pin = Pin(8, Pin.OUT)

模拟I2C处理的相关辅助函数为:
  1. def IIC_Start():
  2.     scl_pin.on()
  3.     utime.sleep_us(1)
  4.     sda_pin.on()
  5.     utime.sleep_us(1)
  6.     sda_pin.off()
  7.     utime.sleep_us(1)
  8.     scl_pin.off()
  9.     utime.sleep_us(1)
  10.    
  11. def IIC_Stop():
  12.     scl_pin.on()
  13.     utime.sleep_us(1)
  14.     sda_pin.off()
  15.     utime.sleep_us(1)
  16.     sda_pin.on()
  17.     utime.sleep_us(1)
  18.    
  19. def IIC_Wait_Ack():
  20.     scl_pin.on()
  21.     utime.sleep_us(1)
  22.     scl_pin.off()
  23.     utime.sleep_us(1)

模拟I2C发送字节数据的函数为:
  1. def Write_IIC_Byte(IIC_Byte):
  2.     da=IIC_Byte
  3.     scl_pin.off()
  4.     for i in range(8):
  5.        if (da&0x80):
  6.            sda_pin.on()
  7.        else:
  8.            sda_pin.off()
  9.        utime.sleep_us(1)
  10.        da=da<<1
  11.        scl_pin.on()
  12.        utime.sleep_us(1)
  13.        scl_pin.off()
  14.        utime.sleep_us(1)

发送指令的函数为:
  1. def Write_IIC_Command(IIC_Command):
  2.     IIC_Start()
  3.     Write_IIC_Byte(0x78)
  4.     IIC_Wait_Ack()
  5.     Write_IIC_Byte(0x00)
  6.     IIC_Wait_Ack()
  7.     Write_IIC_Byte(IIC_Command)
  8.     IIC_Wait_Ack()
  9.     IIC_Stop()

发送数据的函数为:
  1. def Write_IIC_Data(IIC_Data):
  2.     IIC_Start()
  3.     Write_IIC_Byte(0x78)
  4.     IIC_Wait_Ack()
  5.     Write_IIC_Byte(0x40)
  6.     IIC_Wait_Ack()
  7.     Write_IIC_Byte(IIC_Data)
  8.     IIC_Wait_Ack()
  9.     IIC_Stop()

选取发送指令或数据的函数为:
  1. def OLED_WR_Byte(dat , cmd):
  2.     if (cmd):
  3.         Write_IIC_Data(dat)
  4.     else:
  5.         Write_IIC_Command(dat)

设置显示位置的函数为:
  1. def OLED_Set_Pos(x, y):
  2.     OLED_WR_Byte(0xb0+y,OLED_CMD)
  3.     OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD)
  4.     OLED_WR_Byte((x&0x0f),OLED_CMD)

实现清除屏幕显示的函数为:
  1. def OLED_Clear():
  2.     for i in range(8):
  3.         OLED_WR_Byte (0xb0+i,OLED_CMD)
  4.         OLED_WR_Byte (0x00,OLED_CMD)
  5.         OLED_WR_Byte (0x10,OLED_CMD)
  6.         for n in range(128):
  7.             OLED_WR_Byte(0,OLED_DATA)  #OLED_WR_Byte(0xf0,OLED_DATA)

实现OLED显示屏初始化的函数为:
  1. def OLED_Init():
  2.     Write_IIC_Command(0xAE)
  3.     Write_IIC_Command(0x40)
  4.     Write_IIC_Command(0xb0)
  5.     Write_IIC_Command(0xc8)
  6.     Write_IIC_Command(0x81)
  7.     Write_IIC_Command(0xff)
  8.     Write_IIC_Command(0xa1)
  9.     Write_IIC_Command(0xa6)
  10.     Write_IIC_Command(0xa8)
  11.     Write_IIC_Command(0x1F)
  12.     Write_IIC_Command(0xd3)
  13.     Write_IIC_Command(0x00)
  14.     Write_IIC_Command(0xd5)
  15.     Write_IIC_Command(0xf0)
  16.     Write_IIC_Command(0xd9)
  17.     Write_IIC_Command(0x22)
  18.     Write_IIC_Command(0xda)
  19.     Write_IIC_Command(0x02)
  20.     Write_IIC_Command(0x8d)
  21.     Write_IIC_Command(0x14)
  22.     Write_IIC_Command(0xdb)
  23.     Write_IIC_Command(0x49)
  24.     Write_IIC_Command(0xaf)

实现字符显示的函数为:
  1. def OLED_ShowChar(x,y,chr,Char_Size):
  2.    c=chr
  3.    OLED_Set_Pos(x,y)
  4.    for i in range(8):
  5.       OLED_WR_Byte(F8X16[c*16+i],OLED_DATA)
  6.    OLED_Set_Pos(x,y+1)
  7.    for i in range(8):
  8.       OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA)

实现驱动测试的主程序为:
  1. if(__name__=='__main__'):
  2.     OLED_Init()
  3.     OLED_Clear()
  4.     OLED_ShowChar(0,0,0,16)
  5.     OLED_ShowChar(8,0,1,16)
  6.     OLED_ShowChar(16,0,2,16)
  7.     OLED_ShowChar(0,2,17,16)
  8.     OLED_ShowChar(8,2,18,16)
  9.     OLED_ShowChar(16,2,19,16)
  10.     time.sleep(1000)

经程序运行,其测试效果如图1所示,这样就达到了驱动OLED屏的目标。   
4754968df1bd85fd37.png
图1  测试效果

为丰富显示内容及色彩,还可使用SPI接口的TFT显示屏。

SPI方式驱动TFT显示屏,需要使用的部分引脚资源图2所示。
6994868df208169d71.png
2 引脚资源分配
TFT显示屏与开发板的连接关系为:
TFT_CS----GPIO49
TFT_RS----GPIO50
TFT_DC----GPIO52
TFT_MOSI----GPIO29
TFT_SCLK----GPIO28
TFT_BL----GPIO51

为采用硬件驱动方式,要导入SPIPinTFT及字库等,即:
from machine import SPI,Pin
from ST7735 import TFT
from font import sysfont, seriffont, terminalfont
import time
import math
对相关引脚的设置为:
TFT_CLK =   const(28)
TFT_MOSI =  const(29)
TFT_DC =    const(52)
TFT_RST =   const(50)
TFT_CS =    const(49)
使用显示屏驱动函数的情况下,对显示屏初始化处理为:
spi = SPI(1, baudrate=8_000_000, polarity=0, phase=0, bits=8, sck=Pin(TFT_CLK), mosi=Pin(TFT_MOSI), miso=None)
tft = TFT(spi, TFT_DC, TFT_RST, TFT_CS)

实现驱动测试的程序为:
  1. def test_fps():
  2.     tft.fill(TFT.BLACK)  # 清空屏幕
  3.     frame_count = 1  # 测试 50 帧
  4.     start_time = time.ticks_ms()  # 记录开始时间

  5.     for _ in range(frame_count):
  6.         testlines(TFT.RED)
  7.         test()
  8.         tftprinttest()
  9.     end_time = time.ticks_ms()  # 记录结束时间
  10.     elapsed_time = (end_time - start_time) / 1000  # 计算总时间 (秒)
  11.     fps = frame_count / elapsed_time  # 计算 FPS
  12.     print(f"FPS: {fps:.2f}")  # 输出帧率

  13. test_fps()

经程序执行,其测试效果如图3至图5所示。
1245068df214a2c066.png
3 字体大小测试


6486468df217925110.png

4 绘制效果测试


9548468df219edffc1.png

5 字体颜色效果

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

本版积分规则

12

主题

14

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部