esp32s3驱动摄像头——摄像头拍照并存放到sd卡中

序章

本文章是完成esp32s3驱动摄像头拍照储存sd卡,其代码逻辑是按键读取低电平(低电平驱动)拍一照片并存储进sd卡  下面是硬件和软件的实现

目录

1.硬件准备

1.1芯片选择

1.2摄像头

1.3sd卡

2.代码

2.0介绍

开发软件和所使用的库

2.1sd卡驱动代码

2.1.1sd读写代码

2.1.1.1 sd头文件

2.1.1.2 sdcpp文件

2.1.2sd卡软件抽象层

2.2摄像头驱动代码

2.2.1 摄像头初始化

2.2.2摄像头拍摄代码

2.2.3摄像头存储进sd卡代码

3.全部代码

 

 

 

1.硬件准备

1.1芯片选择

我使用的是esp32s3的芯片因为相比于8266来说,它具有8MPSRAM拍出分辨率更高的照片,用过8266的cam的都知道虽然它的生态好教程多但是模糊,因为它默认的分辨率是SVGA=800*600(当然是能支持一些应用如人脸识别)。

1.2摄像头

一、OV5640 摄像头介绍
OV5640_V5( V5 是版本号,下面均以 OV5640 表示该产品)是芯路恒科技推出的一款高性能 500W 像素高清摄像头模块。该模块采用 OmniVision 公司生产的一颗 1/4 英寸CMOS QSXGA( 25921944)图像传感器 OV5640,配合高质量的光学镜头及为实现更高性能而精心设计的 PCBA,使该模块拥有了尽可能高的成像质量。OV5640 模块的特点如下:
 1.4μm1.4μm 像素大小,并且使用 OmniBSI 技术以达到更高性能(高灵敏度、
低串扰和低噪声)
 自动图像控制功能:自动曝光( AEC)、自动白平衡( AWB)、自动消除灯光条纹、
 自动黑电平校准( ABLC)和自动带通滤波器( ABF)等。
 支持图像质量控制:色饱和度调节、色调调节、 gamma 校准、锐度和镜头校准等
 标准的 SCCB 接口,兼容 IIC 接口
 支持 RawRGB、 RGB(RGB565/RGB555/RGB444)、 CCIR656、 YUV(422/420)、 YCbCr
( 422)和压缩图像( JPEG)输出格式
 支持 QSXGA( 500W)图像尺寸输出,以及按比例缩小到其他任何尺寸
 支持图像缩放、平移和窗口设置
 支持图像压缩,即可输出 JPEG 图像数据
 支持数字视频接口( DVP)
 

ab5b5aa3223b4f9d9fa02509b2828e30.png

1.3sd卡

2.代码

2.0开发软件和所使用的库

我使用的是vscode开发,因为里面有封装的espcam库和处理sd卡的软件抽象层的库

2.1头文件

2.1.1SD

2.1.1.1 sd头文件

这里需要注意的是我采用的是三线spi,也就是不要片选,其实大多时候使用spi是因为硬件本身需要用spi而非是真的用到了一对多的spi通讯,所以留出一个宝贵的的引脚还是很有必要的(没办法esp系列芯片的引脚确实不够用),当然如果你的pcb打开了cs引脚但不需要用到一对多那你只需要cs上拉处理即可(因为cs低电平有效)

#ifndef __SD_READ_WRITE_H
#define __SD_READ_WRITE_H

#include "Arduino.h" 
#include "FS.h"  //处理sd卡软件抽象层
#include "SD_MMC.h" //sd卡的读写库
//引脚定义这里用的是硬件spi 根据自己的具体所选的spi进行接线
#define SD_MMC_CMD  38 //据需求更改  
#define SD_MMC_CLK  39 //据需求更改
#define SD_MMC_D0   40 //据需求更改

// 列出指定目录下的文件和子目录
// 参数 fs: 文件系统对象
// 参数 dirname: 要列出的目录名
// 参数 levels: 要递归列出的子目录层级
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);

// 创建一个新的目录
// 参数 fs: 文件系统对象
// 参数 path: 要创建的目录路径
void createDir(fs::FS &fs, const char * path);

// 删除一个目录及其所有内容
// 参数 fs: 文件系统对象
// 参数 path: 要删除的目录路径
void removeDir(fs::FS &fs, const char * path);

// 读取并显示文件内容
// 参数 fs: 文件系统对象
// 参数 path: 要读取的文件路径
void readFile(fs::FS &fs, const char * path);

