zynq驱动SPI ST7735S LCD

参考

树莓派Pico驱动SPI ST7735S LCD.csdn

PS 硬件 SPI 主机访问 W25Q16.csdn

BD

system.tcl

注意事项:

Vivado 自动生成了两个未使用的片选信号。请在 system_wrapper.v 文件中删除与这两个片选相关的代码,以避免综合报错。

未使用的片选信号包括:

bash 复制代码
output SPI_0_0_ss1_o;
output SPI_0_0_ss2_o;

PIN.xdc

bash 复制代码
## SPI SCLK
set_property PACKAGE_PIN M15 [get_ports SPI_0_0_sck_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_0_0_sck_io]

## SPI MOSI
set_property PACKAGE_PIN L16 [get_ports SPI_0_0_io0_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_0_0_io0_io]

## SPI MISO 
set_property PACKAGE_PIN K14 [get_ports SPI_0_0_io1_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_0_0_io1_io]

## SPI CS
set_property PACKAGE_PIN J14 [get_ports SPI_0_0_ss_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_0_0_ss_io]

## DC
set_property PACKAGE_PIN N20 [get_ports {GPIO_EMIO_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_EMIO_tri_io[0]}]

## RES
set_property PACKAGE_PIN U19 [get_ports {GPIO_EMIO_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_EMIO_tri_io[1]}]

裸机驱动

main.c

c 复制代码
#include "xparameters.h"
#include "xspips.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xil_printf.h"

/*=========================================================
 * 硬件配置区域
 *---------------------------------------------------------
 * 这里定义的是 ZYNQ PS 侧外设资源:
 * - SPI 使用 PS SPI0
 * - GPIO 使用 EMIO(从 PL 引出来的 IO)
 *========================================================*/
#define SPI_DEVICE_ID   XPAR_XSPIPS_0_DEVICE_ID
#define GPIO_DEVICE_ID  XPAR_XGPIOPS_0_DEVICE_ID

/*=========================================================
 * EMIO 引脚映射
 *---------------------------------------------------------
 * PIN_DC  :数据/命令选择信号(DC)
 * PIN_RES :LCD 复位信号(RESET)
 *
 * 注意:
 * 这两个引脚来自 PL → PS EMIO 映射
 * 对应 Vivado 里 GPIO_EMIO_tri_io[x]
 *========================================================*/
#define PIN_DC   54   // EMIO[0]
#define PIN_RES  55   // EMIO[1]

/*=========================================================
 * LCD 逻辑分辨率与偏移
 *---------------------------------------------------------
 * LCD_W / LCD_H :逻辑可用显示区域
 * LCD_XOFF / YOFF:ST7735 内部显存偏移(非常关键)
 *
 * 原因:
 * ST7735 实际 GRAM 比显示区域大,需要 offset 对齐
 *========================================================*/
#define LCD_W    80
#define LCD_H    160
#define LCD_XOFF 26
#define LCD_YOFF 1

/*=========================================================
 * 全局外设句柄
 *---------------------------------------------------------
 * Spi  :SPI 控制器实例
 * Gpio :EMIO GPIO 控制器实例
 *========================================================*/
static XSpiPs   Spi;
static XGpioPs  Gpio;

/*=========================================================
 * GPIO 控制函数(DC / RES)
 *---------------------------------------------------------
 * DC = 0 -> 命令模式
 * DC = 1 -> 数据模式
 *
 * RES = 0 -> LCD 复位
 * RES = 1 -> LCD 正常工作
 *========================================================*/
static inline void dc_cmd()  { XGpioPs_WritePin(&Gpio, PIN_DC, 0); }
static inline void dc_data() { XGpioPs_WritePin(&Gpio, PIN_DC, 1); }

static inline void res_low()  { XGpioPs_WritePin(&Gpio, PIN_RES, 0); }
static inline void res_high() { XGpioPs_WritePin(&Gpio, PIN_RES, 1); }

/*=========================================================
 * SPI 底层发送函数(阻塞模式)
 *---------------------------------------------------------
 * 使用 PolledTransfer:
 * - CPU 阻塞等待发送完成
 * - 适合 LCD 这种低速外设
 *========================================================*/
static inline void spi_write(u8 *buf, int len)
{
    XSpiPs_PolledTransfer(&Spi, buf, NULL, len);
}

