首页 > 其他分享 >esp32笔记[10]-rust驱动ssd1306显示屏

esp32笔记[10]-rust驱动ssd1306显示屏

时间:2023-11-16 21:22:23浏览次数:28  
标签:10 esp32 显示屏 pub BMP let display rust ssd1306

摘要

使用rust(no-std)环境和esp-hal库实现SSD1306显示屏(128x64)显示bmp图片.

平台信息

  • esp32(模组:ESP32-WROOM-32D)
    • (xtensa lx6)(xtensa-esp32-none-elf)
  • rust

超链接

esp32笔记[7]-使用rust+zig开发入门

原理简介

rust的include_bytes!宏

Rust的include_bytes!宏可以用来将本地文件加载为字节数组。这个宏会在编译时将指定的文件读取为字节数组,并将其嵌入到生成的二进制文件中。这样,你就可以在程序运行时直接访问这个字节数组,而不需要再次读取文件。
需要注意的是,include_bytes!宏只能在编译时加载文件,因此无法用于动态加载文件。

bmp图片的各种颜色空间

  • RGB888
  • RGB565
  • Gray

BMP图片可以使用多种颜色空间来表示,其中包括RGB888、RGB565和Gray。以下是这些颜色空间的简要说明:

  1. RGB888

    • 也被称为24位RGB,因为每个颜色(红色、绿色和蓝色)分别使用8位来表示,总共24位。
    • 这为每种颜色提供了256个可能的阴影,因此总共可以表示1600多万种颜色。
    • 是真彩色的一种表示方式,它提供了丰富的颜色信息,适用于需要高质量颜色的应用。
  2. RGB565

    • 在这种颜色空间中,红色使用5位,绿色使用6位,蓝色使用5位来表示,总共16位。
    • 相比RGB888,RGB565使用的空间更少,这降低了存储和带宽要求,但代价是颜色精度降低。
    • 仍然可以表示相对较多的颜色(大约65,000种),对于许多应用来说足够接近真彩色。
  3. Gray

    • 灰度色彩空间仅使用亮度信息,不使用色度信息。
    • 图像中的每个像素只有一个通道,表示从黑色(0)到白色(255)的亮度。
    • 适用于那些不关注颜色的应用,如一些文本或图标,或者用于黑白照片。

BMP图片格式简介:

BMP(Bitmap)是一种图像文件格式。它的设计相对简单,不采用任何压缩技术,因此通常占用较多的存储空间。

BMP文件的基本组成包括:位图文件头(Bitmap File Header)、位图信息头(Bitmap Info Header)和颜色表(Color Table)或称为调色板(Palette)。之后的数据就是实际的像素数据。

使用Rust结构体描述BMP图片数据结构:

在Rust中,我们可以使用结构体来描述BMP的数据结构。以下是一个非常基础的描述,它涵盖了BMP文件头和位图信息头。

#[derive(Debug)]
pub struct BitmapFileHeader {
    pub signature: [u8; 2], // "BM"
    pub file_size: u32,
    pub reserved1: u16,
    pub reserved2: u16,
    pub offset_data: u32, // 通常为54
}

#[derive(Debug)]
pub struct BitmapInfoHeader {
    pub size: u32, // 通常为40
    pub width: i32,
    pub height: i32,
    pub planes: u16, // 必须为1
    pub bit_count: u16, // 位数,如1、4、8、16、24、32等
    pub compression: u32, // 0表示不压缩
    pub size_image: u32, // 实际像素数据的大小
    pub x_pixels_per_meter: i32,
    pub y_pixels_per_meter: i32,
    pub colors_used: u32,
    pub colors_important: u32,
}

例如,对于24位的BMP图像,每个像素由三个字节表示,分别代表红、绿、蓝三种颜色。

ssd1306的128x64显示屏简介

SSD1306是一款OLED显示屏驱动芯片,它驱动的显示屏通常为128x64分辨率。这种显示屏被广泛应用于各种嵌入式系统和可穿戴设备中,如智能手表、手机、车载电子产品等。

OLED即有机发光二极管,这种显示屏技术具有自发光的特性,每一个像素都可以独立发光,因此色彩鲜艳,对比度高,视角广。

此外,由于SSD1306驱动的OLED显示屏是自发光的,所以它在显示黑色时像素是不发光的,这样就可以实现非常低的功耗。同时,SSD1306还具有内置的对比度控制、显示RAM和振荡器,进一步减少了外部组件和功耗。

总的来说,SSD1306的128x64 OLED显示屏具有高对比度、宽视角、低功耗、快速响应等优点,适用于需要高品质图像和长续航的各种应用场景。

