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

【福利三:逢7发帖赢大礼】使用惠勤致远STM32H743VI开发板+ST7796并口彩屏移植LVGL9.5并分享一些额外内容

[复制链接]
donatello1996 发布时间:2026-7-15 20:02
       最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:: p2 Y+ ?, @  s. \
1.jpg 2.jpg 3.jpg 4.jpg
  k$ D9 o' H2 B4 v7 k
4 o/ a! Y- e) f9 ^0 N
" b! B6 l  S% W
STM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。1 M8 X. e' w, z$ V1 @  K
要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:
& [# _0 K# \/ ^) Z$ l  m* k 5.JPG * v9 @/ Z, d! a
* Z  \  M% n9 @( l
. G  ~: n, D7 Z' h( H
其实就是要调通LCD刷入缓存和触摸坐标读取的功能:
; X7 \; }. G- U. T' v- l
9 p! ]) ?: ?! I3 A, K) t) \void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color)8 N& F" `  g0 q$ }6 w7 a
{6 T9 u; W0 c- p& s; h
    uint16_t height, width;$ f/ c, G9 X, ~) {9 i' Q% l5 j8 N
    uint16_t i, j;   
3 }) K' y( {! u/ C    + @+ s& i% ~) j. j/ \
    width = ex - sx + 1;
% O/ D; C7 o; E' U0 I- B3 s    height = ey - sy + 1;" }2 ~& v1 a- r9 ~

. W9 C! E' q& z" C5 D0 n    for (i = 0; i < height; i++)' R" W3 `1 T- a0 Z" r' H4 W
    {
1 X1 M* H, d6 V, B" |  W        lcd_set_cursor(sx, sy + i);) N: h5 q1 k0 a9 I3 a
        lcd_write_ram_prepare();
3 g; t! C" I# n* J
4 ?$ m1 l9 ~* w! L: I! p/ [        for (j = 0; j < width; j++)
9 S7 ?; k# T/ p# Y5 r: J        {
- F# H# u) a- W% P' {( A9 U' C            LCD->LCD_RAM = color[i * width + j];9 T7 j# ]  ~4 Z' z
        }
1 e0 a* R5 M8 @1 f- C( A  i" o    }
6 M- o7 C1 b8 f6 f- c! I% p. w% d, r9 N, m}3 j* |5 N( N% R1 j" h1 e+ t$ P

0 a( q3 L* N, s$ B% @1 f- u+ d3 }: ?1 O! y, D* g( ]
" K4 G( `! Q! ]
: M: h4 F& ]# `% G! J

* j- f; D3 Z8 C1 e. `, e, m* m$ C* c
uint8_t tp_scan(uint8_t mode)
- u, `0 S0 f0 S( R0 Q{
' |+ H3 N& Q+ V2 z$ e7 q# `    if (T_PEN == 0)     /* 有按键按下 */6 N4 i" _" O; G, S' f$ Q4 S
    {
# f# _% ~5 J# I1 m        if (mode)       /* 读取物理坐标, 无需转换 */
# Q9 v1 Q6 |9 G& e! h+ q8 `3 h        {# f' j* [7 Z( }" N; W2 S7 K- J2 u
            tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]);
1 e$ \$ w1 e6 z4 r        }
8 W& b* a! R+ U6 a0 H! I5 n3 N        else if (tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]))     /* 读取屏幕坐标, 需要转换 */2 }; U0 }: g2 Z/ i
        {
5 t9 q& _$ h9 P4 m  S. I9 H: i3 s/ l            /* 将X轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的X坐标值) */$ R: k  l* C7 w& V7 G
            tp_dev.x[0] = (signed short)(tp_dev.x[0] - tp_dev.xc) / tp_dev.xfac + lcddev.width / 2;& q( X0 }# Q& k) Z* ^( k
9 q0 F" v& q% u' W9 c
            /* 将Y轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的Y坐标值) */
4 N$ o/ |  e& w. q2 t9 G( E' I            tp_dev.y[0] = (signed short)(tp_dev.y[0] - tp_dev.yc) / tp_dev.yfac + lcddev.height / 2;" |. ~- ]0 Q8 a' }0 A
        }4 p* c4 o6 t& J+ L% O2 `: ?2 B

9 R: u7 H& o: t; [5 {1 r$ D0 s% |+ F        if ((tp_dev.sta & TP_PRES_DOWN) == 0)   /* 之前没有被按下 */
; C) T4 ]9 y9 N6 k5 ?4 [" Q        {2 \4 I/ {+ I0 k1 l, L
            tp_dev.sta = TP_PRES_DOWN | TP_CATH_PRES;   /* 按键按下 */
5 B! A3 }# S+ P, b            tp_dev.x[CT_MAX_TOUCH - 1] = tp_dev.x[0];   /* 记录第一次按下时的坐标 */
. Q  |* v. [: a/ t. M. ?            tp_dev.y[CT_MAX_TOUCH - 1] = tp_dev.y[0];
( ~) N; Q  L! Z. Z4 d: f        }
$ s0 _/ l% k& N    }
2 Q% S4 L2 d( l; O* O/ l    else
- p, G, R* r9 R7 U/ S    {$ w2 L3 u" I" c7 R& h5 X
        if (tp_dev.sta & TP_PRES_DOWN)      /* 之前是被按下的 */6 A1 c- w% P" G. s* [9 T
        {3 t6 x2 k3 ]/ D  t+ r
            tp_dev.sta &= ~TP_PRES_DOWN;    /* 标记按键松开 */
7 e& }6 B9 ~$ H% x3 Z        }
3 i0 s+ A9 D) w5 |3 x2 E        else     /* 之前就没有被按下 */0 L( x% E; \6 W
        {) S0 t% [' m1 ~9 E  z8 J" j
            tp_dev.x[CT_MAX_TOUCH - 1] = 0;) N' x! K4 c. q, T+ J5 `
            tp_dev.y[CT_MAX_TOUCH - 1] = 0;+ t. g) W8 w0 G3 n
            tp_dev.x[0] = 0xffff;
