【rust/esp32】初识slint ui框架并在st7789 lcd上显示

这篇具有很好参考价值的文章主要介绍了【rust/esp32】初识slint ui框架并在st7789 lcd上显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

说在前面

  • esp32版本:s3
  • 运行环境:no-std
  • 开发环境:wsl2
  • LCD模块:ST7789V2 240*280 LCD
  • Slint版本:master分支
  • github地址:这里

关于slint

  • 官网
  • 为啥不用lvgl
    只能说rust的生态还是不太行,lvgl的rust binding似乎还在开发中,已经有仓库了,但是还在开发中。
    slint目前比较完善,但是相关资料也少。
    反正已经在折腾rust了,也不在乎再多折腾个小众点的。

关于no-std

  • 上一篇还是std环境,怎么就变成no-std了?
    std环境下也折腾了slint,但是fps就是不怎么高 (可能哪里写的不对) ,然后就试了下no-std,稍微丝滑点,并且编译也快。

关于dma

  • rust生态下dma的资料更是少的可怜,找了好久也没啥进展,所以本文不涉及dma

准备工作

  • 引脚连接见上篇
  • 开发环境部分,由于不需要esp idf,简单很多,cargo直接搞定

相关依赖

  • Cargo.toml
    [dependencies]
    hal = { package = "esp32s3-hal", version = "0.13.0"}
    esp-backtrace = { version = "0.9.0", features = ["esp32s3", "panic-handler", "exception-handler", "print-uart"] }
    esp-println = { version = "0.7.0", features = ["esp32s3","log"] }
    log = { version = "0.4.18" }
    esp-alloc = { version = "0.3.0" }
    embedded-hal = "0.2.7"
    embedded-graphics-core = "0.4.0"
    embedded-graphics = "0.8.1" 
    embedded-graphics-framebuf = "0.5.0"
    display-interface = "0.4"
    display-interface-spi = "0.4"
    mipidsi = "0.7.1"
    slint = { git = "https://githubfast.com/slint-ui/slint", default-features = false, features = ["compat-1-2","unsafe-single-threaded","libm", "renderer-software"] }
    
    [build-dependencies]
    slint-build = { git = "https://githubfast.com/slint-ui/slint" }
    

代码

#![no_std]
#![no_main]

extern crate alloc;
use alloc::boxed::Box;
use alloc::rc::Rc;
use rs_esp32s3_no_std_st7789_demo::dma::DmaBackend;
use core::cell::RefCell;
use core::mem::MaybeUninit;
use display_interface_spi::SPIInterfaceNoCS;
use embedded_graphics_core::prelude::{DrawTarget, Point, RgbColor, Size};
use embedded_graphics_core::{pixelcolor::raw::RawU16, primitives::Rectangle};
use esp_backtrace as _;
use esp_println::println;
use hal::spi::master::{Spi, dma};
use hal::{
    clock::{ClockControl, CpuClock},
    peripherals::Peripherals,
    prelude::*,
    spi::SpiMode,
    systimer::SystemTimer,
    timer::TimerGroup,
    Delay, Rtc, IO,
};
use mipidsi::Display;

#[global_allocator]
static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();

// 分配内存
fn init_heap() {
    const HEAP_SIZE: usize = 250 * 1024;
    static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit();

    unsafe {
        ALLOCATOR.init(HEAP.as_mut_ptr() as *mut u8, HEAP_SIZE);
    }
}

// slint自动编译ui代码
slint::include_modules!();
#[entry]
fn main() -> ! {
    init_heap();

	// slint 设置默认backend
    slint::platform::set_platform(Box::new(EspBackend::default()))
        .expect("backend already initialized");

    let main_window = Recipe::new().unwrap();

    let strong = main_window.clone_strong();
    let timer = slint::Timer::default();
    // 由于我的lcd不支持触屏 这里模拟了下按钮点击
    timer.start(
        slint::TimerMode::Repeated,
        core::time::Duration::from_millis(1000),
        move || {
            if strong.get_counter() <= 0 {
                strong.set_counter(25);
            } else {
                strong.set_counter(0);
            }
        },
    );

    main_window.run().unwrap();

    panic!("The MCU demo should not quit");
}

#[derive(Default)]
pub struct EspBackend {
    window: RefCell<Option<Rc<slint::platform::software_renderer::MinimalSoftwareWindow>>>,
}

impl slint::platform::Platform for EspBackend {
    fn create_window_adapter(
        &self,
    ) -> Result<Rc<dyn slint::platform::WindowAdapter>, slint::PlatformError> {
        let window = slint::platform::software_renderer::MinimalSoftwareWindow::new(
            slint::platform::software_renderer::RepaintBufferType::ReusedBuffer,
        );
        self.window.replace(Some(window.clone()));
        Ok(window)
    }