实现

核心代码

/*
备注:
- 使用no-std,没有常规的main函数
- 串口波特率115200
- 不要占用SPI FLASH的GPIO(6,7,8,9,10,11)
目标平台:
- esp32s1(xtensa lx6)(xtensa-esp32-none-elf)
依赖:
- esp32-hal(0.16.0)
- esp-backtrace(0.9.0)
- esp-println(0.7.0)
- critical_section(1.1.2)
- embedded-svc(0.26.1)
- embedded-io(0.6.1)
- ssd1306(0.8.4)
- embedded_graphics(0.8.1)
- tinybmp(0.5.0)
编译及烧录命令:
- cargo-offline run
- (优先使用)cargo build --release
- cargo-offline build --release
- cargo-offline build --example main --release
*/
#![no_std]
#![no_main]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_variables)]
#![allow(unused_unsafe)]
#![allow(dead_code)]
#![allow(unused_mut)]
#![feature(c_variadic)]
#![feature(const_mut_refs)]
#![feature(type_alias_impl_trait)]

use ssd1306::{
    prelude::*, 
    I2CDisplayInterface, 
    Ssd1306,
    mode::BufferedGraphicsMode,
    mode::BasicMode,
};//ssd1306相关
use embedded_graphics::{
    mono_font::{
        ascii::{FONT_6X10, FONT_9X18_BOLD},
        MonoTextStyleBuilder,
    },
    pixelcolor::BinaryColor,
    prelude::*,
    text::{Alignment, Text},
    pixelcolor::Rgb565,
    pixelcolor::Gray2,
    pixelcolor::Rgb888,
    image::Image,
};// ssd1306相关
use tinybmp::Bmp;// ssd1306相关

fn main()->!{
// 省略其他代码
    // 配置ssd1306
    let mut oled_sda = io.pins.gpio21.into_push_pull_output();
    let mut oled_scl = io.pins.gpio22.into_push_pull_output();
    let i2c = I2C::new(
        peripherals.I2C0,
        oled_sda,
        oled_scl,
        100u32.kHz(),
        &clocks,
    );
    let interface = I2CDisplayInterface::new(i2c);

    // 定义display变量
    let mut display = 
        Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
        .into_buffered_graphics_mode();
    match display.init(){
        Ok(_)=>{
            println!("init ssd1306 ok!");
            ssd1306_display(2,&mut display);
        }
        Err(_)=>{
            println!("init ssd1306 failed!");
        }
    }
// 省略其他代码
}

// ssd1306显示封装
pub fn ssd1306_display(mode: u8, _display: &mut Ssd1306<I2CInterface<I2C<I2C0>>, DisplaySize128x64, BufferedGraphicsMode<DisplaySize128x64>>){
   if(mode == 1){
      // 显示文字logo
      let text_style = MonoTextStyleBuilder::new()
            .font(&FONT_6X10)
            .text_color(BinaryColor::On)
            .build();
        let text_style_big = MonoTextStyleBuilder::new()
            .font(&FONT_9X18_BOLD)
            .text_color(BinaryColor::On)
            .build();
        Text::with_alignment(
            "sugardraw",
            _display.bounding_box().center() + Point::new(0, 0),
            text_style_big,
            Alignment::Center,
        )
        .draw(_display)
        .unwrap();
  
        Text::with_alignment(
            "Chip: ESP32",
            _display.bounding_box().center() + Point::new(0, 14),
            text_style,
            Alignment::Center,
        )
        .draw(_display)
        .unwrap();
  
        // 写入缓存到显示屏
        _display.flush().unwrap();
        // 清除显示屏缓存
        _display.clear(BinaryColor::Off).unwrap();
    }
    else if(mode == 2){
      // 显示bmp图片
        let sugardraw_bmp_result = Bmp::<Rgb888>::from_slice(include_bytes!("./data/sugardraw_128x64.bmp"));
        match sugardraw_bmp_result {
            Ok(sugardraw_bmp) => {
                let im: Image<Bmp<Rgb888>> = Image::new(&sugardraw_bmp, Point::new(0, 0));// 左上为原点,左边参数为纵轴,右边参数为横轴
                im.draw(&mut _display.color_converted()).unwrap();
                _display.flush().unwrap();
            }
            Err(error) => {
                println!("Failed to load BMP image");
            }
        }
    }
}// end ssd1306_display

编译配置

Cargo.toml

[dependencies.ssd1306]
version = "0.8.4"

[dependencies.tinybmp]
version = "0.5.0"

