萤火工场GD32VW553-V2基于RTThread框架点亮2.4寸TFT LCD

分享作者:wx17693392898626
评测品牌:萤火工场
评测型号:GD32VW553-IOT-V2
发布时间:2026-03-24 16:11:51
0
概要
本次使用ICEasy商城免费申请的萤火工场GD32VW553 V2版本RISCV开发板,基于国产操作系统RTThread,点亮一块ILI9341驱动的TFT LCD屏幕
开源口碑分享内容

零.芯片简介

GD32VW553H_EVAL是兆易创新推出的一款GD32VW系列的评估板。开发板外观如下图所示:

GD32VW553系列双模无线MCU,支持Wi-Fi 6及Bluetooth LE 5.2无线连接,集成了高达4MB Flash及320KB SRAM,另有32KB可配置指令高速缓存(I-Cache),大幅提升了CPU处理效率。不仅具备出色的无线性能,芯片还配置了丰富的通用有线接口,包含3个U(S)ART、2个I2C、1个SPI以及1个四线制QSPI等, 以及多达29个可编程 GPIO 管脚。内置2个32位通用定时器、2个16位通用定时器、4个16位基本定时器、1个PWM高级定时器和1个12位ADC。供电电压1.8V - 3.6V,并提供了85℃  - 105℃宽温选择,以满足工控互联、照明设备以及插座面板等高温场景应用所需。

面向实时处理和高效通信需求,GD32VW553系列MCU采用了全新的开源指令集架构RISC-V处理器内核,主频可达160MHz,还配备了高级DSP硬件加速器、双精度浮点单元(FPU)以及指令扩展接口等资源,以出色的微架构设计实现了极佳的能效比,并提供了灵活的可扩展性。

一.搭建RT-Thread工程

1 环境准备

1.1 工具链

