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

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

[复制链接]
donatello1996 发布时间:2026-7-15 20:02
       最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:; N" j( ~$ q6 v5 ^, N2 [
1.jpg 2.jpg 3.jpg 4.jpg
$ b+ }, [( w- i! y: M8 h/ ?  G
; N3 L1 N! D: J. |4 {
4 y- m2 C: ?! \. I6 F  O
STM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。
- b1 _% k2 D( I0 A5 V7 U要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:" z3 h- q, Z) b  E! j) e
5.JPG
! _4 m$ K! Q: J' d2 \0 @
' Y7 R; h. n9 |9 ^+ p

9 o7 }% V  `/ T" `7 S5 b! p0 y其实就是要调通LCD刷入缓存和触摸坐标读取的功能:# V9 y7 C' W5 T

. e+ G3 o7 X* @) D0 b+ k; v8 svoid FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color)
* P, V2 c/ o0 ]0 l# k* {{
0 w4 B9 H1 b) k. @' ~# u' N, _    uint16_t height, width;
, W/ F6 e8 a( r0 |. ~) z3 ]. P# a9 ?    uint16_t i, j;   
! ?5 f/ X& e) \! m) E9 `1 l    ) m2 \. f  E" E' ^+ d
    width = ex - sx + 1;! ~+ v0 d9 j5 f, q* G
    height = ey - sy + 1;
1 O6 m! |# `8 i) x3 v- b
) I: g5 v0 u5 m  c. s3 K    for (i = 0; i < height; i++)# }+ n7 H  f* H% X+ v# L
    {
* D7 _) K! x( \2 ?: c        lcd_set_cursor(sx, sy + i);5 m! p% g( G* ^
        lcd_write_ram_prepare();$ `$ z& f3 O5 d" d3 J2 e* F0 S- S0 j/ @
' K+ d; y, b& I' u0 O, Q  f4 c
        for (j = 0; j < width; j++)
+ L+ W9 Y0 ~9 L, e0 N        {
" N9 `8 @7 ]& m            LCD->LCD_RAM = color[i * width + j];
6 x( g* `8 r4 C3 ~        }% j' U  z: o8 o1 r* f! b
    }
  B* _  L* {$ B# |( E  L0 ~6 Q, F}+ k) t. l; b2 k; C1 g% H, U
, B1 H! C6 r* s1 y2 v" k
/ F4 q! N8 n9 K& w) @1 {

. x' }0 t% [8 Q" R9 a" }
. Q! N0 e1 E, u! H9 i5 h- A
/ N- a" G6 u. }0 s# h! P1 F

' U, ^3 m, Y3 B# kuint8_t tp_scan(uint8_t mode)
2 q' F0 c1 X* d" q& n& n! p1 F% t" b/ ~{
1 B& O; _, B- t' w1 O    if (T_PEN == 0)     /* 有按键按下 */
" O5 w9 G; F! G8 \" f9 y- J    {2 \3 P8 Y$ X$ c1 P
        if (mode)       /* 读取物理坐标, 无需转换 */
- b" O8 I; P2 b1 ?5 b8 Q: o# ]! M        {- Q# ?: b6 w# K0 W
            tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]);8 w( f2 B  l5 @$ J( Z  \/ u
        }
# r  T9 ]7 `' @, z2 P( i/ {        else if (tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]))     /* 读取屏幕坐标, 需要转换 */) ^+ c, v# a% p- E  c
        {
( G* _0 B0 l% q5 S# l8 A            /* 将X轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的X坐标值) */1 G6 d7 h( l# _/ E; }# g9 F) P( J
            tp_dev.x[0] = (signed short)(tp_dev.x[0] - tp_dev.xc) / tp_dev.xfac + lcddev.width / 2;+ @# R" ^: F" c/ [6 z' p

; N  ]: {6 C/ H+ _; h) z            /* 将Y轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的Y坐标值) */, n4 b3 R5 E5 e, K: Y- B  ^5 a5 W6 \
            tp_dev.y[0] = (signed short)(tp_dev.y[0] - tp_dev.yc) / tp_dev.yfac + lcddev.height / 2;
% D7 {+ U8 e9 J6 ~' u- \) ^( k        }$ p+ u0 Z8 c* E/ }
+ B6 k* t! I' [7 B$ p5 E7 [
        if ((tp_dev.sta & TP_PRES_DOWN) == 0)   /* 之前没有被按下 */- U/ |, y. C- y# N. `& a7 ^" S" M& o
        {3 V( i( ^: k2 P: ?, d/ j' s
            tp_dev.sta = TP_PRES_DOWN | TP_CATH_PRES;   /* 按键按下 */
8 n% K- R/ k' t4 y! r/ `8 w            tp_dev.x[CT_MAX_TOUCH - 1] = tp_dev.x[0];   /* 记录第一次按下时的坐标 */, d" L' C8 Z9 t4 K
            tp_dev.y[CT_MAX_TOUCH - 1] = tp_dev.y[0];
; h  m2 H* D" G, ?) e0 w        }
7 w9 d/ D" ~' N; L4 _+ {0 _! z( C    }5 m9 ~2 C- \5 D* m2 }# P, p
    else9 M8 f. Q  n- H  N
    {
, S8 o. V0 r. _7 T0 ~        if (tp_dev.sta & TP_PRES_DOWN)      /* 之前是被按下的 */% P+ r; L0 \! i  [7 E
        {' r% u) B2 F5 }9 }' S/ [+ H4 B2 }" g
            tp_dev.sta &= ~TP_PRES_DOWN;    /* 标记按键松开 */3 g. j  n, |$ p7 c  w/ C: |
        }
  H4 n" x( w/ k& \9 ]- p- b! C        else     /* 之前就没有被按下 */) S, F4 N6 P. O. |( ]2 S. v- Q! C, g
        {
/ H5 t' j6 K1 |7 |            tp_dev.x[CT_MAX_TOUCH - 1] = 0;) n9 A* Q1 Z. V2 b3 k2 n: U$ }1 {6 X' [
            tp_dev.y[CT_MAX_TOUCH - 1] = 0;7 \  S5 i+ m# R, p, |5 Y
            tp_dev.x[0] = 0xffff;8 s: H% p( c- b1 w. N& [$ J+ y
            tp_dev.y[0] = 0xffff;7 {2 J6 y3 p5 r% _* w
        }+ A) ^' S2 o1 _7 K" M3 v
    }
# {' T# y, a% t& L
: S& h0 p! D* P3 `# W    return tp_dev.sta & TP_PRES_DOWN; /* 返回当前的触屏状态 */+ a# {1 f! ^! @, z* g
}% u) k/ x( m) X# R" @0 o8 s+ \

7 e6 Z5 {9 `" x然后是从Github官网下载LVGL9.5:
9 u' R9 m* l9 |: R! `; g 6.JPG 7.JPG 8.JPG 9.JPG
+ W" q: X0 A2 |: ?! o8 v1 L! @
) A+ W0 A% j  b% |/ E
7 |* k. Z2 P8 C
可以看出来,LVGL9.5相比起LVGL9.3,更新了很多内容,主目录有疑似Zephyr的更新,libs目录也加入了3dmaths和webp的支持,也就是后续可能支持3D图形算法和网页端应用,很让人期待!将LVGL9.5代码放进单片机工程,并依次添加支持文件即可:! T( X" `3 J* G: B" n2 w& p% \6 r; [
10.JPG + _8 B/ M! l2 Z4 u( m; m0 ]- E( c

/ a2 P; j5 Y0 ~. M$ d" Q
2 p! P, Y; q+ ^4 q3 r0 M) i
然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:
: `* S8 _% n' f. Q" B: h 11.JPG
/ v6 |9 W2 X& [
5 K0 R5 S! J' ?; B* Uextern void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);8 g/ N! A# D) W% i! v

- z9 q3 e2 M+ b7 D2 k* b4 wstatic void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
1 P% ?1 H' H$ b{  j' L0 \7 v$ C2 h. \& ~7 Y
    if(disp_flush_enabled) . u2 u* _) d' M& T, ~# `
                {
. r8 G7 x6 _# E, f      int32_t x;8 x3 z* c& g9 \2 O0 l8 G
      int32_t y;& ?4 C, }7 I! h2 ]( I. c+ [. ]
                        FMCTFTLCD_ST7796_Fill(area->x1 , area->y1 , area->x2 , area->y2 , px_map);  V6 d1 \+ a; x& o3 ?) u7 ]
//        for(y = area->y1; y <= area->y2; y++) ' v% ?. H7 _, l% ?
//                                {
6 k) C: U& S: ^8 x//            for(x = area->x1; x <= area->x2; x++)
; S% c9 A! O4 X. Y' A//                                                {
6 N! j6 e( U& S8 f//                px_map++;
& n9 G6 P$ B. v6 L//            }
0 Y# R" V) h% O  E1 W( }9 A//        }
1 ?% _3 V) V; K. \2 ~# D) H4 f% C    }4 D+ T3 c; F3 C. L, z

8 M% s/ X! L  M    /*IMPORTANT!!!1 M7 Y% G; ^& t( i
     *Inform the graphics library that you are ready with the flushing*/" z& A3 C: _. G$ J
    lv_display_flush_ready(disp_drv);
: C( p7 n; c- c( ^* C2 u}
; n9 x. T$ N. b2 P9 A* v" r5 F
6 }8 d: F: d( P. g

+ c2 M3 F  B4 P$ B9 T1 Q9 p$ Q" O$ Z在indev_disp文件中添加触摸的支持:, y* R- M2 Q; u3 G* @; d% Q9 q
12.JPG
) N, r# y: G) |! @% d4 G/ Y3 T/ n" t" |
static bool touchpad_is_pressed(void)
; i. j' |) k$ |7 ?( s8 s+ j0 m{
3 D# [8 A0 n  n5 ?                tp_dev.scan(0);
' `5 U- r, o% n* S& e                if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480)- ]: N( A) Z& q3 H4 d
                {
0 W8 s% \+ V+ _/ ~' R) s6 o5 X                        //printf("%d %d.\n" , tp_dev.x[0] , tp_dev.y[0]);) G# G& U2 I5 L$ b  X' q
                        return true;5 c" _8 d4 [/ M
                }
4 l# t. R/ Z: p, Z0 _6 m  V- U9 }/ b' [    return false;
6 X' [5 J+ A! t+ Q}- t" ]8 `3 T. a) R" ~5 q. P

) z! o9 {" k7 U- f# ?/*Get the x and y coordinates if the touchpad is pressed*/
5 x5 Y$ @  {- Y# a6 }6 o7 nstatic void touchpad_get_xy(int32_t * x, int32_t * y)$ N, c9 F! q0 O& s" |- I0 R! C
{
' l1 D' J8 l4 i( l    /*Your code comes here*/% k. p( n! {* A! S
& h6 N) R5 z" R$ Q" d
    (*x) = tp_dev.x[0];
; Y* i+ I- H# O! f    (*y) = tp_dev.y[0];
% a3 W1 ]( G1 L) V}, f5 N0 O/ c, @8 l
# f; k( [3 u& W2 y- N
搞定,然后看看刷屏效果:
! f2 h2 R  `7 F  H8 ^, S( @6 S, ~; Y7 z) Z
可以看出来,使用FMC并口来刷屏,效果还是很丝滑顺畅的,可以满足图形化界面显示要求。  K& s5 M4 o' m/ b5 p( j! _8 K
" G/ ^1 R9 H' o' s
3 S) }9 D0 h7 U0 V
然后是一些额外的内容,对DMA MEM2MEM机制的尝试,我们知道FMC刷屏其实也是对RAM(GRAM显存)进行操作,因此理论上可以用DMA MEM2MEM机制来实现对刷屏的加速(并非DMA2D,DMA2D是针对LTDC接口的屏幕),参考野火H743挑战者例程:
6 p9 B3 R. f  D1 r" k 13.JPG 14.JPG 15.JPG
8 ]  {) I8 \) K- d4 h野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。
' r, n% q' [, M2 X6 X- @' J  O' Q; V9 A2 @$ P0 _1 T

8 }: q0 |$ }  W& C. n; E使用这个例程移植到我自己的LVGL例程中,DMA MEM2MEM也不能正常工作,原因未知,还在探索中。
- Y  t1 W% l+ U; h3 U; y
$ F1 y" J6 h4 J- ~( n# C# A% Y
5 n) w  B* s) m
收藏 评论0 发布时间:2026-7-15 20:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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