RP2040接ST7735小显示屏

最近准备给恒流源加上电流显示,所以就给板子准备了一个显示接口,我买的小显示屏是80x160像素的分辨率的长条形显示屏,使用的是8Pin的FPC接口。接口的定义如下:

 大致的含义如下:

LEDALED背光供电(也有说背光调制)
GND接地
RESET重置pin,初始化时需要重置屏幕,低电平有效复位屏幕
RSDCpin,0=命令寄存器 1=数据寄存器
SDA即SPI的MOSI,主机的TX引脚
SCL即SPI的SCK引脚
VDD主控芯片供电
CS即SPI的片选

 涉及的电路图如下:

由于小型化的需要,所以,电阻电容都是0402大小,排阻是0402x2。由于背光有降压的需求(明确要求3V),所以3.3V供电需要串接一个二极管。我找的是肖特基的二极管,大约350mV的压降。

 焊好板子,接上显示屏之后,就可以进行软件开发了。最开始的时候,我选择的是Adafruit_Gfx这个包,因为Adafruit这家公司在开源界足够有名,但这个库实在是一言难尽,因为这个库对ST7735的支持并不是特别好,为什么这么说呢,因为这个库对ST7735的支持类连最基本的定制显示屏的参数都做不到,只给了一些有限的显示屏的规格,而我买的这个屏恰恰是在它支持范围之外,最大的问题是颜色的格式,我猜测,Adafruit用的是SPI小端数据传输的方式,但是我这个屏幕支持的格式是大端格式,也就是说,传输到屏幕的数据是BGR格式,而不是RGB。因此需要给颜色换位置,但是Adafruit支持的几个规格没有这种分辨率和颜色格式。我不得不自己想了个办法,直接写寄存器来处理这个问题。

        // 初始化屏幕
        tft.initR( INITR_MINI160x80 );  // 80x160专用
        delay(50);

        tft.setFont();

        // 设置BGR模式 + 旋转方向(示例为0°方向)
        tft.setRotation(3);
        uint8_t madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST7735_MADCTL_BGR;
        tft.sendCommand(ST77XX_MADCTL, &madctl, 1);

        tft.fillScreen(BACK_COLOR);
        delay(200);

只有这样,我才能解决颜色反转的问题。非常的烦人。你应该注意到了代码之间的delay函数。因为Adafruit是直接写屏的方式,意思就是有任何操作,直接写到芯片的寄存器内。但是,这个有个问题,就是如果上一条指令还在执行的时候,你就开始发送下一条指令,会导致ST7735出现问题,具体的表现就是屏幕死锁,再也无法更新,而且屏幕显示花屏。

操作的间隔问题非常的麻烦,因为你必须小心的处理每一条操作,避免屏幕的死锁,但是,这又加深了系统的延迟。而且Adafruit有一个致命的缺陷,就是没有双缓冲和dma数据传输,这一点让屏幕在更新字符串的时候延迟特别高,而且有明显的闪烁。

void CPicoFilamental::DrawFrame()
{
    if( enable_tft )
    {
        const int x = 10, y = 34;
        tft.setTextSize( 2 );

        tft.setCursor( x, y );
        tft.setTextColor( BACK_COLOR ); // 底色文字
        tft.print( old_string.c_str() );

        delay(10);

        if( IsFailure() )
        {
            tft.setCursor( x, y );
            tft.print( "Failure!" );
            old_string = "Failure!";
        }
        else
        {
            double now = 0.0f, exp = 0.0f;
            GetCurrent( now, exp );

            tft.setCursor( x, y );
            tft.setTextColor( FONT_COLOR ); // 白色文字

            char msg[32];
            sprintf( msg, "%.1f/%.0fmA", now * 1000.0f, exp * 1000.0f );
            tft.print( msg );
            old_string = msg;
        }
    }
}

这是一段设置屏幕显示的代码,我是先用上一次写的字符串,用背景色先写一次,然后延迟10毫秒,再写下一次要显示的字符串。因为ST7735依赖延迟来确保操作的稳定行,更新显示内存的时间手册上说是5ms左右,但是我的测试发现5ms完全不够,哪怕我设置为10ms,也会有小几率死屏。