首先需要准备BSP编译所需的工具链,[工具链下载链接](https://www.gigadevice.com.cn/product/mcu/mcus-product-selector/gd32vw553hmq6),在该链接下载应用软件选项中的GD32 Embedded Builder。

工具链的相对路径如下:

> GD32EmbeddedBuilder_v1.5.2.30854\Tools\RISC-V Embedded GCC\8.2.0-2.2-20190521-0004\bin

1.2 下载工具

GD32VW553可以使用GD官方工具GD32AllInOneProgrammer下载,[GD32AllInOneProgrammer下载链接](https://www.gd32mcu.com/cn/download?kw=GD32+All-In-One+Programmer&lan=cn),编译出的固件可使用该软件下载。

1.3 RT-Thread ENV工具

RT-Thread的BSP可以使用官方env工具编译,需自行学习,[env下载链接](https://www.rt-thread.org/download.html#download-rt-thread-env-tool)。

2 固件编译

在BSP根路径下使用env工具打开BSP,示例如下:

然后执行pkgs --update命令添加当前BSP所需要的驱动库,示例如下(如果长时间未使用env,可首先

进行pkgs --upgrade更新软件包的链接索引)

(.venv) RTT@RSH-PC0001 E:\rt-thread\bsp\gd32\risc-v\gd32vw553h-eval
$ pkgs --upgrade
Error message:[Errno 2] No such file or directory: 'E:\\env-windows-v2.0.0\\env-windows\\tools\\bin\\..\\..\\tools\\scripts\\cmds\\.config'
open .config failed
[Use Github server - auto decision based on IP location]
Begin to upgrade env packages.
remote: Enumerating objects: 768, done.
remote: Counting objects: 100% (374/374), done.
remote: Compressing objects: 100% (16/16), done.
Receiving objects:  96% (738/768)
Receiving objects: 100% (768/768), 142.23 KiB | 5.69 MiB/s, done.
Resolving deltas: 100% (462/462), completed with 70 local objects.
From https://github.com/RT-Thread/packages
 * branch              HEAD       -> FETCH_HEAD
==============================>  Env packages upgrade done
(.venv) RTT@RSH-PC0001 E:\rt-thread\bsp\gd32\risc-v\gd32vw553h-eval
$ pkgs --update
接下来需要设置工具链字段,示例如下(使用时将下述路径调整为自己的工具链路径):
(.venv) RTT@RSH-PC0001 E:\rt-thread\bsp\gd32\risc-v\gd32vw553h-eval
$ set RTT_EXEC_PATH=E:\GD32\GD32VW5\GD32EmbeddedBuilder_v1.5.6_Rel\Tools\RISC-V Embedded GCC\8.2.0-2.2-20190521-0004\bin
接下来执行scons -j128命令编译工程,示例如下:
(.venv) RTT@RSH-PC0001 E:\rt-thread\bsp\gd32\risc-v\gd32vw553h-eval
$ scons -j16

成功编译会输出下述日志,并在BSP根路径生成**rtthread.bin**固件,该固件即下文需要烧录的固件。

LINK rtthread.elf
Memory region         Used Size  Region Size  %age Used
           flash:       66388 B         4 MB      1.58%
             ram:        288 KB       288 KB    100.00%
riscv-none-embed-objcopy -O binary rtthread.elf rtthread.bin
riscv-none-embed-size rtthread.elf
   text    data     bss     dec     hex filename
  65152    1200    7612   73964   120ec rtthread.elf
scons: done building targets.

3 固件烧录

固件烧录需要使用上述的GD32AllInOneProgrammer软件,

需要注意的是使用上述软件烧录时需要将boot1置为高电平,烧录结束后重新设置为低电平,手动调整板载的boot跳线帽。

4 运行结果

烧录完毕后,使用串口连接自己的串口终端软件,即可通过串口与开发板交互,示例如下:


 \ | /
- RT -     Thread Operating System
 / | \     5.2.1 build Mar 12 2026 14:51:49
 2006 - 2025 Copyright by RT-Thread team
Hello GD32VW553H
msh >
msh >ps
thread   pri  status      sp     stack size max used left tick   error  tcb addr
-------- ---  ------- ---------- ----------  ------  ---------- ------- ----------
tshell    20  running 0x000002d0 0x00001000    31%   0x00000009 OK      0x20002598
tidle0    31  ready   0x00000220 0x00000400    53%   0x00000019 OK      0x20000654
timer      4  suspend 0x00000290 0x00000400    64%   0x00000009 EINTRPT 0x20000ba8
main      10  suspend 0x00000280 0x00001000    17%   0x00000013 EINTRPT 0x200012b8
msh >

5 配置工程

需要利用 ENV 工具对BSP 进行配置,步骤如下:

1. 在 bsp 下打开 env 工具。

2. 输入`menuconfig`命令配置工程,配置好之后保存退出。

3. 输入`pkgs --update`命令更新软件包。

4. 输入`scons `命令重新编译工程。

二.编写SPI驱动代码

配置rt-thread的SPI驱动

使用文件资源管理器,进入目录rt-thread\bsp\gd32\risc-v\gd32vw553h-eval,在目录空白处点击右键选择ConEmu Here,打开rt-thread的env环境命令行。

使用pkgs —update命令下载gd32vw553的标准驱动库,在当前目录下的\packages\gd32-riscv-series-latest会下载好gd32vw553的标准驱动库文件。

输入menuconfig命令并按回车,进入配置rt-thread配置界面,通过光标控制箭头、Enter、ESC、空格等按键选择使能SPI。

Hardware Drivers Config  --->
    On-chip Peripheral Drivers  --->
        Enable SPI Bus --->
            Enable SPI0 Bus


退出时按Y即可保存config

然后输入scons编译,然后使用串口下载,然后连接串口终端,输入list device查看设备列表


编写LCD驱动

下面将通过修改GD原厂DEMO例程的方式来实现点屏

新建BSP文件夹,里面新增bsp_lcd.c和bsp_lcd.h

代码如下:

#include "bsp_lcd.h"
_lcd_dev lcddev;
static struct rt_spi_device *lcd_dev;
static void Lcd_reset(void)
{
    LCD_RST_CLR;
    DELAY(100);
    LCD_RST_SET;
    DELAY(50);
}
static void Lcd_wr_reg(uint8_t reg)
{
    LCD_DC_CLR;
    rt_spi_send(lcd_dev, ®, 1);
    LCD_DC_SET;
}
static void Lcd_wr_data(uint8_t data)
{
    rt_spi_send(lcd_dev, &data, 1);
}
static void Lcd_wr_data_16bit(uint16_t data)
{
    uint8_t buf[2];
    buf[0] = data >> 8;
    buf[1] = data & 0xff;
    Lcd_wr_data(buf[0]);
    Lcd_wr_data(buf[1]);
}
void Lcd_setwindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd)
{
     LCD_CS_CLR;
    /* write the register address 0x2A */
    Lcd_wr_reg(0x2A);
    Lcd_wr_data_16bit(xStar);
    Lcd_wr_data_16bit(xEnd);
    /* write the register address 0x2B */
    Lcd_wr_reg(0x2B);
    Lcd_wr_data_16bit(yStar);
    Lcd_wr_data_16bit(yEnd);
    /* write the register address 0x2C */
    Lcd_wr_reg(0x2C);
    LCD_CS_SET;
}
void Lcd_clear(uint16_t Color)
{
    unsigned int i, m;
    uint8_t* buf = (uint8_t*)rt_malloc(80);
    struct rt_spi_message msg;
    for (i = 0; i < 40; i++)
    {
        buf[2 * i] = Color >> 8;
        buf[2 * i + 1] = Color & 0xff;
    }
    Lcd_setwindows(0, 0, lcddev.width - 1, lcddev.height - 1);
    LCD_DC_SET;
    LCD_CS_CLR;
    for (i = 0; i < lcddev.height; i++)
    {
        for (m = 0; m < lcddev.width;)
        {
            m += 40;
            msg.send_buf   = buf;
            msg.recv_buf   = RT_NULL;
            msg.length     = 80;
            msg.cs_take    = 0;
            msg.cs_release = 0;
            msg.next       = 0;
            rt_spi_transfer_message(lcd_dev, &msg);
        }
    }
    LCD_CS_SET;
    rt_free(buf);
}
void lcd_fill_array_spi(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, void *Image)
{
    rt_uint32_t size = 0;
    size = (Xend - Xstart + 1) * (Yend - Ystart + 1) * 2;
    Lcd_setwindows(Xstart, Ystart, Xend, Yend);
    LCD_DC_SET;
    rt_spi_send(lcd_dev, Image, size);
}
static void Lcd_cmd_init(void)
{
    LCD_CS_CLR;
    Lcd_reset();
    /* write the register address 0xCB */
    Lcd_wr_reg(0xCB);
    Lcd_wr_data(0x39);
    Lcd_wr_data(0x2C);
    Lcd_wr_data(0x00);
    Lcd_wr_data(0x34);
    Lcd_wr_data(0x02);
    /* write the register address 0xCF */
    Lcd_wr_reg(0xCF);
    Lcd_wr_data(0x00);
    Lcd_wr_data(0XC1);
    Lcd_wr_data(0X30);
    /* write the register address 0xE8 */
    Lcd_wr_reg(0xE8);
    Lcd_wr_data(0x85);
    Lcd_wr_data(0x00);
    Lcd_wr_data(0x78);
    /* write the register address 0xEA */
    Lcd_wr_reg(0xEA);
    Lcd_wr_data(0x00);
    Lcd_wr_data(0x00);
    /* write the register address 0xED */
    Lcd_wr_reg(0xED);
    Lcd_wr_data(0x64);
    Lcd_wr_data(0x03);
    Lcd_wr_data(0X12);
    Lcd_wr_data(0X81);
    /* write the register address 0xF7 */
    Lcd_wr_reg(0xF7);
    Lcd_wr_data(0x20);
    /* power control VRH[5:0] */
    Lcd_wr_reg(0xC0);
    Lcd_wr_data(0x23);
    /* power control SAP[2:0];BT[3:0] */
    Lcd_wr_reg(0xC1);
    Lcd_wr_data(0x10);
    /* vcm control */
    Lcd_wr_reg(0xC5);
    Lcd_wr_data(0x3e);
    Lcd_wr_data(0x28); 
    /* vcm control2 */
    Lcd_wr_reg(0xC7);
    Lcd_wr_data(0x86);
    Lcd_wr_reg(0x36);
    Lcd_wr_data(0x48); 
    /* write the register address 0x3A */
    Lcd_wr_reg(0x3A);
    Lcd_wr_data(0x55);
    /* write the register address 0xB1 */
    Lcd_wr_reg(0xB1);
    Lcd_wr_data(0x00);
    Lcd_wr_data(0x18);
    /* display function control */
    Lcd_wr_reg(0xB6);
    Lcd_wr_data(0x08); 
    Lcd_wr_data(0x82);
    Lcd_wr_data(0x27);  
    /* 3gamma function disable */
    Lcd_wr_reg(0xF2);
    Lcd_wr_data(0x00); 
    /* gamma curve selected  */
    Lcd_wr_reg(0x26);
    Lcd_wr_data(0x01); 
    /* set gamma */
    Lcd_wr_reg(0xE0);
    Lcd_wr_data(0x0F);
    Lcd_wr_data(0x31);
    Lcd_wr_data(0x2B);
    Lcd_wr_data(0x0C);
    Lcd_wr_data(0x0E);
    Lcd_wr_data(0x08);
    Lcd_wr_data(0x4E);
    Lcd_wr_data(0xF1);
    Lcd_wr_data(0x37);
    Lcd_wr_data(0x07);
    Lcd_wr_data(0x10);
    Lcd_wr_data(0x03);
    Lcd_wr_data(0x0E);
    Lcd_wr_data(0x09);
    Lcd_wr_data(0x00);
    /* set gamma */
    Lcd_wr_reg(0XE1);
    Lcd_wr_data(0x00);
    Lcd_wr_data(0x0E);
    Lcd_wr_data(0x14);
    Lcd_wr_data(0x03);
    Lcd_wr_data(0x11);
    Lcd_wr_data(0x07);
    Lcd_wr_data(0x31);
    Lcd_wr_data(0xC1);
    Lcd_wr_data(0x48);
    Lcd_wr_data(0x08);
    Lcd_wr_data(0x0F);
    Lcd_wr_data(0x0C);
    Lcd_wr_data(0x31);
    Lcd_wr_data(0x36);
    Lcd_wr_data(0x0F);
    /* exit sleep */
    Lcd_wr_reg(0x11);
    DELAY(120); 
    /* display on */
    Lcd_wr_reg(0x29);
    Lcd_wr_reg(0x2c);
    LCD_CS_SET;
}
static void Lcd_pin_init(void)
{
    rt_pin_mode(LCD_DC_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LCD_RES_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LCD_CS_PIN, PIN_MODE_OUTPUT);
}
static void Lcd_init(void)
{
    Lcd_pin_init();
    lcddev.width=LCD_WIDTH;
    lcddev.height=LCD_HEIGHT;
    Lcd_reset();        /* LCD Hardware Reset */
    DELAY(120);         /* Delay 120ms */
    Lcd_cmd_init();    /* lcd init */
}
rt_err_t spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
{
    RT_ASSERT(bus_name != RT_NULL);
    RT_ASSERT(device_name != RT_NULL);
    rt_err_t result = RT_EOK;
    struct rt_spi_device *spi_device;
    /* attach the device to spi bus*/
    spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
    RT_ASSERT(spi_device != RT_NULL);
    result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL);
    if (RT_EOK != result)
    {
        LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
    }
    else
    {
        LOG_I("%s attach to %s done", device_name, bus_name);
    }
    return result;
}
rt_err_t spi_lcd_init(uint32_t freq)
{
    rt_err_t res = RT_EOK;
    spi_device_attach(LCD_SPI_BUS_NAME, LCD_SPI_DEVICE_NAME, LCD_CS_PIN);
    lcd_dev = (struct rt_spi_device *)rt_device_find(LCD_SPI_DEVICE_NAME);
    if (lcd_dev != RT_NULL)
    {
        struct rt_spi_configuration spi_config;
        spi_config.data_width = 8;
        spi_config.max_hz = freq * 1000 * 1000;
        spi_config.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
        rt_spi_configure(lcd_dev, &spi_config);
    }
    else
    {
        res = -RT_ERROR;
    }
    Lcd_init();
    Lcd_clear(WHITE);
    return res;
}

三.编写屏幕测试代码

引脚连接

模块屏幕
VCCVCC
GNDGND
PA12CS
PB12RST
PA9MOSI
PA11CLK
PA15BLK
PB13DC

在main.c中添加测试代码,如下:

static uint16_t color_array[] =
{
    WHITE, BLACK, BLUE, BRED,
    GRED, GBLUE, RED, YELLOW
};
static int lcd_spi_test(void)
{
    uint8_t index = 0;
    for (index = 0; index < sizeof(color_array) / sizeof(color_array[0]); index++)
    {
        Lcd_clear(color_array[index]);
        LOG_I("lcd clear color: %#x", color_array[index]);
        DELAY(200);
    }
    return RT_EOK;
}
MSH_CMD_EXPORT(lcd_spi_test, lcd will fill color => you need init lcd first);

然后使用scons命令编译、下载,打开串口终端,输入Tab键并按回车查看支持的命令列表,已经出现lcd的测试命令。

这样就可以执行刷屏测试!

全部评论
暂无评论
0/144