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

【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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版