    fn duration_since_start(&self) -> core::time::Duration {
        core::time::Duration::from_millis(
            SystemTimer::now() / (SystemTimer::TICKS_PER_SECOND / 1000),
        )
    }

    fn run_event_loop(&self) -> Result<(), slint::PlatformError> {
        let peripherals = Peripherals::take();
        let mut system = peripherals.SYSTEM.split();
        let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock240MHz).freeze();

        let mut rtc = Rtc::new(peripherals.RTC_CNTL);
        let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
        let mut wdt0 = timer_group0.wdt;
        let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks);
        let mut wdt1 = timer_group1.wdt;

        rtc.rwdt.disable();
        wdt0.disable();
        wdt1.disable();

        let mut delay = Delay::new(&clocks);
        let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

        let clk = io.pins.gpio18;
        let sdo = io.pins.gpio17;
        let cs = io.pins.gpio14;

		// 初始化spi
        let spi = Spi::new_no_miso(
            peripherals.SPI2,
            clk,
            sdo,
            cs,
            60u32.MHz(),
            SpiMode::Mode0,
            &clocks,
        );
        println!("spi init.");

        let dc = io.pins.gpio15.into_push_pull_output();
        let rst = io.pins.gpio16.into_push_pull_output();

		// spi interface
        let di = SPIInterfaceNoCS::new(spi, dc);
        // st7789 驱动
        let mut display = mipidsi::Builder::st7789(di)
            .with_display_size(240, 280)
            .with_window_offset_handler(|_| (0, 20)) // 这里稍微设置了下偏移
            .with_framebuffer_size(240, 280)
            .with_invert_colors( mipidsi::ColorInversion::Inverted)
            .init(&mut delay, Some(rst))
            .unwrap();

        println!("display init.");
        let mut bl = io.pins.gpio13.into_push_pull_output();
        bl.set_high().unwrap();

        let size = slint::PhysicalSize::new(240, 280);

        self.window.borrow().as_ref().unwrap().set_size(size);

        let mut buffer_provider = DrawBuffer {
            display,
            buffer: &mut [slint::platform::software_renderer::Rgb565Pixel::default(); 240],
        };

        loop {
            slint::platform::update_timers_and_animations();

			// 这里的大致流程是:
			// slint会计算出当前帧需要变化的像素
			// 结果会暂时存放在buffer_provider
			// 然后将buffer_provider中的数据传给spi
            if let Some(window) = self.window.borrow().clone() {
                window.draw_if_needed(|renderer| {
                    renderer.render_by_line(&mut buffer_provider);
                });
                if window.has_active_animations() {
                    continue;
                }
            }
        }
    }

    fn debug_log(&self, arguments: core::fmt::Arguments) {
        println!("{}", arguments);
    }
}

struct DrawBuffer<'a, Display> {
    display: Display,
    buffer: &'a mut [slint::platform::software_renderer::Rgb565Pixel],
}

impl<DI: display_interface::WriteOnlyDataCommand, RST: embedded_hal::digital::v2::OutputPin>
    slint::platform::software_renderer::LineBufferProvider
    for &mut DrawBuffer<'_, Display<DI, mipidsi::models::ST7789, RST>>
{
    type TargetPixel = slint::platform::software_renderer::Rgb565Pixel;

    fn process_line(
        &mut self,
        line: usize,
        range: core::ops::Range<usize>,
        render_fn: impl FnOnce(&mut [slint::platform::software_renderer::Rgb565Pixel]),
    ) {
        let buffer = &mut self.buffer[range.clone()];

        render_fn(buffer);

        // We send empty data just to get the device in the right window
        self.display
            .set_pixels(
                range.start as u16,
                line as _,
                range.end as u16,
                line as u16,
                buffer
                    .iter()
                    .map(|x| embedded_graphics_core::pixelcolor::raw::RawU16::new(x.0).into()),
            )
            .unwrap();
    }
}

结果

  • 还是有卡顿的感觉
    【rust/esp32】初识slint ui框架并在st7789 lcd上显示,Rust,单片机,rust,ui,开发语言,esp32,st7789
  • 对比c lvgl+dma,加权fps有157,差距太大了
    【rust/esp32】初识slint ui框架并在st7789 lcd上显示,Rust,单片机,rust,ui,开发语言,esp32,st7789

参考

  • slint mcu

文章来源地址https://www.toymoban.com/news/detail-742838.html

