Đã port thành công thư viện đồ họa LVGL lên STM32F407, màn hình LCD model MSP3526; nếu muốn đổi sang màn hình khác chỉ cần sửa lại driver LCD, dự án có cả bản FreeRTOS và bare-metal. Dùng SPI+DMA điều khiển màn hình.
Màn LCD này: độ phân giải 320×480, kích thước 3,5 inch, chip điều khiển ST7796, giao tiếp SPI; chip cảm ứng điện dung FT6336U, giao tiếp I²C.
Sau khi ép xung MCU, tốc độ khung toàn màn ~9 FPS, cập nhật cục bộ >30 FPS; với SPI thì có lẽ đã ổn.
- STM32 đọc cảm biến nhiệt độ/độ ẩm SHTC3 qua I²C phần cứng: https://blog.zeruns.com/archives/692.html
- Template STM32F407 đã port sẵn U8g2 (thư viện chuẩn): https://blog.zeruns.com/archives/722.html
- Driver OLED 0,96 inch trên STM32G4 (HAL), hỗ trợ I²C phần cứng & mềm: https://blog.zeruns.com/archives/776.html
Nhóm thảo luận điện tử/Vi điều khiển: 2169025065
Ảnh demo
Video demo: https://www.bilibili.com/video/BV1Ni421S7ta/
Giới thiệu LVGL
LVGL (Light & Versatile Graphics Library) là thư viện đồ họa mã nguồn mở, miễn phí, cung cấp mọi thứ cần thiết để tạo GUI nhúng: thành phần đồ họa dễ dùng, hiệu ứng đẹp, chiếm ít bộ nhớ.
Tính năng chính:
- Hàng loạt thành phần đồ họa mô-đun: nút, biểu đồ, danh sách, thanh trượt, hình ảnh…
- Cỗ máy đồ họa cao cấp: hoạt ảnh, khử răng cưa, trong suốt, cuộn mượt, pha trộn lớp…
- Hỗ trợ nhiều thiết bị đầu vào: cảm ứng, bàn phím, encoder, phím cứng…
- Đa màn hình
- Không phụ thuộc phần cứng, chạy được trên mọi LCD
- Cắt gọt linh hoạt (tối thiểu 64 kB Flash, 16 kB RAM)
- Đa ngôn ngữ UTF-8: tiếng Trung, Nhật, Hàn, Ả Rập…
- Layout kiểu CSS (Flexbox, Grid)
- Hỗ trợ RTOS, bộ nhớ ngoài, tăng tốc phần cứng (DMA2D của STM32, PXP/VGLite của NXP)
- Chạy mượt chỉ với một bộ đệm khung hình
- Viết hoàn toàn bằng C, gọi được từ C++
- Micropython binding
- Mô phỏng trên PC, không cần phần cứng
- Ví dụ phong phú, tài liệu & API đầy đủ
- Giấy phép MIT hoàn toàn miễn phí
Yêu cầu tối thiểu:
Hầu hết vi điều khiển hiện đại đều chạy được LVGL:
- MCU/CPU 16, 32 hoặc 64 bit
- Tốc độ clock khuyến nghị >16 MHz
- Flash/ROM: >64 kB cho bản rất gọn (khuyến nghị >180 kB)
- RAM:
– RAM tĩnh: ~2 kB, tùy tính năng & loại đối tượng
– Heap: >2 kB (khuyến nghị 8 kB)
– Dữ liệu động: >2 kB (nhiều đối tượng thì nên 16 kB), đặt qua LV_MEM_SIZE trong lv_conf.h
– Bộ đệm hiển thị: >chiều ngang pixel (khuyến nghị 10×chiều ngang)
– Một framebuffer trong MCU hoặc bộ điều khiển LCD - Trình biên dịch C99 trở lên
Trang chủ LVGL: https://lvgl.io/
Sơ đồ nối dây
| LCD屏 | MCU/开发板 | 功能描述 |
|---|---|---|
| GND | GND | LCD屏电源地 |
| VCC | 5V或3.3V | LCD屏电源正极 |
| LCD_CS | PE6 | LCD屏SPI片选 |
| LCD_RST | PC1 | LCD屏复位 |
| LCD_RS | PC0 | LCD屏命令/数据选择 |
| SDI/MOSI | PB5 | LCD屏SPI数据线,主机输出从机输入 |
| SCK | PB3 | LCD屏SPI时钟线 |
| LED | 3.3 V | 背光LED(可接IO,软件调光) |
| SDO/MISO | PB4 | LCD屏SPI数据线,主机输入从机输出 |
| CTP_SCL | PB8 | 电容触摸屏控制器I2C时钟线 |
| CTP_RST | PB7 | 电容触摸屏控制器复位 |
| CTP_SDA | PB9 | 电容触摸屏控制器I2C数据线 |
| CTP_INT | PB6 | 电容触摸屏控制器中断信号 |
Lưu ý: chân PB4 trên board mình dùng không ra header hai bên mà nằm trong cổng JTAG phía trên.
Tải tài liệu & mã nguồn
Tài liệu màn hình online: https://url.zeruns.com/68x3Y
Gói tài liệu màn hình – link 1: https://www.123pan.com/s/2Y9Djv-rZevH.html
Link 2: https://url.zeruns.com/gzBO4
Project STM32F407+LVGL bare-metal – link 1: https://url.zeruns.com/X242k
Link 2: https://pan.baidu.com/s/1vAhHijYd_aWvRr3_c1_WtA?pwd=ry4g
Project STM32F407+LVGL FreeRTOS – link 1: https://www.123pan.com/s/2Y9Djv-CzevH.html
Link 2: https://url.zeruns.com/0iOHF
Nhớ bấm Star nhé!
Mã nguồn Gitee: https://gitee.com/zeruns/STM32F407_LVGL_Template_MSP3526
GitHub: https://github.com/zeruns/STM32F407_LVGL_Template_MSP3526
(*) Bản mới nhất trên Gitee/GitHub dùng FreeRTOS; bản bare-metal nằm ở mục Releases, tag 0.1.3.
Project sinh bằng STM32CubeMX, phát triển với Keil5 + VScode + EIDE.
Mình tham khảo hướng dẫn của Zhengdian Yuanzi (正点原子) để port LVGL.
Video hướng dẫn của Zhengdian Yuanzi – link 1: https://www.123pan.com/s/2Y9Djv-0ZevH.html
Link 2: https://www.alipan.com/s/Pd6TDfT2rBL
Hướng dẫn sử dụng
Tải code về, biên dịch và nạp là chạy ngay.
Muốn tắt hiển thị FPS & CPU thì sửa trong lv_conf.h, đổi hai macro sau từ 1 thành 0:
/*1: Show CPU usage and FPS count*/
#define LV_USE_PERF_MONITOR 1
#if LV_USE_PERF_MONITOR
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
#endif
/*1: Show the used memory and the memory fragmentation
* Requires LV_MEM_CUSTOM = 0*/
#define LV_USE_MEM_MONITOR 1
#if LV_USE_MEM_MONITOR
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
#endif
```
Nếu dùng phiên bản FreeRTOS thì viết code trong file `freertos.c`, có thể dùng phần mềm STM32CubeMX để tạo thread và semaphore, sau đó sinh code; code sẽ được tự động đặt đúng vị trí quy định, nên dù sinh lại cũng không ảnh hưởng đoạn bạn đã viết. Phiên bản bare-metal thì chỉ việc viết code trực tiếp trong file `main.c`.
Muốn tắt chương trình Demo thì comment đoạn code trong hình dưới là xong.

## Địa chỉ mua linh kiện
- STM32F407VET6 development board: [https://s.click.taobao.com/sQSMWmt](https://s.click.taobao.com/t?e=m%3D2%26s%3DGxUVgIOWBWVw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2IT%2BVhjqUP7X0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAhscfsB2%2FyzZJq71CBMBeP%2F1SarTXhIOTsgIpc1WFZiJNubylQlnZt0ft88oCh4qlKjZ0Zrpn9cYR7kNHbGZ5w15bTaW0%2FWfaQBd0yVbMw3IeTeL3FeYp0owmLWBgEm80VKxcI130SjETn2JhMaQNtYWLhXkoGmYygFktLIh%2BAXuBHaXkFVFVVsYOae24fhW0&union_lens=lensId%3APUB%401716477927%40212abf30_0d16_18fa60ea164_1890%40025BlJPZdLaOG4oFPxX7gKUY%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_5a7fc953-12f7-46f5-8abf-f0725f8174cf_)
- Daplink downloader: [https://s.click.taobao.com/9kMKWmt](https://s.click.taobao.com/t?e=m%3D2%26s%3DTHTCnVvsTHtw4vFB6t2Z2ueEDrYVVa64YUrQeSeIhnK53hKxp7mNFrMfIvbtZ%2F%2B2mFKI%2FmDcMIH0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAFBcM8wkWlGmBPeR%2FUFCetKLWMw3EOEsyJN2owMjhufwDudUsQ2T%2Bdnc9abdYtRqDTzYdoB%2FDOjstFZhpb%2ByhLzPbHWUbis%2BWsZGiFV6vs3eSWi1ViPhRlULEkqTedE399KEV1g6mN9AKChukhDzWey1fmH6DK4UhxgxdTc00KD8%3D&union_lens=lensId%3APUB%401716478245%4021673e1b_0d06_18fa6137a23_e4cb%40023uxCV3Edv0RnAmphuKflFP%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_be2f7d85-fcee-40ff-96c5-d9d5bd472c5d_)
- MSP3526 screen: [https://s.click.taobao.com/i1Z29nt](https://s.click.taobao.com/t?e=m%3D2%26s%3DepCXgq%2FZmWBw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2tJl3z4Kcvjj0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMA%2FEM5jbZlb7P9R7R4oT9ML5ESMSIvSnZOMN7NXhFCiynJvjSktgLu1nmUrf%2BRsjyAm8kA6wY1r21y2p9AgG%2F91VmfPAhbcEJheBtNII99o%2FtnjWeMZ%2B39PZGZ9wPRcXV%2BQ%2FMlsmagC3ST4aDEgnPNca8ZkUY0DmW2xiXvDf8DaRs%3D&skuId=5223178287593&union_lens=lensId%3APUB%401716478528%40212c5298_0d1d_18fa617cd1e_3501%40034rs5qkRnldNGhC5eLF4gZ4%40eyJmbG9vcklkIjo4NTQ2Nywiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfZGV0YWlsX2h0bSIsInNyY0Zsb29ySWQiiOiiI4MDY3NCJ9%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_18bdbb55-0a4c-494e-96fc-a14c1b4c6732_)
- Dây nối Dupont: [https://s.click.taobao.com/W1wHWmt](https://s.click.taobao.com/t?e=m%3D2%26s%3DD%2BKEsm2G8bhw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2Sn8%2BqdSFAFT0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAhscfsB2%2FyzZJq71CBMBeP%2F1SarTXhIOTsgIpc1WFZiJNubylQlnZt5Tr%2BZsTRXxVoTwQXkQy%2BZ5FeGSAzHUbnuYhpSNeyz6v9H5aeGRpz8mogVv1SEjhEYwmLWBgEm80VKxcI130SjETn2JhMaQNtYWLhXkoGmYyO0%2FufYOLJc1EEap0MMy2i8YOae24fhW0&union_lens=lensId%3APUB%401716478612%402104b45c_0cd2_18fa619123a_652e%40023dY61JLu6wYjo297E4L0ip%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_c09a2639-b75e-40a9-8886-2b13dfb05f6a_)
- STM32F407VGT6 development board: [https://s.click.taobao.com/VjC29nt](https://s.click.taobao.com/t?e=m%3D2%26s%3DimgWkSQh79Jw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2VCC9Q%2BPYiL70JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAhscfsB2%2FyzZJq71CBMBeP%2F1SarTXhIOTsgIpc1WFZiJNubylQlnZt1PgRVjPwS2ItjXwer7KgrNYvdwnwfvUuaclSgSzfliuRVQ2zHzYrnKVyphVinEJT4wmLWBgEm80VKxcI130SjETn2JhMaQNtYWLhXkoGmYy0ZHJIUNbntFzUAbdwYp3usYOae24fhW0&union_lens=lensId%3APUB%401716478657%4021547cbb_0d71_18fa619c373_1476%40027J4l8QPFtC3F2VYygWUUdV%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_a456d2bb-5c50-4eb6-a55f-0e6f4ff87eed_)
## Đoạn code chính
Chủ yếu là gọi hàm fill LCD dưới đây trong hàm `disp_flush` của file `lv_port_disp.c`. Driver LCD được sửa từ example do nhà sản xuất màn hình cung cấp.
```c
/**
* @brief 填充LCD屏幕指定矩形区域
* 使用LVGL库的颜色值填充LCD指定区域。
* @param sx 起始X坐标
* @param sy 起始Y坐标
* @param ex 结束X坐标
* @param ey 结束Y坐标
* @param color_p 指向要填充的颜色的指针
*/
void LCD_Fill_LVGL(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, lv_color_t *color_p)
{
uint32_t i, j;
uint16_t width = ex - sx + 1; // 计算填充区域的宽度
uint16_t height = ey - sy + 1; // 计算填充区域的高度
uint32_t Pixel = width * height; // 计算填充区域像素个数
LCD_SetWindows(sx, sy, ex, ey); // 设置LCD的显示窗口为指定的区域
// for (i = 0; i < height; i++)
// {
// for (j = 0; j < width; j++){
// Lcd_WriteData_16Bit(color_p->full); // 写入数据
// }
// }
// 数据分割值, 用于分批发送数据
#define data_split 3000
uint8_t data[Pixel * 2]; // 创建一个数组用于存储颜色数据
for (i = 0; i < Pixel; i++)
{
// 将颜色数据从16位转换为两个8位的数据
data[i * 2] = (color_p->full) >> 8; // 获取高8位数据
data[i * 2 + 1] = (uint8_t)(color_p->full); // 获取低8位数据
color_p++; // 指向下一个颜色值
// 判断数据量是否大于10000,如果大于则分批发送数据
if (Pixel > 10000)
{
if ((i + 1) % data_split == 0)
{
if ((i + 1) == data_split)
{
Lcd_WriteData_DMA(data, data_split * 2); // 以DMA方式发送数据
}
else
{
while (HAL_SPI_GetState(LCD_SPI) != HAL_SPI_STATE_READY); // 等待SPI总线空闲
uint8_t *temp = &data[((uint16_t)((i + 1) / data_split) - 1) * data_split * 2]; // 获取剩余数据
Lcd_WriteData_DMA(temp, data_split * 2); // 以DMA方式发送数据
}
}
else if (((i + 1) % data_split > 0) && ((i + 1) > data_split) && (i == (Pixel - 1)))
{
if ((uint16_t)((i + 1) / data_split) == 1)
{
while (HAL_SPI_GetState(LCD_SPI) != HAL_SPI_STATE_READY)
; // 等待SPI总线空闲
uint8_t *temp = &data[data_split * 2]; // 获取剩余数据
Lcd_WriteData_DMA(temp, ((i + 1) % data_split) * 2); // 以DMA方式发送数据
}
else
{
while (HAL_SPI_GetState(LCD_SPI) != HAL_SPI_STATE_READY)
; // 等待SPI总线空闲
uint8_t *temp = &data[(uint16_t)((i + 1) / data_split) * data_split * 2]; // 获取剩余数据
Lcd_WriteData_DMA(temp, ((i + 1) % data_split) * 2);
}
}
}
}
if (Pixel <= 10000)
{
// 要发送的数据小于10000*2字节时一次全部发送
Lcd_WriteData_DMA(data, Pixel * 2);
}
LCD_SetWindows(0, 0, lcddev.width - 1, lcddev.height - 1); // 恢复窗口设置为全屏
}
Các dự án open-source khác đáng xem
- Mình làm bộ thu thập điện năng 3 pha open-source, tiện theo dõi điện nhà: https://blog.zeruns.com/archives/771.html
- Template STM32F407 chuẩn peripheral đã port sẵn thư viện đồ họa U8g2: https://blog.zeruns.com/archives/722.html
- Open-source board最小系统 CH32V307VCT6: https://blog.zeruns.com/archives/726.html
- Module nguồn DCDC buck-boost LM25118 điều chỉnh được: https://blog.zeruns.com/archives/727.html
- Module boost đồng bộ EG1164 công suất lớn open-source, hiệu suất tối đa 97%: https://blog.zeruns.com/archives/730.html
- Node cảm biến môi trường 4G dùng Air700E, đẩy dữ liệu nhiệt độ, độ ẩm, áp suất lên Alibaba Cloud qua MQTT: https://blog.zeruns.com/archives/747.html
- Tải điện tử thông minh dùng CH32V307 open-source, sản phẩm thiết kế cuộc thi nhúng: https://blog.zeruns.com/archives/785.html
Đọc thêm
- Giới thiệu VPS/cloud server giá rẻ, hiệu năng tốt: https://blog.zeruns.com/archives/383.html
- Hướng dẫn mở server Minecraft: https://blog.zeruns.com/tag/mc/
- Đánh giá nhanh nguồn RD6012P 60V 12A: https://blog.zeruns.com/archives/740.html
- Trải nghiệm mở hộp máy in 3D Bambu P1SC: https://blog.zeruns.com/archives/770.html
- So sánh thực tế các loại tụ và cuộn khác nhau (D, Q, ESR, X): https://blog.zeruns.com/archives/765.html
- Test & mổ xẻ củ sạc 120W giá 2.6 CNY trên TikTok Shop: https://blog.zeruns.com/archives/786.html