// 写入内容到文件,如果文件不存在则创建
// 参数 fs: 文件系统对象
// 参数 path: 要写入的文件路径
// 参数 message: 要写入文件的内容
void writeFile(fs::FS &fs, const char * path, const char * message);

// 在文件的末尾追加内容
// 参数 fs: 文件系统对象
// 参数 path: 要追加内容的文件路径
// 参数 message: 要追加的内容
void appendFile(fs::FS &fs, const char * path, const char * message);

// 重命名一个文件或目录
// 参数 fs: 文件系统对象
// 参数 path1: 原始文件或目录路径
// 参数 path2: 新的文件或目录路径
void renameFile(fs::FS &fs, const char * path1, const char * path2);

// 删除一个文件
// 参数 fs: 文件系统对象
// 参数 path: 要删除的文件路径
void deleteFile(fs::FS &fs, const char * path);

// 测试文件系统的读写性能
// 参数 fs: 文件系统对象
// 参数 path: 用于测试的文件路径
void testFileIO(fs::FS &fs, const char * path);

// 将JPEG图片数据写入文件
// 参数 fs: 文件系统对象
// 参数 path: 要写入的文件路径
// 参数 buf: JPEG图片数据的缓冲区
// 参数 size: JPEG图片数据的大小
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);

// 读取指定目录下的文件数量
// 参数 fs: 文件系统对象
// 参数 dirname: 要读取文件数量的目录名
// 返回值: 目录下的文件数量
int readFileNum(fs::FS &fs, const char * dirname);

#endif

2.1.1.2 sdcpp文件

 

#include "sd_read_write.h"

//初始化sd卡
void sdmmcInit(void){
  SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
  if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
    Serial.println("Card Mount Failed");
    return;
  }
//获取SD卡的类型
  uint8_t cardType = SD_MMC.cardType();
  if(cardType == CARD_NONE){
      Serial.println("No SD_MMC card attached");
      return;
  }
  Serial.print("SD_MMC Card Type: ");
  if(cardType == CARD_MMC){
      Serial.println("MMC");
  } else if(cardType == CARD_SD){
      Serial.println("SDSC");
  } else if(cardType == CARD_SDHC){
      Serial.println("SDHC");
  } else {
      Serial.println("UNKNOWN");
  }
// 打印SD卡大小
  uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
  Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);  
  Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
}

// 列出指定目录下的文件和子目录
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    // 打开目录
    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    // 检查是否为目录
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    // 打开目录的下一个文件
    File file = root.openNextFile();
    while(file){
        // 如果是目录,则打印目录名并递归列出子目录
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.path(), levels -1);
            }
        } else {
            // 如果是文件,则打印文件名和大小
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

// 创建一个新的目录
void createDir(fs::FS &fs, const char * path){
    // 打印正在创建的目录
    Serial.printf("Creating Dir: %s\n", path);
    if(fs.mkdir(path)){
    // 尝试创建目录,如果成功则打印成功信息,否则打印失败信息
        Serial.println("Dir created");
    } else {
        Serial.println("mkdir failed");
    }
}

// 删除一个目录及其所有内容
void removeDir(fs::FS &fs, const char * path){
    Serial.printf("Removing Dir: %s\n", path);
    if(fs.rmdir(path)){
    // 尝试删除目录,如果成功则打印成功信息,否则打印失败信息
        Serial.println("Dir removed");
    } else {
        Serial.println("rmdir failed");
    }
}

// 读取并显示文件内容
void readFile(fs::FS &fs, const char * path){
    // 打印正在读取的文件
    Serial.printf("Reading file: %s\n", path);

   // 打开文件
    File file = fs.open(path);
    if(!file){
        Serial.println("Failed to open file for reading");
        return;
    }
    // 读取并打印文件内容
    Serial.print("Read from file: ");
    while(file.available()){
        Serial.write(file.read());
    }
}

// 写入内容到文件,如果文件不存在则创建
void writeFile(fs::FS &fs, const char * path, const char * message){
    //打印正在写的文件
    Serial.printf("Writing file: %s\n", path);
    File file = fs.open(path, FILE_WRITE);
    // 打开文件用于写入
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("File written");
    } else {
        Serial.println("Write failed");
    }
}