所以,最后我找遍了Arduino的共享库,发现一个非常好的库:LovyanGFX,这是一个日本人写的库,这个库有我需要的一切,双缓冲,详细的配置,足够方便的操作,等等。用这个库也非常方便,只需要先写一个配置文件,他在例子中也提供了ST7735的模板:

#include <LovyanGFX.hpp>

//#define USE_BACKLIGHT

// ST7735S (80x160) の接続設定例
#define TFT_MISO -1
#define TFT_MOSI 19
#define TFT_SCLK 18
#define TFT_CS   17
#define TFT_DC   26
#define TFT_RST  27
#ifdef USE_BACKLIGHT
#define TFT_BLK  28
#endif
#define SPI_PORT  0

class LGFX : public lgfx::LGFX_Device
{
  lgfx::Panel_ST7735S _panel_instance;
  lgfx::Bus_SPI       _bus_instance; // SPIバスのインスタンス
#ifdef USE_BACKLIGHT
  lgfx::Light_PWM     _light_instance;
#endif

public:
  LGFX(void)
  {
    {                                    // バス制御の設定を行います。
      auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。

      // SPIバスの設定
      cfg.spi_host = SPI_PORT;   // 使用するSPIポートを選択(0 or 1)
      cfg.spi_mode = 0;          // SPI通信モードを設定 (0 ~ 3)
      cfg.freq_write = 40000000; // 送信時のSPIクロック (最大80MHz, 80MHzを整数で割った値に丸められます)
      cfg.freq_read = 20000000;  // 受信時のSPIクロック

      cfg.pin_sclk = TFT_SCLK; // SPIのSCLKピン番号を設定
      cfg.pin_mosi = TFT_MOSI; // SPIのMOSIピン番号を設定
      cfg.pin_miso = TFT_MISO; // SPIのMISOピン番号を設定 (-1 = disable)
      cfg.pin_dc   = TFT_DC;   // SPIのD/Cピン番号を設定  (-1 = disable)

      _bus_instance.config(cfg);              // 設定値をバスに反映します。
      _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。
    }

    {                                      // 表示パネル制御の設定を行います。
      auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。

      cfg.pin_cs = TFT_CS;   // CSが接続されているピン番号   (-1 = disable)
      cfg.pin_rst = TFT_RST; // RSTが接続されているピン番号  (-1 = disable)
      cfg.pin_busy = -1;     // BUSYが接続されているピン番号 (-1 = disable)

      cfg.panel_width = 80;   // 実際に表示可能な幅
      cfg.panel_height = 160; // 実際に表示可能な高さ
      cfg.offset_x = 26;      // パネルのX方向オフセット量
      cfg.offset_y = 1;       // パネルのY方向オフセット量

      // cfg.offset_rotation = 4; // 回転方向の値のオフセット 0~7 (4~7は上下反転)
      cfg.invert = true; // パネルの明暗が反転してしまう場合 trueに設定
      // cfg.rgb_order = true;   // パネルの赤と青が入れ替わってしまう場合 trueに設定

      _panel_instance.config(cfg);
    }

#ifdef USE_BACKLIGHT
    { // バックライト制御の設定を行います。(必要なければ削除)
      auto cfg = _light_instance.config();    // バックライト設定用の構造体を取得します。

      cfg.pin_bl = TFT_BLK;         // バックライトが接続されているピン番号
      cfg.invert = false;           // バックライトの輝度を反転させる場合 true
      cfg.freq   = 44100;           // バックライトのPWM周波数
      cfg.pwm_channel = 6;          // 使用するPWMのチャンネル番号

      _light_instance.config(cfg);
      _panel_instance.setLight(&_light_instance);  // バックライトをパネルにセットします。
    }
#endif

    setPanel(&_panel_instance); // 使用するパネルをセットします。
  }
};

主要是调整PIN对应的GPIO值,还有使用的SPI端口、速率,另外,还有还有分辨率,颜色反转,RGB反向等等。这些做好了之后,只需要在 主循环中执行下面的代码就行了:

  lcd.init();
  lcd.setRotation(1);
  lcd.fillScreen(0xFFFFFFU);

  lcd.setCursor(10, 20);
  lcd.print("print!");

是不是很简单?而且由于有双缓冲和DMA传输,整个屏幕更新终于不再闪烁。

ST7735显示屏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值