/*=========================================================
 * LCD 写命令
 *---------------------------------------------------------
 * 流程:
 * 1. DC = 0(命令)
 * 2. SPI 发送 1 byte
 *========================================================*/
static void lcd_cmd(u8 cmd)
{
    dc_cmd();
    spi_write(&cmd, 1);
}

/*=========================================================
 * LCD 写数据
 *---------------------------------------------------------
 * 流程:
 * 1. DC = 1(数据)
 * 2. SPI 发送 1 byte
 *========================================================*/
static void lcd_data(u8 data)
{
    dc_data();
    spi_write(&data, 1);
}

/*=========================================================
 * LCD 硬件复位
 *---------------------------------------------------------
 * 时序要求:
 * RES 拉低 ≥10ms
 * RES 拉高后等待 ≥120ms
 *
 * 这是 ST7735 启动稳定关键步骤
 *========================================================*/
static void lcd_reset()
{
    res_low();
    usleep(20000);     // 保证复位时间充足
    res_high();
    usleep(120000);    // 等待内部振荡器稳定
}

/*=========================================================
 * 设置显示窗口(核心函数)
 *---------------------------------------------------------
 * 功能:
 * 指定 LCD GRAM 写入区域
 *
 * ST7735 使用 3 个命令:
 * 0x2A -> 列地址(X)
 * 0x2B -> 行地址(Y)
 * 0x2C -> 写显存开始
 *
 * 注意:
 * 必须加 LCD_XOFF / LCD_YOFF,否则图像错位
 *========================================================*/
static void lcd_set_addr(u16 x0, u16 y0, u16 x1, u16 y1)
{
    /* 加偏移(硬件坐标修正) */
    x0 += LCD_XOFF;
    x1 += LCD_XOFF;
    y0 += LCD_YOFF;
    y1 += LCD_YOFF;

    /*========================
     * 设置列地址
     *========================*/
    lcd_cmd(0x2A);
    dc_data();
    u8 col[] = {0, x0, 0, x1};
    spi_write(col, 4);

    /*========================
     * 设置行地址
     *========================*/
    lcd_cmd(0x2B);
    dc_data();
    u8 row[] = {0, y0, 0, y1};
    spi_write(row, 4);

    /*========================
     * 写入 GRAM
     *========================*/
    lcd_cmd(0x2C);
}

/*=========================================================
 * LCD 初始化流程
 *---------------------------------------------------------
 * 初始化步骤(必须严格顺序):
 * 1. 复位
 * 2. 退出睡眠
 * 3. 开启 IPS 模式
 * 4. 帧率配置
 * 5. 电源控制
 * 6. 像素格式
 * 7. 显示方向
 * 8. 开显示
 *========================================================*/
static void lcd_init()
{
    lcd_reset();

    lcd_cmd(0x11);      // Sleep Out(退出睡眠)
    usleep(120000);     // 必须等待内部稳定

    lcd_cmd(0x21);      // IPS 显示必须开启(反色控制)

    /*========================
     * 帧率控制
     *========================*/
    lcd_cmd(0xB1); lcd_data(0x05); lcd_data(0x3A); lcd_data(0x3A);
    lcd_cmd(0xB2); lcd_data(0x05); lcd_data(0x3A); lcd_data(0x3A);

    lcd_cmd(0xB4); lcd_data(0x03); // 反转控制

    /*========================
     * 电源控制
     *========================*/
    lcd_cmd(0xC0); lcd_data(0x62); lcd_data(0x02); lcd_data(0x04);
    lcd_cmd(0xC1); lcd_data(0xC0);
    lcd_cmd(0xC2); lcd_data(0x0D); lcd_data(0x00);

    lcd_cmd(0xC5); lcd_data(0x0E);

    /*========================
     * 像素格式 + 显示方向
     *========================*/
    lcd_cmd(0x3A); lcd_data(0x05);   // RGB565
    lcd_cmd(0x36); lcd_data(0xC8);   // 扫描方向控制

    lcd_cmd(0x29);      // Display ON(开启显示)
}

/*=========================================================
 * 全屏填充颜色
 *---------------------------------------------------------
 * 本质:
 * - 设置整个窗口
 * - 连续写 LCD_W * LCD_H 个像素
 *
 * 注意:
 * RGB565 = 2 byte / pixel
 *========================================================*/