// 向文件追加内容
void appendFile(fs::FS &fs, const char * path, const char * message){
    // 打印正在追加内容的文件路径
    Serial.printf("Appending to file: %s\n", path);

    // 打开文件用于追加
    File file = fs.open(path, FILE_APPEND);
    if(!file){
        // 如果文件打开失败,打印错误信息
        Serial.println("Failed to open file for appending");
        return;
    }
    // 追加内容到文件,并检查是否成功
    if(file.print(message)){
        Serial.println("Message appended");
    } else {
        // 如果追加失败,打印错误信息
        Serial.println("Append failed");
    }
}

// 重命名文件
void renameFile(fs::FS &fs, const char * path1, const char * path2){
    // 打印重命名操作的信息
    Serial.printf("Renaming file %s to %s\n", path1, path2);
    // 尝试重命名文件,并检查是否成功
    if (fs.rename(path1, path2)) {
        Serial.println("File renamed");
    } else {
        // 如果重命名失败,打印错误信息
        Serial.println("Rename failed");
    }
}

// 删除文件
void deleteFile(fs::FS &fs, const char * path){
    // 打印正在删除的文件路径
    Serial.printf("Deleting file: %s\n", path);
    // 尝试删除文件,并检查是否成功
    if(fs.remove(path)){
        Serial.println("File deleted");
    } else {
        // 如果删除失败,打印错误信息
        Serial.println("Delete failed");
    }
}

// 测试文件I/O性能
void testFileIO(fs::FS &fs, const char * path){
    // 打开文件
    File file = fs.open(path);
    static uint8_t buf[512]; // 静态缓冲区
    size_t len = 0; // 文件长度
    uint32_t start = millis(); // 开始时间
    uint32_t end = start; // 结束时间

    if(file){
        // 获取文件长度
        len = file.size();
        size_t flen = len; // 保存原始长度
        start = millis(); // 重置开始时间
        // 读取文件内容
        while(len){
            size_t toRead = len; // 要读取的字节数
            if(toRead > 512){
                toRead = 512; // 限制每次读取的字节数
            }
            file.read(buf, toRead); // 读取文件内容到缓冲区
            len -= toRead; // 更新剩余字节数
        }
        end = millis() - start; // 计算读取时间
        // 打印读取结果
        Serial.printf("%u bytes read for %u ms\r\n", flen, end);
        file.close(); // 关闭文件
    } else {
        // 如果文件打开失败,打印错误信息
        Serial.println("Failed to open file for reading");
    }

    // 打开文件用于写入
    file = fs.open(path, FILE_WRITE);
    if(!file){
        // 如果文件打开失败,打印错误信息
        Serial.println("Failed to open file for writing");
        return;
    }

    // 写入数据到文件
    size_t i;
    start = millis(); // 重置开始时间
    for(i=0; i<2048; i++){
        file.write(buf, 512); // 写入512字节到文件
    }
    end = millis() - start; // 计算写入时间
    // 打印写入结果
    Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
    file.close(); // 关闭文件
}

// 将JPEG图片数据写入文件
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
    // 打开文件用于写入
    File file = fs.open(path, FILE_WRITE);
    if(!file){
      // 如果文件打开失败,打印错误信息
      Serial.println("Failed to open file for writing");
      return;
    }
    // 写入数据到文件
    file.write(buf, size);
    // 打印文件保存成功信息
    Serial.printf("Saved file to path: %s\r\n", path);
}

// 读取指定目录下的文件数量
int readFileNum(fs::FS &fs, const char * dirname){
    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return -1;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return -1;
    }

    File file = root.openNextFile();
    int num=0;
    while(file){
    //遍历文件个数
      file = root.openNextFile();
      num++;
    }
    return num;  
}

2.1.2 摄像头引脚的头文件

#ifndef __camera_pin_H
#define __camera_pin_H

#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5

#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16

#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13

#endif

2.2CAM

2.2.1 摄像头初始化

1.下面是摄像头的结构体 可以根据具体的应用结合psram,芯片的算力还有摄像头的散热来修改下面的参数

SQCIF=12*96
QCIF=176*144
CIF=352*288
QVGA=320*240
VGA=640*480
SVGA=800*600
WSVGA=1024*600
XGA=1024*768
XVGA=1280*960
UXGA=1600*1200