[dependencies.embedded-graphics]
version = "0.8.1"

.cargo/config.toml

[target.xtensa-esp32-none-elf]
runner = "espflash flash --monitor"

[build]
rustflags = [
  "-C", "link-arg=-nostartfiles",
  "-C", "link-arg=-Wl,-Tlinkall.x",
]
target = "xtensa-esp32-none-elf"

[unstable]
build-std = ["core","alloc"]

效果

标签:10,esp32,显示屏,pub,BMP,let,display,rust,ssd1306
From: https://www.cnblogs.com/qsbye/p/17837290.html

相关文章

  • [ZJOI2010] 基站选址
     我感觉我缺了一个dp优化的思路我不知道我是不是能够对状态继续优化dp写少了。。。确诊了题目描述有NN个村庄坐落在一条直线上,第i(i>1)i(i>1)个村庄距离第11个村庄的距离为DiDi​。需要在这些村庄中建立不超过KK个通讯基站,在第ii个村庄建立基站的费用为CiCi​。如......
  • 学习笔记10——20211303
    一、学习任务自学教材第12章,提交学习笔记(10分),评分标准如下1.知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容(4分)“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”核心是要求GPT:......
  • 10、弹性布局(Flex Expanded)
    自定义的IconContainerclassIconContainerextendsStatelessWidget{Colorcolor;IconDataicon;//IconContainer(this.icon,{super.key,requiredthis.color});//与下方效果一样//IconContainer(this.icon,{Key?key,requiredthis.color}):super(k......
  • 一键整合,万用万灵,Python3.10项目嵌入式一键整合包的制作(Embed)
    我们知道Python是一门解释型语言,项目运行时需要依赖Python解释器,并且有时候需要安装项目中对应的三方依赖库。对于专业的Python开发者来说,可以直接通过pip命令进行安装即可。但是如果是分发给其他的Windows用户,特别是不熟悉Python的人来说,这样过于繁琐。因此最好的办法是连同Pytho......
  • 在ESP32-C3上实现断电后RTC(Real-Time Clock)继续走时
    如果您想在ESP32-C3上实现断电后RTC(Real-TimeClock)继续走时,可以考虑以下几种方法:使用外部RTC芯片:您可以连接一个外部的RTC芯片,例如DS1307或DS3231等,这些芯片通常具有内置的锂电池,可以在断电时保持走时。将外部RTC芯片的VDD引脚连接到ESP32-C3的电池或电源,并将时钟信号线连接到ESP3......
  • Windows10+VisualStudio2022+CMake+Qt开发环境搭建
    一、概述之前一直使用QtCreator当做QT的开发工具,也没觉得有啥问题。最近使用了VisualStudio+Cmake写了一些SDL2和FFmpeg的东西感觉这个VisualStudio这个工具挺好用的。就萌生了要使用VisualStudio开发Qt的想法。有了这个想法之后就想着需要搭建一个开发环境。百度搜索了......
  • 【操作系统MIT 6.1810(2022版)笔记】Lab实验:环境搭建——以Ubuntu20.04为例
    感觉环境搭建没有别人说的那么难。我是双系统用户(Win+Ubuntu20.04),所以直接在Ubuntu上搭建了。听别人说不要用Ubuntu18.04搭建,不知道为什么参考链接:官网环境搭建教程环境搭建打开终端,输入以下命令并回车运行sudoapt-getinstallgitbuild-essentialgdb-multiarchqemu-s......
  • mysql链接不上3306报错10060
    1、控制台进入查看防火墙(前提mysql我的端口是3306,现在大部分人已经不用3306了)firewall-cmd--zone=public--list-ports(查看3306端口是否开启,如果没见到3306端口)2、添加3306firewall-cmd--zone=public--add-port=3306/tcp--parmanent3、如上添加成功了,最重要的一点来......
  • GD32F103C8T6看门狗
    GD32F10x看门狗两个看门狗设备(独立看门狗IWDG和窗口看门狗WWDG)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。一、独立看门狗IWDG特性:自由运行的递减计数器;时钟由独立的RC振荡器提供(可在停止和待机模......
  • 若依vue启动报Error: error:0308010C:digital envelope routines::unsupported
    解决:若依vue启动报Error:error:0308010C:digitalenveloperoutines::unsupported1.描述:问题产生原因是因为node.jsV17版本中最近发布的OpenSSL3.0,而OpenSSL3.0对允许算法和密钥大小增加了严格的限制,可能会对生态系统造成一些影响.解决方法:有很多种,我把适合我的写在第一......