static void lcd_clear(u16 color)
{
    lcd_set_addr(0, 0, LCD_W-1, LCD_H-1);

    dc_data(); // 进入数据模式

    u8 hi = color >> 8;
    u8 lo = color & 0xFF;

    for (int i = 0; i < LCD_W * LCD_H; i++) {
        u8 d[2] = {hi, lo};
        spi_write(d, 2);
    }
}

/*=========================================================
 * 画 8x8 字符 A
 *---------------------------------------------------------
 * A 使用点阵:
 * 每一行 8bit 表示像素开关
 *
 * fc = 前景色(字体颜色)
 * bc = 背景色
 *========================================================*/
static void lcd_draw_A(u16 x, u16 y, u16 fc, u16 bc)
{
    u8 A[8] = {
        0x18,
        0x24,
        0x42,
        0x7E,
        0x42,
        0x42,
        0x42,
        0x00
    };

    lcd_set_addr(x, y, x + 7, y + 7);

    dc_data();  // 进入数据模式

    for (int row = 0; row < 8; row++) {
        for (int col = 0; col < 8; col++) {

            u16 color;

            /* 判断当前像素是否属于字体笔画 */
            if (A[row] & (1 << (7 - col))) {
                color = fc;   // 字体颜色
            } else {
                color = bc;   // 背景颜色
            }

            u8 d[2] = { color >> 8, color & 0xFF };
            spi_write(d, 2);
        }
    }
}

/*=========================================================
 * 主函数
 *========================================================*/
int main()
{
    xil_printf("ST7735 ZYNQ OK\r\n");

    /*========================
     * SPI 初始化
     *========================*/
    XSpiPs_Config *cfg;
    cfg = XSpiPs_LookupConfig(SPI_DEVICE_ID);
    XSpiPs_CfgInitialize(&Spi, cfg, cfg->BaseAddress);

    XSpiPs_SetOptions(&Spi,
        XSPIPS_MASTER_OPTION |      // 主机模式
        XSPIPS_FORCE_SSELECT_OPTION // 强制片选控制
    );

    XSpiPs_SetClkPrescaler(&Spi, XSPIPS_CLK_PRESCALE_16);

    /*========================
     * EMIO GPIO 初始化
     *========================*/
    XGpioPs_Config *gcfg;
    gcfg = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    XGpioPs_CfgInitialize(&Gpio, gcfg, gcfg->BaseAddr);

    /* DC 输出配置 */
    XGpioPs_SetDirectionPin(&Gpio, PIN_DC, 1);
    XGpioPs_SetOutputEnablePin(&Gpio, PIN_DC, 1);

    /* RES 输出配置 */
    XGpioPs_SetDirectionPin(&Gpio, PIN_RES, 1);
    XGpioPs_SetOutputEnablePin(&Gpio, PIN_RES, 1);

    /*========================
     * LCD 初始化
     *========================*/
    lcd_init();

    /*========================
     * 主循环演示
     *========================*/
    while (1) {

        lcd_clear(0xF800); // 红色
        usleep(500000);

        lcd_clear(0x07E0); // 绿色
        usleep(500000);

        lcd_clear(0x001F); // 蓝色
        usleep(500000);

        /* 显示字母 A */
        lcd_draw_A(10, 20, 0xFFFF, 0x0000);

        usleep(500000);
    }
}

测试

全红,全黄, 全蓝, 字母A 之间循环播放

bash 复制代码
[10:22:25.989]收←◆=== ST7735 OK TEST ===

[10:22:26.304]收←◆DONE

[10:23:46.980]收←◆ST7735 ZYNQ OK

linux驱动

BD

与裸机共用,但把sd,emmc ,enet0 打开 linux_spi_oled_system.tcl

内核配置确认