2.亮度 饱和度 垂直翻转这些默认参数即可效果还是ok的但如果应用场景比较特殊的话也可以更改

 

 // 创建并初始化摄像头配置结构体
  camera_config_t config;
  // 配置摄像头数据引脚
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  // 配置时钟和同步引脚
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  // 配置I2C引脚
  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  // 配置电源和复位引脚
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  // 设置时钟频率
  config.xclk_freq_hz = 20000000;
  // 设置图像尺寸
  config.frame_size = FRAMESIZE_UXGA;
  // 设置像素格式
  config.pixel_format = PIXFORMAT_JPEG; // JPEG格式用于流式传输
  // 设置帧缓冲区获取模式
  config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  // 设置帧缓冲区位置
  config.fb_location = CAMERA_FB_IN_PSRAM;
  // 设置JPEG质量
  config.jpeg_quality = 12;
  // 设置帧缓冲区数量
  config.fb_count = 1;

  // 如果检测到PSRAM,则使用更高的分辨率和JPEG质量
  if(psramFound()){
    config.jpeg_quality = 10;
    config.fb_count = 2;
    config.grab_mode = CAMERA_GRAB_LATEST;
  } else {
    // 如果没有PSRAM,限制帧大小并使用DRAM
    config.frame_size = FRAMESIZE_SVGA;
    config.fb_location = CAMERA_FB_IN_DRAM;
  }

  // 初始化摄像头
  esp_err_t err = esp_camera_init(&config);
  // 检查摄像头是否初始化成功
  if (err != ESP_OK) {
    // 如果初始化失败,打印错误代码
    Serial.printf("Camera init failed with error 0x%x", err);
    return 0; // 返回0表示失败
  }

  // 获取传感器指针
  sensor_t * s = esp_camera_sensor_get();
  // 传感器初始设置:翻转图像、调整亮度和饱和度 这里可以不更改
  s->set_vflip(s, 1); // 翻转图像垂直方向
  s->set_brightness(s, 1); // 调整亮度
  s->set_saturation(s, 0); // lower the saturation

 

2.2.2摄像头拍摄代码

while(digitalRead(BUTTON_PIN)==LOW);
      // 按钮释放后,开始拍照流程

      //初始化帧缓冲区的指针
      camera_fb_t * fb = NULL;
      // 获取一帧图像数据
      fb = esp_camera_fb_get();
     

2.2.3摄像头存储进sd卡代码

    fb = esp_camera_fb_get();
      //检查是否获取帧缓冲区域
      if (fb != NULL) {
        // 读取sd卡上照片数量
        int photo_index = readFileNum(SD_MMC, "/camera");
        // 检查是否成功读取文件数量
        if(photo_index!=-1)
        {
          // 构建照片存储路径
          String path = "/camera/" + String(photo_index) +".jpg";
          // 将照片写入SD卡
          writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
        }
        // 释放帧缓冲区
        esp_camera_fb_return(fb);
      }
      else {
        // 如果获取帧缓冲区失败,打印错误信息
        Serial.println("Camera capture failed.");
      }

 

3.全部代码

#include "esp_camera.h"
#define CAMERA_MODEL_ESP32S3_EYE
#include "camera_pins.h"
#include "sd_read_write.h"

#define BUTTON_PIN  0   //定义按键引脚
int cameraSetup(void);  //声明

void setup() {
  Serial.begin(115200);
  //关闭debug减少串口信息 
  Serial.setDebugOutput(false); 
  Serial.println(); 
  //低电平驱动上拉电阻  
  pinMode(BUTTON_PIN, INPUT_PULLUP);  
  
  //sd卡初始化
  sdmmcInit();
  // removeDir(SD_MMC, "/camera"); //删除文件
  createDir(SD_MMC, "/camera");
  listDir(SD_MMC, "/camera", 0);
  //摄像头连接判断
  if(cameraSetup()==1){
    Serial.println("camerasetup");
  }
  else{
    Serial.println("cameradown");
    return;
  }
}



void loop() {
  // 检查按钮是否被按下(低电平有效)
  if(digitalRead(BUTTON_PIN)==LOW){
    // 简单的消抖,延时20毫秒
    delay(20);
    // 再次检查按钮是否仍然被按下
    if(digitalRead(BUTTON_PIN)==LOW){
      // 当按钮持续被按下时,进入等待循环直到按钮释放
      while(digitalRead(BUTTON_PIN)==LOW);
      // 按钮释放后,开始拍照流程

      //初始化帧缓冲区的指针
      camera_fb_t * fb = NULL;
      // 获取一帧图像数据
      fb = esp_camera_fb_get();
      //检查是否获取帧缓冲区域
      if (fb != NULL) {
        // 读取sd卡上照片数量
        int photo_index = readFileNum(SD_MMC, "/camera");
        // 检查是否成功读取文件数量
        if(photo_index!=-1)
        {
          // 构建照片存储路径
          String path = "/camera/" + String(photo_index) +".jpg";
          // 将照片写入SD卡
          writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
        }
        // 释放帧缓冲区
        esp_camera_fb_return(fb);
      }
      else {
        // 如果获取帧缓冲区失败,打印错误信息
        Serial.println("Camera capture failed.");
      }
     
    }
  }
}

