你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【Zephyr | STM32L562-DK】2 基于LCD的hello_world测试

[复制链接]
lugl 发布时间:2026-9-8 12:17

基于Zephyr RTOS LCD图形化测试

Zephyr已经完美支持这块开发板了,本篇将分享如何快速进行lcd的hello world测试

添加LCD显示支持

在prj.conf中添加display开关,即可以把开发板上的LCD加入驱动并参与编译

CONFIG_DISPLAY=y

测试程序

在src目录下面添加lcd_test.c

/*
 * LCD test for STM32L562E-DK on-board 240x240 TFT (ST7789V via FMC MIPI-DBI).
 * Draws text, color blocks and curves using the raw Zephyr display API,
 * no LVGL involved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/display.h>

#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#include "lcd_test.h"

#define LCD_W 240
#define LCD_H 240

/* RGB565 colors (host order, byte swap handled at draw time if needed) */
#define COLOR_BLACK   0x0000
#define COLOR_WHITE   0xFFFF
#define COLOR_RED     0xF800
#define COLOR_GREEN   0x07E0
#define COLOR_BLUE    0x001F
#define COLOR_YELLOW  0xFFE0
#define COLOR_CYAN    0x07FF
#define COLOR_MAGENTA 0xF81F
#define COLOR_GRAY    0x8410

/* Full-screen framebuffer: 240 * 240 * 2 = 115200 bytes */
static uint16_t fb[LCD_W * LCD_H];
static bool fb_swap_bytes;

struct glyph {
    char ch;
    uint8_t row[8]; /* bit 7 = leftmost column */
};