bash 复制代码
$:grep -i SPI .config | grep -v "^#"
CONFIG_UNINLINE_SPIN_UNLOCK=y                # ❌ 非必须(内核锁优化)
CONFIG_MUTEX_SPIN_ON_OWNER=y                 # ❌ 非必须(锁优化)
CONFIG_RWSEM_SPIN_ON_OWNER=y                 # ❌ 非必须(锁优化)
CONFIG_LOCK_SPIN_ON_OWNER=y                  # ❌ 非必须(锁优化)
CONFIG_REGMAP_SPI=y                          # ❌ 非必须(SPI寄存器抽象框架,驱动用)
CONFIG_MTD_SPI_NOR=y                         # ❌ 非必须(SPI Flash / W25Qxx)
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y          # ❌ 非必须(Flash性能优化)
CONFIG_SPI=y                                 # ✔ 必须(SPI核心框架)
CONFIG_SPI_MASTER=y                          # ✔ 必须(SPI主机模式)
CONFIG_SPI_MEM=y                             # ❌ 非必须(SPI Flash/QSPI memory接口)
CONFIG_SPI_BITBANG=y                         # ❌ 非必须(GPIO模拟SPI,不用)
CONFIG_SPI_CADENCE=y                         # ✔ 必须(Zynq PS SPI底层驱动)
CONFIG_SPI_XILINX=y                          # ✔ 必须(Xilinx SPI控制器支持)
CONFIG_SPI_ZYNQ_QSPI=y                       # ❌ 非必须(QSPI Flash启动用)
CONFIG_RTC_I2C_AND_SPI=y                     # ❌ 非必须(RTC相关)
bash 复制代码
$:grep -i FB .config | grep -v "^#"
CONFIG_DRM_KMS_FB_HELPER=y        # ❌ 非必须(DRM转fb兼容层,用于老程序/X11)
CONFIG_DRM_FBDEV_EMULATION=y      # ❌ 非必须(DRM自动生成 /dev/fb0)
CONFIG_DRM_FBDEV_OVERALLOC=100    # ❌ 非必须(fb buffer额外预分配,性能参数)
CONFIG_FB_CMDLINE=y               # ❌ 非必须(允许bootargs配置fb参数)
CONFIG_FB_NOTIFY=y                # ❌ 非必须(fb事件通知机制)
CONFIG_FB=y                       # ✔ 必须(Framebuffer核心框架)
CONFIG_FB_CFB_FILLRECT=y         # ✔ 推荐(矩形填充加速)
CONFIG_FB_CFB_COPYAREA=y         # ✔ 推荐(显存区域拷贝)
CONFIG_FB_CFB_IMAGEBLIT=y        # ✔ 推荐(图像/字符绘制)
CONFIG_FB_SYS_FILLRECT=y         # ✔ 建议(软件fb基础实现)
CONFIG_FB_SYS_COPYAREA=y         # ✔ 建议
CONFIG_FB_SYS_IMAGEBLIT=y        # ✔ 建议
CONFIG_FB_SYS_FOPS=y             # ✔ 必须(/dev/fb0 用户接口)
CONFIG_FB_DEFERRED_IO=y          # ⭐ 强烈推荐(SPI LCD刷屏优化,减少卡顿)

设备树 system-user.dtsi

bash 复制代码
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/media/xilinx-vip.h>
#include <dt-bindings/phy/phy.h>

/ {
    model = "ant Board111";
    compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";

    /* =========================================================
     * LED
     * ========================================================= */
    leds {
        compatible = "gpio-leds";

        gpio-led1 {
            label = "led2";
            gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
            default-state = "on";
        };
        gpio-led5 {
            label = "ps_led0";
            gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
            default-state = "on";
        };

        gpio-led6 {
            label = "ps_led1";
            gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
            linux,default-trigger = "timer";
        };
    };

    /* =========================================================
     * KEY
     * ========================================================= */
    keys {
        compatible = "gpio-keys";
        autorepeat;

        gpio-key3 {
            label = "ps_key1";
            gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
            linux,code = <KEY_UP>;
        };

        gpio-key4 {
            label = "ps_key2";
            gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
            linux,code = <KEY_DOWN>;
        };
    };
};

/* =========================================================
 * UART / SD / QSPI
 * ========================================================= */
&uart0 {
    u-boot,dm-pre-reloc;
    status = "okay";
};

&sdhci0 {
    u-boot,dm-pre-reloc;
    status = "okay";
};

&qspi {
    u-boot,dm-pre-reloc;

    flash@0 {
        compatible = "w25q256", "jedec,spi-nor";
        reg = <0x0>;
        spi-max-frequency = <50000000>;

        partition@0 {
            label = "boot";
            reg = <0x00000000 0x00100000>;
        };
        partition@1 {
            label = "bootenv";
            reg = <0x00100000 0x00020000>;
        };
        partition@2 {
            label = "kernel";
            reg = <0x00540000 0x00500000>;
        };
    };
};

