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

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

[复制链接]
donatello1996 发布时间:2026-7-15 20:02
       最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:
% `8 ?6 d8 h! P& N9 M; V 1.jpg 2.jpg 3.jpg 4.jpg / a& [9 v# H2 y( U
, g4 T: ~! f8 ]# s4 n# x' t! T3 N

9 d7 ]6 w/ ~: x4 j; _! q9 a: z* BSTM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。; Z) ~- }0 N6 B1 ~/ F
要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:
, ?0 d% Y+ N% w% Y: F% k7 K 5.JPG ; z* D1 s% R4 u1 [, m, Q
) T9 p. s/ s* [3 @% L( q& R

' O( d* h! P) Z9 L/ K9 L# ^其实就是要调通LCD刷入缓存和触摸坐标读取的功能:0 M3 m* O; G( w5 n- Q

/ r3 m, o- d5 Z' ~0 l3 k8 yvoid FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color)
1 \2 z3 q# w( `' a{
' c: p$ k( Q' M' W8 s    uint16_t height, width;
& E3 A; p# K7 l5 w2 {9 D+ w    uint16_t i, j;   
6 a7 N% G5 o( R! {' V   
" n  d, s( {3 }  m" {/ l9 r    width = ex - sx + 1;$ |+ R" s! i+ l2 Y
    height = ey - sy + 1;
% `4 a1 w) [' A( O; h; z- S' i
- {+ U/ R1 q: V    for (i = 0; i < height; i++)" A- y6 [2 y! |7 @# v3 t' ]3 I# c
    {
) p6 M1 u- v- S( j" }9 ]% Z/ b        lcd_set_cursor(sx, sy + i);0 S8 W. J. l# V* D+ d( a( g
        lcd_write_ram_prepare();) o! w( C2 j- h2 V, ?3 d$ q# I4 ?3 @5 `
. v* o- J: n  v- ^6 @
        for (j = 0; j < width; j++)
2 y  [) g' c  E" r5 t$ J; S        {. Q0 G+ n7 E( J6 a' n
            LCD->LCD_RAM = color[i * width + j];; a) h( P8 C8 v1 `; k  H
        }$ k9 ]/ l9 R& ]( R8 X/ g
    }
! o+ o5 }- n' ?! Q0 R}
! k9 r) J& p. W  Z# g; d: M6 f
3 E) z  c9 w7 B4 T/ b
, Z3 i. q2 L+ B+ C& R

. A, w8 q1 u8 r9 j( S' e& ~( k% Z+ b0 {# _" f
: C) ~* {/ T% l$ W. h
: G* g3 [7 Q8 M5 c+ Z  p" R* H
uint8_t tp_scan(uint8_t mode)7 L" }0 _, l4 x8 S" j
{+ m! X% ?8 ?3 V, [
    if (T_PEN == 0)     /* 有按键按下 */
( S; q5 K& U$ m, y, @% d    {
6 i! c1 x+ `1 ?        if (mode)       /* 读取物理坐标, 无需转换 */
0 M7 x& M& }4 f        {
# T8 b; Q2 P) Q, r            tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]);1 F( I, y/ Q" B+ A2 J: P" X
        }
$ Z+ Q$ K: e+ U5 i! A0 @* d        else if (tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]))     /* 读取屏幕坐标, 需要转换 */2 r$ n, k  A# t" y  a* }& X: r. ^" w- N
        {
' Y* J  r; x" L% u            /* 将X轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的X坐标值) */5 y" M& L& ^* K: z5 p
            tp_dev.x[0] = (signed short)(tp_dev.x[0] - tp_dev.xc) / tp_dev.xfac + lcddev.width / 2;6 p9 s: }' r& Z5 D! o# r