// 摄像头设置函数
int cameraSetup(void) {
  // 创建并初始化摄像头配置结构体
  camera_config_t config;
  // 配置摄像头数据引脚
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  // 配置时钟和同步引脚
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  // 配置I2C引脚
  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  // 配置电源和复位引脚
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  // 设置时钟频率
  config.xclk_freq_hz = 20000000;
  // 设置图像尺寸
  config.frame_size = FRAMESIZE_UXGA;
  // 设置像素格式
  config.pixel_format = PIXFORMAT_JPEG; // JPEG格式用于流式传输
  // 设置帧缓冲区获取模式
  config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  // 设置帧缓冲区位置
  config.fb_location = CAMERA_FB_IN_PSRAM;
  // 设置JPEG质量
  config.jpeg_quality = 12;
  // 设置帧缓冲区数量
  config.fb_count = 1;

  // 如果检测到PSRAM,则使用更高的分辨率和JPEG质量
  if(psramFound()){
    config.jpeg_quality = 10;
    config.fb_count = 2;
    config.grab_mode = CAMERA_GRAB_LATEST;
  } else {
    // 如果没有PSRAM,限制帧大小并使用DRAM
    config.frame_size = FRAMESIZE_SVGA;
    config.fb_location = CAMERA_FB_IN_DRAM;
  }

  // 初始化摄像头
  esp_err_t err = esp_camera_init(&config);
  // 检查摄像头是否初始化成功
  if (err != ESP_OK) {
    // 如果初始化失败,打印错误代码
    Serial.printf("Camera init failed with error 0x%x", err);
    return 0; // 返回0表示失败
  }

  // 获取传感器指针
  sensor_t * s = esp_camera_sensor_get();
  // 传感器初始设置:翻转图像、调整亮度和饱和度
  s->set_vflip(s, 1); // 翻转图像垂直方向
  s->set_brightness(s, 1); // 调整亮度
  s->set_saturation(s, 0); // lower the saturation

  Serial.println("Camera configuration complete!");
  return 1;
} 

4.效果展示

 

上课划水写的,后续发效果展示和硬件接线

 

 

 

 

要在ESP32S3驱动ST7789 LCD显示屏,你可以按照以下步骤进行操作: 1. 首先,你需要连接ESP32S3和ST7789显示屏。根据引用的链接和引用提到的驱动名称,你可以找到具体的引脚连接图和驱动程序。 2. 确保你的ESP32S3开发板上已经安装了适当的开发环境,例如Arduino IDE。根据引用提到的信息,你可以使用Arduino IDE来进行测试。 3. 下载并安装ST7789驱动库。你可以在Arduino IDE的库管理器搜索"ST7789",然后选择适合你的库进行安装。 4. 在你的Arduino IDE打开一个新的项目,并导入ST7789库。你可以在库管理器搜索并选择安装的库。 5. 在你的代码包含ST7789库的头文件,并初始化SPI连接和ST7789对象。根据库的文档和示例,你可以设置显示屏的分辨率、引脚连接和其他必要的参数。 6. 编写代码以显示你想要在屏幕上显示的内容。ST7789库应该提供了一些函数来方便你在屏幕上绘制图形、显示文本等操作。 7. 上传代码到ESP32S3开发板并运行。确保你的开发板与计算机正确连接,并选择正确的开发板和端口。根据库的示例和文档,你应该能够看到你的代码在ST7789显示屏上正常运行。 请注意,以上步骤仅提供了一个基本的指导,具体的驱动过程可能因为硬件和软件环境的差异而有所不同。确保阅读并遵循ST7789库的文档和示例,以便获得更详细的指导和支持。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [使用ESP32驱动ST7789,效果很好的IPS显示屏](https://blog.csdn.net/u012388993/article/details/120605961)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ESP32-S3 lvgl-v8-st7789](https://download.csdn.net/download/weixin_53411486/87164695)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值