&gem0 {
    local-mac-address = [00 0a 35 00 8b 87];

    ethernet_phy: ethernet-phy@7 {
        reg = <0x7>;
    };
};

/* =========================================================
 * SPI 控制器
 * ========================================================= */
&spi1 {
    status = "disabled";
};
&spi0 {
    status = "okay";
    num-cs = <1>;
    is-decoded-cs;
    st7735@0 {
        compatible = "my,st7735s";
        reg = <0>;
        spi-max-frequency = <20000000>;
        /* SPI mode 0 */
        spi-cpol = <0>;
        spi-cpha = <0>;
        /* GPIO控制 */
        reset-gpios = <&gpio0 55 GPIO_ACTIVE_LOW>;
        dc-gpios    = <&gpio0 54 GPIO_ACTIVE_HIGH>;
        /* LCD参数 */
        width = <80>;
        height = <160>;

        rotate = <90>;
        invert = <1>;

        status = "okay";
    };
};

ST7735S LCD 驱动 (未使用设备树)

my_st7735.c

c 复制代码
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/of.h>

#define LCD_W       80
#define LCD_H       160
#define LCD_XOFF    26
#define LCD_YOFF    1

struct st7735 {
    struct spi_device *spi;
    struct gpio_desc *dc;
    struct gpio_desc *reset;
    struct delayed_work dwork;  // 定时切换
};

static int lcd_spi(struct st7735 *ctx, u8 *buf, int len)
{
    return spi_write_then_read(ctx->spi, buf, len, NULL, 0);
}

static void dc_cmd(struct st7735 *ctx)  { gpiod_set_value(ctx->dc, 0); }
static void dc_data(struct st7735 *ctx) { gpiod_set_value(ctx->dc, 1); }

static void lcd_reset(struct st7735 *ctx)
{
    gpiod_set_raw_value(ctx->reset, 0);
    msleep(20);
    gpiod_set_raw_value(ctx->reset, 1);
    msleep(120);
}

static void lcd_cmd(struct st7735 *ctx, u8 cmd)
{
    dc_cmd(ctx);
    lcd_spi(ctx, &cmd, 1);
}

static void lcd_data(struct st7735 *ctx, u8 data)
{
    dc_data(ctx);
    lcd_spi(ctx, &data, 1);
}

static void lcd_set_addr(struct st7735 *ctx, u16 x0, u16 y0, u16 x1, u16 y1)
{
    x0 += LCD_XOFF;
    x1 += LCD_XOFF;
    y0 += LCD_YOFF;
    y1 += LCD_YOFF;

    lcd_cmd(ctx, 0x2A);
    dc_data(ctx);
    u8 col[4] = {0, x0, 0, x1};
    lcd_spi(ctx, col, 4);

    lcd_cmd(ctx, 0x2B);
    dc_data(ctx);
    u8 row[4] = {0, y0, 0, y1};
    lcd_spi(ctx, row, 4);

    lcd_cmd(ctx, 0x2C);
}

static void lcd_init(struct st7735 *ctx)
{
    lcd_reset(ctx);
    lcd_cmd(ctx, 0x11); msleep(120);
    lcd_cmd(ctx, 0x21);

    lcd_cmd(ctx, 0xB1); lcd_data(ctx, 0x05); lcd_data(ctx, 0x3A); lcd_data(ctx, 0x3A);
    lcd_cmd(ctx, 0xB2); lcd_data(ctx, 0x05); lcd_data(ctx, 0x3A); lcd_data(ctx, 0x3A);
    lcd_cmd(ctx, 0xB4); lcd_data(ctx, 0x03);

    lcd_cmd(ctx, 0xC0); lcd_data(ctx, 0x62); lcd_data(ctx, 0x02); lcd_data(ctx, 0x04);
    lcd_cmd(ctx, 0xC1); lcd_data(ctx, 0xC0);
    lcd_cmd(ctx, 0xC2); lcd_data(ctx, 0x0D); lcd_data(ctx, 0x00);
    lcd_cmd(ctx, 0xC5); lcd_data(ctx, 0x0E);

    lcd_cmd(ctx, 0x3A); lcd_data(ctx, 0x05);
    lcd_cmd(ctx, 0x36); lcd_data(ctx, 0xC8);
    lcd_cmd(ctx, 0x29);
}