/* 5x7 font in an 8x8 cell (columns 1-5 used), uppercase + digits */
static const struct glyph font[] = {
    { ' ', { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
    { '!', { 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00 } },
    { '-', { 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00 } },
    { '.', { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00 } },
    { ':', { 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00 } },
    { '0', { 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 } },
    { '1', { 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 } },
    { '2', { 0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x7C, 0x00 } },
    { '3', { 0x38, 0x44, 0x04, 0x18, 0x04, 0x44, 0x38, 0x00 } },
    { '4', { 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00 } },
    { '5', { 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00 } },
    { '6', { 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00 } },
    { '7', { 0x7C, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x00 } },
    { '8', { 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00 } },
    { '9', { 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00 } },
    { 'A', { 0x38, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00 } },
    { 'B', { 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 } },
    { 'C', { 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 } },
    { 'D', { 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x00 } },
    { 'E', { 0x7C, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7C, 0x00 } },
    { 'F', { 0x7C, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 } },
    { 'G', { 0x38, 0x44, 0x40, 0x5C, 0x44, 0x44, 0x38, 0x00 } },
    { 'H', { 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00 } },
    { 'I', { 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 } },
    { 'J', { 0x1C, 0x08, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00 } },
    { 'K', { 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 } },
    { 'L', { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00 } },
    { 'M', { 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00 } },
    { 'N', { 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x44, 0x00 } },
    { 'O', { 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 } },
    { 'P', { 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00 } },
    { 'Q', { 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00 } },
    { 'R', { 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00 } },
    { 'S', { 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00 } },
    { 'T', { 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 } },
    { 'U', { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 } },
    { 'V', { 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 } },
    { 'W', { 0x44, 0x44, 0x44, 0x54, 0x54, 0x6C, 0x44, 0x00 } },
    { 'X', { 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 } },
    { 'Y', { 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00 } },
    { 'Z', { 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00 } },
};

static const struct glyph *find_glyph(char ch)
{
    ch = toupper((unsigned char)ch);
    for (size_t i = 0; i < ARRAY_SIZE(font); i++) {
        if (font[i].ch == ch) {
            return &font[i];
        }
    }
    return &font[0]; /* space */
}

static inline void fb_pixel(int x, int y, uint16_t color565)
{
    if (x < 0 || x >= LCD_W || y < 0 || y >= LCD_H) {
        return;
    }
    fb[y * LCD_W + x] = fb_swap_bytes ? (uint16_t)((color565 >> 8) | (color565 << 8))
                      : color565;
}

static void fb_fill(uint16_t color565)
{
    uint16_t c = fb_swap_bytes ? (uint16_t)((color565 >> 8) | (color565 << 8))
                   : color565;

    for (size_t i = 0; i < LCD_W * LCD_H; i++) {
        fb[i] = c;
    }
}

static void fb_fill_rect(int x, int y, int w, int h, uint16_t color565)
{
    for (int j = y; j < y + h; j++) {
        for (int i = x; i < x + w; i++) {
            fb_pixel(i, j, color565);
        }
    }
}

static void fb_draw_rect(int x, int y, int w, int h, uint16_t color565)
{
    for (int i = x; i < x + w; i++) {
        fb_pixel(i, y, color565);
        fb_pixel(i, y + h - 1, color565);
    }
    for (int j = y; j < y + h; j++) {
        fb_pixel(x, j, color565);
        fb_pixel(x + w - 1, j, color565);
    }
}

/* Bresenham line */
static void fb_draw_line(int x0, int y0, int x1, int y1, uint16_t color565)
{
    int dx = abs(x1 - x0);
    int dy = -abs(y1 - y0);
    int sx = x0 < x1 ? 1 : -1;
    int sy = y0 < y1 ? 1 : -1;
    int err = dx + dy;

    for (;;) {
        fb_pixel(x0, y0, color565);
        if (x0 == x1 && y0 == y1) {
            break;
        }
        int e2 = 2 * err;

        if (e2 >= dy) {
            err += dy;
            x0 += sx;
        }
        if (e2 <= dx) {
            err += dx;
            y0 += sy;
        }
    }
}

static void fb_draw_char(int x, int y, char ch, int scale, uint16_t color565)
{
    const struct glyph *g = find_glyph(ch);

    for (int r = 0; r < 8; r++) {
        for (int c = 0; c < 8; c++) {
            if (g->row[r] & (0x80 >> c)) {
                fb_fill_rect(x + c * scale, y + r * scale,
                         scale, scale, color565);
            }
        }
    }
}

static void fb_draw_string(int x, int y, const char *s, int scale, uint16_t color565)
{
    int cx = x;

    while (*s) {
        fb_draw_char(cx, y, *s++, scale, color565);
        cx += 6 * scale; /* 5 px glyph + 1 px spacing, scaled */
    }
}

int lcd_test_run(void)
{
    const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
    struct display_capabilities caps;

    if (!device_is_ready(dev)) {
        printk("LCD: display device not ready\n");
        return -ENODEV;
    }

    display_get_capabilities(dev, &caps);
    fb_swap_bytes = (caps.current_pixel_format == PIXEL_FORMAT_RGB_565X);

    printk("LCD: %ux%u, pixel format 0x%x%s\n",
           caps.x_resolution, caps.y_resolution, caps.current_pixel_format,
           fb_swap_bytes ? " (byte swapped)" : "");

    /* 1. background */
    fb_fill(COLOR_BLACK);

    /* 2. text */
    fb_draw_string(30, 12, "HELLO LCD!", 3, COLOR_WHITE);
    fb_draw_string(42, 48, "STM32L562E-DK", 2, COLOR_CYAN);

    /* 3. color blocks with white frames */
    fb_fill_rect(20, 80, 60, 50, COLOR_RED);
    fb_draw_rect(20, 80, 60, 50, COLOR_WHITE);
    fb_fill_rect(90, 80, 60, 50, COLOR_GREEN);
    fb_draw_rect(90, 80, 60, 50, COLOR_WHITE);
    fb_fill_rect(160, 80, 60, 50, COLOR_BLUE);
    fb_draw_rect(160, 80, 60, 50, COLOR_WHITE);

    /* 4. curves: sine (yellow) and cosine (magenta), 2.5 periods */
    fb_draw_line(10, 195, 230, 195, COLOR_GRAY); /* x axis */
    fb_draw_string(12, 150, "SIN", 1, COLOR_YELLOW);
    fb_draw_string(52, 150, "COS", 1, COLOR_MAGENTA);

    int prev_sin_y = 0, prev_cos_y = 0;

    for (int x = 10; x <= 230; x += 2) {
        float t = (float)(x - 10) / 220.0f * 2.5f * 2.0f * 3.14159265f;
        int sin_y = 195 - (int)(28.0f * sinf(t));
        int cos_y = 195 - (int)(28.0f * cosf(t));

        if (x > 10) {
            fb_draw_line(x - 2, prev_sin_y, x, sin_y, COLOR_YELLOW);
            fb_draw_line(x - 2, prev_cos_y, x, cos_y, COLOR_MAGENTA);
        }
        prev_sin_y = sin_y;
        prev_cos_y = cos_y;
    }

    /* flush whole framebuffer to the panel */
    struct display_buffer_descriptor desc = {
        .buf_size = sizeof(fb),
        .width = LCD_W,
        .pitch = LCD_W,
        .height = LCD_H,
    };

    display_blanking_off(dev);
    int ret = display_write(dev, 0, 0, &desc, fb);

    if (ret != 0) {
        printk("LCD: display_write failed: %d\n", ret);
        return ret;
    }

    printk("LCD: test pattern written\n");
    return 0;
}

并添加lcd_test.h把test开放出来

/*
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef LCD_TEST_H_
#define LCD_TEST_H_

int lcd_test_run(void);

#endif /* LCD_TEST_H_ */

3、在main.c中添加 lcd_test_run

#include <stdio.h>
#include <zephyr/kernel.h>

#include "lcd_test.h"

int main(void)
{
    printf("Hello World! %s\n", CONFIG_BOARD_TARGET);

    int ret = lcd_test_run();

    printf("LCD test %s\n", ret == 0 ? "passed" : "failed");

    return 0;
}

效果展示

编译下载后,可以看到绘出了完美的helloworld的测试界面:

hellowld.png

总结

Zephyr RTOS完美支持这块开发板,只需要添加lcd开关即可成功驱动。不需要复杂的配置即可实现。

收藏 评论0 发布时间:2026-9-8 12:17

举报

0个回答

所属标签

ST中文论坛活动

即日起开启活动话题入口,之后的活动统一都放在此处,欢迎大家的加入!


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版