! b# t' N0 {& x) @. {  L6 E            tp_dev.y[0] = 0xffff;
/ U0 `/ f8 x$ r, w# J: J1 Q2 e        }1 C+ M8 X( k1 P1 l1 k& M
    }
" _1 b( A' S' x. z5 d' j: R" U6 z1 H6 {, ]
    return tp_dev.sta & TP_PRES_DOWN; /* 返回当前的触屏状态 */
; ]0 T' M+ Y6 W7 B- Z}
0 k! ]7 {: n6 D, }3 e9 p
) u" o, T5 j2 y2 R
然后是从Github官网下载LVGL9.5:$ T8 ~' p2 J, z6 X$ I5 G
6.JPG 7.JPG 8.JPG 9.JPG & Q9 R" K# y) K) R* n

4 b, _9 N$ Q! B9 g' k. r4 [9 O* K
4 |* S5 ?# h1 j2 N, ~- Z- ?7 j! f
可以看出来,LVGL9.5相比起LVGL9.3,更新了很多内容,主目录有疑似Zephyr的更新,libs目录也加入了3dmaths和webp的支持,也就是后续可能支持3D图形算法和网页端应用,很让人期待!将LVGL9.5代码放进单片机工程,并依次添加支持文件即可:/ H  j! x: S/ s; W* \% a
10.JPG
+ P3 j8 J6 v) J+ c% t+ D
* J8 [- q4 S; W% {

# W9 a  d8 j  M& e' T然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:- U1 z  [+ B4 O4 P7 Y5 P( D
11.JPG
5 F( \) g( D' U3 m
- ?& ~" o8 I) e+ q6 vextern void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);& A) V, w6 s7 F* u; p1 ^
" ~7 v5 D, |1 R5 f! I" t
static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)* `$ c0 w1 Q! {1 g1 B
{
# i$ u* Q& |6 Q    if(disp_flush_enabled) ! v/ `, ^# h3 a( i/ V5 N" j
                {
4 y! g2 c" P4 D8 r' \# S      int32_t x;# U" e" ]  R  M. I* }) ]
      int32_t y;. V% b( j3 }7 A+ F5 g/ E$ f
                        FMCTFTLCD_ST7796_Fill(area->x1 , area->y1 , area->x2 , area->y2 , px_map);
' o+ u5 X) F& \+ ^% j1 g; A: r( H//        for(y = area->y1; y <= area->y2; y++)
, Y" W8 U4 X. Z- X- L: S/ i//                                {: _* Z* C5 K* B9 |
//            for(x = area->x1; x <= area->x2; x++) ! Q7 ~( Q5 n3 k# m2 T
//                                                {- p3 p; w+ a: S- f- x* @/ ?% B; O9 v
//                px_map++;* }3 H# k. R+ ?* k1 q& [3 G
//            }8 @2 @3 f. j% X+ }* c
//        }
- m5 E# e9 u% _! z+ O    }4 z, ^4 K0 f* }- r6 D; Q4 ~

: n2 L4 s5 I# ?1 i8 @3 O    /*IMPORTANT!!!
; p- E  \! _" H     *Inform the graphics library that you are ready with the flushing*/( a$ E$ Z' o) j" L# C
    lv_display_flush_ready(disp_drv);; ?1 N5 G* o4 |3 I& m3 [- I* t
}8 B) l% j* h" \5 Y7 Z
& j" D4 c5 z" K! R, _  T9 y) C: T1 f, `
' f& Q$ d. ?, K% ^% W
在indev_disp文件中添加触摸的支持:! m9 y( I; Y7 o" [9 d9 t
12.JPG 6 r$ W# Q' p6 p+ |9 E& F

$ k! v  w- L4 A5 O' m- B' K/ s. `) tstatic bool touchpad_is_pressed(void)& F7 N, J4 F' s3 F2 C# @% H. `
{
9 H- P9 q1 l" Y- _                tp_dev.scan(0);" u4 W5 [5 V' A
                if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480)
; s1 k* \8 a6 B( ]$ M* x                {4 u4 u6 u1 j/ o+ U; K* W$ v& N% W
                        //printf("%d %d.\n" , tp_dev.x[0] , tp_dev.y[0]);# a# \8 I# Q7 ~2 ~
                        return true;
0 `8 A& e, j/ P3 {                }7 I4 ~$ p" T0 ]3 \' N( ^
    return false;. s! ^( E9 b5 y3 \" @, R
}2 _% S0 I. a' S5 u9 K

& V2 F) D1 {3 Q1 e/*Get the x and y coordinates if the touchpad is pressed*/, A0 f6 y/ _% N9 Q( A& S
static void touchpad_get_xy(int32_t * x, int32_t * y)' a$ Z- f5 j! k
{; y( h7 x  p8 W4 p0 s
    /*Your code comes here*/
! }' q5 o7 Y+ ]% S/ r( k# S
" d: G$ S9 @, J4 N4 y/ f) O$ ?# }5 j    (*x) = tp_dev.x[0];, B( a" k& v" @) C+ `$ V
    (*y) = tp_dev.y[0];
$ {: V( f6 Q; v* O}' ~  O2 q' Y7 e' u; {; P2 B2 X1 u
2 J/ o  X$ W! l# `$ B5 N/ E
搞定,然后看看刷屏效果:
. Y9 n! O# w$ O/ I5 ?9 }
! k- V8 K0 l6 y& V8 |  a7 S可以看出来,使用FMC并口来刷屏,效果还是很丝滑顺畅的,可以满足图形化界面显示要求。& b# E5 @( I7 k1 r7 q
4 F5 T  D, F- n2 B; z& r3 F

$ ^" S( b0 [! E0 s( D. B然后是一些额外的内容,对DMA MEM2MEM机制的尝试,我们知道FMC刷屏其实也是对RAM(GRAM显存)进行操作,因此理论上可以用DMA MEM2MEM机制来实现对刷屏的加速(并非DMA2D,DMA2D是针对LTDC接口的屏幕),参考野火H743挑战者例程:
# |2 l) g! `# @* [9 U, ~ 13.JPG 14.JPG 15.JPG 8 l# s; _+ Y8 W) B
野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。
3 j6 X! ]6 P1 ^" `' N
8 s% d1 d7 p# H; {

$ n) T9 Z  L5 Z. [使用这个例程移植到我自己的LVGL例程中,DMA MEM2MEM也不能正常工作,原因未知,还在探索中。& H6 d& C! \9 h, g: h
4 d$ Z4 J: d, E
$ a# r; D. u3 c- r4 {+ z
赞 收藏 评论0 发布时间:2026-7-15 20:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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