// ==========================
// 颜色填充函数
// ==========================
static void lcd_fill(struct st7735 *ctx, u16 color)
{
    lcd_set_addr(ctx, 0, 0, LCD_W-1, LCD_H-1);
    dc_data(ctx);
    u8 c[2] = {color >> 8, color & 0xFF};
    int i;
    for (i = 0; i < LCD_W * LCD_H; i++)
        lcd_spi(ctx, c, 2);
}

// 颜色定义
#define RED     0xF800
#define BLUE    0x001F
#define YELLOW  0xFFE0

static int color_idx = 0;

// 定时切换颜色
static void lcd_color_work(struct work_struct *work)
{
    struct st7735 *ctx = container_of(to_delayed_work(work), struct st7735, dwork);
    u16 color;

    if (color_idx == 0) color = RED;
    else if (color_idx == 1) color = BLUE;
    else color = YELLOW;

    lcd_fill(ctx, color);
    color_idx = (color_idx + 1) % 3;

    // 500ms 切换一次
    schedule_delayed_work(&ctx->dwork, msecs_to_jiffies(500));
}

static int st7735_probe(struct spi_device *spi)
{
    struct st7735 *ctx;

    // 完全使用你稳定的配置
    spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
    spi->max_speed_hz = 4000000;
    spi_setup(spi);

    ctx = devm_kzalloc(&spi->dev, sizeof(*ctx), GFP_KERNEL);
    ctx->spi = spi;

    ctx->dc = devm_gpiod_get(&spi->dev, "dc", GPIOD_OUT_LOW);
    ctx->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);

    spi_set_drvdata(spi, ctx);

    lcd_init(ctx);

    // 启动颜色切换
    INIT_DELAYED_WORK(&ctx->dwork, lcd_color_work);
    schedule_delayed_work(&ctx->dwork, 0);

    dev_info(&spi->dev, "红/蓝/黄自动切换\n");
    return 0;
}

static int st7735_remove(struct spi_device *spi)
{
    struct st7735 *ctx = spi_get_drvdata(spi);
    cancel_delayed_work_sync(&ctx->dwork);
    return 0;
}

static const struct of_device_id st7735_dt_ids[] = {
        { .compatible = "my,st7735s" },
        {},
};
MODULE_DEVICE_TABLE(of, st7735_dt_ids);

static struct spi_driver st7735_driver = {
        .driver = {
                .name = "my_st7735",
                .of_match_table = st7735_dt_ids,
        },
        .probe = st7735_probe,
        .remove = st7735_remove,
};

module_spi_driver(st7735_driver);
MODULE_LICENSE("GPL");

测试

bash 复制代码
# 红蓝黄交替
root@ant:/lib/modules/5.4.0-xilinx-v2020.2# insmod my_st7735.ko

ST7735S LCD 驱动 (绑定/dev/fb0)

bash 复制代码
# 查看分辨率
cat /sys/class/graphics/fb0/virtual_size

my_st7735_fb.c

c 复制代码
相关推荐
Orange_sparkle2 小时前
learn claude code学习记录-S05
学习
zhangrelay2 小时前
机器人工程专业:Lubuntu 26.04 + ROS2 Lyrical Luth 入门、进阶、精通全指南
笔记·学习
Orange_sparkle3 小时前
learn claude code学习记录-S06
学习
徒 花3 小时前
HCIP学习09 重发布(路由引入)+ 路由策略
网络·学习·hcip
:mnong3 小时前
跟着学伴AI项目设计分析学习安卓APP研发
android·人工智能·学习
头疼的程序员3 小时前
计算机网络:自顶向下方法(第七版)第九章 学习分享(三)
学习·计算机网络
千谦阙听3 小时前
数据结构最终章:万字详解排序算法!(内部排序)
c语言·数据结构·学习·算法·排序算法
三无推导3 小时前
GitHub爆火项目ChinaTextbook——开源如何重新定义教育普惠的边界
学习·开源·github
kk在加油3 小时前
python学习笔记(基础语法与变量、容器)
笔记·python·学习