, E; c: a7 Y' j' V            /* 将Y轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的Y坐标值) */9 _( l( [2 S1 X' z; D2 ^: M  ?
            tp_dev.y[0] = (signed short)(tp_dev.y[0] - tp_dev.yc) / tp_dev.yfac + lcddev.height / 2;8 I: l3 x! u8 j8 X( k1 T7 y2 ~+ C$ o5 Z
        }
; w9 d) p( a8 h
# y5 w1 F2 d1 b, V3 M) E: o        if ((tp_dev.sta & TP_PRES_DOWN) == 0)   /* 之前没有被按下 */
3 T. r; V% A9 p, ^- w8 F        {, x( j( Z& d# B6 ^3 @: x( W- v1 `3 F4 \
            tp_dev.sta = TP_PRES_DOWN | TP_CATH_PRES;   /* 按键按下 */
4 c: o4 |6 Y! k& E! M/ R4 P            tp_dev.x[CT_MAX_TOUCH - 1] = tp_dev.x[0];   /* 记录第一次按下时的坐标 */
9 {  [% ?! _" z            tp_dev.y[CT_MAX_TOUCH - 1] = tp_dev.y[0];9 |( {9 X$ L4 @5 {  G& B% E
        }4 C0 E' ]" w  q- |& n) J! k# O
    }, R* o$ n1 ~# ^- W1 g
    else
: X% \+ T3 F: Z    {
; U' r) B- R0 Q1 ~        if (tp_dev.sta & TP_PRES_DOWN)      /* 之前是被按下的 */
! i7 `9 r. i( {* ?; Q, k8 q. c+ k% _        {
4 T' s. }1 G+ k$ g, P; W( y            tp_dev.sta &= ~TP_PRES_DOWN;    /* 标记按键松开 */
( [  I; ^9 A9 u3 o0 j6 U* Q        }
0 A, a' t4 j3 `" R2 \        else     /* 之前就没有被按下 */, X4 d4 f9 o% V) U
        {- o5 W( d4 z2 L$ v' R5 R/ D
            tp_dev.x[CT_MAX_TOUCH - 1] = 0;
+ E9 `0 R6 @& s8 M/ F6 K; P0 ?" O            tp_dev.y[CT_MAX_TOUCH - 1] = 0;
: k' ~8 l; @# M0 u            tp_dev.x[0] = 0xffff;
4 [9 C$ r$ O" Q" }1 D0 d2 U            tp_dev.y[0] = 0xffff;, f, v  U( O* K0 Z) H5 k
        }$ Z9 ~+ B+ \- s8 h2 O( b
    }1 V0 U! s: ~" C' W# b4 F
( p- c6 _/ R% I8 l8 ?* L
    return tp_dev.sta & TP_PRES_DOWN; /* 返回当前的触屏状态 */
: x; ^( L4 ^3 T$ j  B}
: v" D! L# [, d0 e

7 Q* u6 @. Z8 u) j& y' K* B3 G然后是从Github官网下载LVGL9.5:
7 D5 a( q6 z; h7 ?% u! u 6.JPG 7.JPG 8.JPG 9.JPG
9 W+ v0 D/ s* o/ t. Z; |, G+ _/ f9 u. n8 z: {
0 d2 M7 M8 C) Q9 K9 Y) x/ l6 N
可以看出来,LVGL9.5相比起LVGL9.3,更新了很多内容,主目录有疑似Zephyr的更新,libs目录也加入了3dmaths和webp的支持,也就是后续可能支持3D图形算法和网页端应用,很让人期待!将LVGL9.5代码放进单片机工程,并依次添加支持文件即可:! l0 _4 H' W+ U: l+ A
10.JPG . l1 ^7 c; {, u/ R3 y* R
+ U1 m/ z% e" n$ @+ @
, H+ P, ]" E( ^  h9 m  l( g0 Y
然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:
# J* v! S2 A# d: X* U- ~  ]! V 11.JPG
' F& B5 H) T; E4 P" H" @9 p4 l
4 ]$ k1 _0 r; e/ t$ l& {extern void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);
$ ]) G6 J* _& U  Y% h, }% N/ A! q8 M, O# x2 S4 c
static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)  _: w% D: l. h( t6 i) ^
{5 J$ Y3 d, S' x! L: W1 z% R
    if(disp_flush_enabled) , r! D# x) @2 y* K' }4 L: F
                {
( r) a1 i+ x5 q+ \% G1 {" G      int32_t x;+ t. A5 r3 j5 j  P4 m2 `
      int32_t y;
5 H4 d; j: M. c! @                        FMCTFTLCD_ST7796_Fill(area->x1 , area->y1 , area->x2 , area->y2 , px_map);& ?; A# y& O1 m' N4 c" p% Y
//        for(y = area->y1; y <= area->y2; y++)
3 H5 K, z7 K6 \  D& O* t* B//                                {1 r- b& ]; _' o: t" \
//            for(x = area->x1; x <= area->x2; x++)
) K! i4 {( C+ F/ }- S; u0 s+ `//                                                {
* g/ }  T+ m9 M- W+ s4 f//                px_map++;  V0 i1 n# q' l6 ]4 o
//            }4 i) S1 p0 h& P, I& E
//        }
5 f4 E1 o; v4 h$ C* z    }
8 T9 Y/ I8 J' j  H  g' E/ U. z
$ Q* z& y1 U/ a7 ]' o5 f& p; ~    /*IMPORTANT!!!
( J3 u: h0 @. s% q6 U     *Inform the graphics library that you are ready with the flushing*/  A# ^) R* D  l8 B: L+ o
    lv_display_flush_ready(disp_drv);
4 Z2 D# g% n- f}
- l0 B/ K! Z1 [) H. L* j

% b7 e2 C& T) J* N' ~' ]

  ]7 q& H7 |7 j9 y& L在indev_disp文件中添加触摸的支持:
2 ?5 y# X( y# h# g 12.JPG % B  D1 m9 U1 s0 f0 ?# ~
9 b2 ^" V7 E$ C
static bool touchpad_is_pressed(void)" r( c' U6 |8 I$ t- L$ _
{: ?+ y( n! v. T0 E$ I
                tp_dev.scan(0);
  m* q7 T0 w5 w3 J3 d+ Y: g                if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480)
1 |7 f; h2 L6 t8 f: n! k) E                {
! D: z7 ?$ ?- o( b! E                        //printf("%d %d.\n" , tp_dev.x[0] , tp_dev.y[0]);+ y2 |) S3 T- b8 p' f& ~
                        return true;
( {2 S6 M6 Y+ {* v, R: W; h. e                }; Q& y, z& W- M$ w7 W
    return false;- A0 s& @4 }( L1 r: A/ \+ c: @0 c
}
' r3 Z: }/ H. G8 l) H
6 a+ l* k$ `) x/*Get the x and y coordinates if the touchpad is pressed*/+ i/ l+ n  z2 X
static void touchpad_get_xy(int32_t * x, int32_t * y)
2 C) m) g) l/ z! y) u  e9 r{+ m& M% W" x; u
    /*Your code comes here*/
; m9 K8 E9 w9 Z6 y
( i: @$ m2 w6 c! [1 |$ L* v8 q    (*x) = tp_dev.x[0];+ s9 y6 |/ e( f
    (*y) = tp_dev.y[0];
' \# ?8 @/ k0 h* Z2 z# K. ~/ O/ _}
/ v- ~% V# ^4 e9 K0 G: e: z4 K6 ~6 f

) ]) P* a0 g+ o搞定,然后看看刷屏效果:" j) a7 \. @1 a. ^( b

" F0 Q( V8 ]( `8 {+ l. Q可以看出来,使用FMC并口来刷屏,效果还是很丝滑顺畅的,可以满足图形化界面显示要求。
4 ^/ N6 n3 v; y* |& H" K6 K( s4 h9 R- h& A1 t  s
' h  p4 ~$ t0 ]5 u' e6 f6 y
然后是一些额外的内容,对DMA MEM2MEM机制的尝试,我们知道FMC刷屏其实也是对RAM(GRAM显存)进行操作,因此理论上可以用DMA MEM2MEM机制来实现对刷屏的加速(并非DMA2D,DMA2D是针对LTDC接口的屏幕),参考野火H743挑战者例程:+ v. i' g8 k; Y3 l( ~
13.JPG 14.JPG 15.JPG
* Z# R* Z- `7 ]3 B. y# t7 O* a野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。/ p% g& T$ {0 m9 j

, d1 ^2 r! {, D3 c

6 L4 i$ b* O7 T, {) w( b, V; K使用这个例程移植到我自己的LVGL例程中,DMA MEM2MEM也不能正常工作,原因未知,还在探索中。* U5 c2 X1 ]4 B4 ?2 D- I' L2 n
/ M1 h  @: f, Q. B) g
" [1 |% }3 Q3 c' i0 D
赞 收藏 评论0 发布时间:2026-7-15 20:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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