到了这里,关于【rust/esp32】初识slint ui框架并在st7789 lcd上显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ESP32+LVGL】1.69寸ST7789+CST816触摸屏之Vscode+platformio开发例程搭建移植

    ESP32开发板(本文以乐鑫系列ESP32-WROOM-32U为例,基本espressif系列的ESP32都行) ST7789+CST816驱动的触摸屏(这里以中景园1.69寸240*280的触摸屏为例) Vscode+platformio插件 触摸屏转接板(最好有,比较方便接线,直接连线问题应该也不大) 在Vscode下,使用platformio插件新建一个工程项

    2024年02月03日
    浏览(63)
  • 物联网开发笔记(89)- 使用Micropython开发ESP32开发板之合宙ESP32 C3开发板通过串口SPI控制st7789 TFT液晶屏1.3寸

    一、目的         这一节我们学习如何使用合宙的ESP32 C3开发板控制1.3寸彩色TFT显示屏模块,分辨率240*240,SPI接口,ST7789驱动芯片。 二、环境         ESP32  C3 + Thonny + 1.3寸 st7789液晶屏模块 + 几根杜邦线 + Win10 接线方法:   三、st7789 TFT显示屏驱动 st7789py.py   四、点亮

    2024年02月11日
    浏览(50)
  • 一起玩儿物联网人工智能小车(ESP32)——59. 基于TFT_eSPI库的1.3寸SPI彩色显示屏的使用(ST7789)

    摘要:本文是TFT液晶屏的基本知识和TFT_eSPI库的简单介绍 在前边已经介绍过0.96寸OLED显示屏的使用方法,那是一个单色屏,显示效果很是一般,因此,本篇来介绍彩色TFT(Thin Film Transistor:薄膜晶体管)显示屏的使用方法。 TFT屏幕和OLED屏幕是两种不同的显示器件。TFT屏幕和

    2024年02月21日
    浏览(43)
  • 一起玩儿物联网人工智能小车(ESP32)——61 基于TFT_eSPI库的1.3寸SPI彩色显示屏的使用(ST7789)(三)

    摘要:本文介绍TFT_eSPI中文字库的制作方法 前面已经介绍了TFT_eSPI库的基本使用方法,如果你可以将英文显示到液晶屏幕上了,那么就可以尝试本文的制作中文字库,并显示中文到液晶屏幕了,否则还是要先完成上一篇文章的学习。 接下来就开始制作中文字库。TFT_eSPI自带了

    2024年02月21日
    浏览(49)
  • ESP8266+TFT显示屏(ST7789 240*240)

    ❤ 操作系统: windows 10 x64 ❤ IDE: Arduino1.8.15 ❤ 运行库1: TFT_eSPI ❤ 运行库2: ESP8266 ❤ 开发板硬件: ESP8266-CH340  ,  ST7789-240*240-TFT显示屏 ESP8266 ST7789 备注 G GND 3V VCC D5 SCL D7 SDA D4 RES D3 DC 3-1 安装库# 打开Arduino,进入: 工具 --   管理库... ,搜索: TFT_eSPI ,选择版本,点击安

    2024年02月06日
    浏览(51)
  • linux驱动开发 ST7789 LCD驱动移植(I.MX6ULL平台)

    前言 I.MX6ULL的板子未选配RGB的屏幕,无法在板子上进行GUI的开发调试,不过手头上有块控制器为ST7789V3的LCD屏幕(1.3inch),通过简易接线后可以很方便进行驱动的移植 如有异议,欢迎留言指正 ST7789 LCD控制器 ST7789是一款单芯片TFT-LCD控制器,支持并口与SPI通信方式 特性 控制器支

    2023年04月09日
    浏览(81)
  • Arduino+esp8266+1.3寸TFT屏(st7789驱动)显示图片教程

    Arduino下载TFT_eSPI和JPEGDecoder库 步骤:项目-加载库-管理库 修改User_Setup.h 驱动 #define ST7789_DRIVER 屏尺寸(我的是240*240) #define TFT_WIDTH 240 #define TFT_HEIGHT 240 连接引脚 #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could co

    2023年04月25日
    浏览(43)
  • 【跟小嘉学 Rust 编程】三十、Rust 使用 Slint UI

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月04日
    浏览(42)
  • linux(全志F1C100S/F1C200S)系列02:移植LCD st7789驱动,LVGL8.3移植

    st7789V中指定了rst与dc引脚,pio 4 3 对应PE3,pio 4 5对应PE5; 详细配置方式见链接:全志 :gpio使用 需要根据自身硬件配置。 Tips:更改 spi-max-frequency = 32000000 - spi-max-frequency = 100000000; 和 fps = 30; 改为 fps = 60; 感谢楼下老哥提示。 rotate = 90;根据屏幕方向更改。 只需要更改下面的三个地

    2024年01月18日
    浏览(61)
  • 利用STM32的HAL库驱动1.54寸 TFT屏(240*240 ST7789V)

      项目:温湿度表 芯片:STM32F030C6T8 液晶:华迪1.54寸 TFT屏 温湿度传感器:SHT30      主要对液晶屏官方驱动代码进行了增加和修改。 一、STM32CubeMX建立工程          I2C1 给SHT30, SPI给液晶屏,TIM16用于内部基础定时,TIM17给LED,USART1打印调试信息。RTC预留。  SPI的DMA设置 

    2023年04月08日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包