最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:
4 ^4 m% Z+ F6 y7 _ STM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。$ I3 d K: E' \( w, ? 要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:! {5 c t( `, b" X0 J5 J
: D& u- m& e* G 其实就是要调通LCD刷入缓存和触摸坐标读取的功能:2 ?" t/ D+ S$ V ?. o void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color) { uint16_t height, width;* [. x' U6 h2 U$ E, u6 ? uint16_t i, j; / @8 Y$ G9 {( B width = ex - sx + 1;' g! q- Q, J4 @; b1 u$ Q/ C height = ey - sy + 1; % s1 O+ g; Z& d& @ for (i = 0; i < height; i++) { lcd_set_cursor(sx, sy + i); lcd_write_ram_prepare(); 1 h# H0 @6 N: i- ~6 |$ o% K for (j = 0; j < width; j++)' P# N4 f4 s6 b; a! a" o/ g { LCD->LCD_RAM = color[i * width + j];: p {0 L0 S+ F$ I W1 S1 x }, X+ a. S, ], _9 f" s2 g }9 w$ R, w9 ~+ \& h" C( O L p } n$ Z8 Q# |* @2 J8 @8 i2 j6 q " h1 I+ Y- R. D* l3 b+ j uint8_t tp_scan(uint8_t mode) {* k4 G0 t/ s+ g' m2 C if (T_PEN == 0) /* 有按键按下 */ {2 ~) u% E) Q2 k" s if (mode) /* 读取物理坐标, 无需转换 */& l$ \& n( {# B* Z0 o {0 ?$ s" `, Z$ Z0 Z! } tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]); } else if (tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0])) /* 读取屏幕坐标, 需要转换 */% y9 H5 F8 l1 d9 V { /* 将X轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的X坐标值) */" G1 C) C- n, _ tp_dev.x[0] = (signed short)(tp_dev.x[0] - tp_dev.xc) / tp_dev.xfac + lcddev.width / 2;: D% B$ w% ]: B; d & O, \7 v" C- [! a, A, q7 ]7 ^ /* 将Y轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的Y坐标值) */ tp_dev.y[0] = (signed short)(tp_dev.y[0] - tp_dev.yc) / tp_dev.yfac + lcddev.height / 2; } - N: e6 A9 D: b( j* v if ((tp_dev.sta & TP_PRES_DOWN) == 0) /* 之前没有被按下 */ { tp_dev.sta = TP_PRES_DOWN | TP_CATH_PRES; /* 按键按下 */ tp_dev.x[CT_MAX_TOUCH - 1] = tp_dev.x[0]; /* 记录第一次按下时的坐标 */ tp_dev.y[CT_MAX_TOUCH - 1] = tp_dev.y[0]; }& |; ?( h- E9 }! V/ K# c { } else {& P& L* S+ a \+ y5 R if (tp_dev.sta & TP_PRES_DOWN) /* 之前是被按下的 */% e6 B- O5 V5 M { tp_dev.sta &= ~TP_PRES_DOWN; /* 标记按键松开 */, h/ v6 c8 P) W; K. q6 B0 L }- C5 X+ f8 P5 g- F J5 F else /* 之前就没有被按下 */+ r7 a3 p. c/ y1 I7 o. h- G {+ Q0 @6 m, j+ e2 z g tp_dev.x[CT_MAX_TOUCH - 1] = 0; tp_dev.y[CT_MAX_TOUCH - 1] = 0; tp_dev.x[0] = 0xffff; tp_dev.y[0] = 0xffff;- L) P x4 s7 ^- z) ?# j }, S9 M. A" m/ ?1 k- G+ E } 9 {; M. d7 L. {! R8 m return tp_dev.sta & TP_PRES_DOWN; /* 返回当前的触屏状态 */1 `; d s% |- z1 v4 u6 ~# Y( z } - i9 K: h5 b9 v' c2 n 然后是从Github官网下载LVGL9.5:; j9 G/ `( m K0 l; c/ Y
/ ]" T1 j9 M) Q2 M' ]! x5 w: M 可以看出来,LVGL9.5相比起LVGL9.3,更新了很多内容,主目录有疑似Zephyr的更新,libs目录也加入了3dmaths和webp的支持,也就是后续可能支持3D图形算法和网页端应用,很让人期待!将LVGL9.5代码放进单片机工程,并依次添加支持文件即可:
然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:
extern void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);) j% `5 M. ?$ Q0 w8 N! T3 ?$ a 9 w; H7 P8 b( L, ?. e static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)/ r* U+ R; ^9 p# ], R0 W- Y { if(disp_flush_enabled) {3 c1 Y2 h" l8 H$ t0 f int32_t x;7 D" C) W1 W& K& s' P; Q3 q; t int32_t y;; t" m& Q' \0 Z7 B2 \+ f FMCTFTLCD_ST7796_Fill(area->x1 , area->y1 , area->x2 , area->y2 , px_map);" `6 y' ]8 N" N" \0 g# Y // for(y = area->y1; y <= area->y2; y++) // { // for(x = area->x1; x <= area->x2; x++) // { // px_map++;' U6 F! v c$ f! N8 }* b7 v // }8 C9 r H. D! C% O // } } - J6 R+ S" G T /*IMPORTANT!!!/ j9 s( T) S+ j V *Inform the graphics library that you are ready with the flushing*/" [% o4 H4 k/ @% M7 C lv_display_flush_ready(disp_drv);3 { t! B% ]: ~. E2 e& K R9 U } / I0 ]$ g7 j }5 Q' `# @& l$ d 在indev_disp文件中添加触摸的支持:- @3 e/ K. x; Y3 k
static bool touchpad_is_pressed(void) { tp_dev.scan(0);) P0 P! n# r! W! ^$ L# R" f if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480)7 {7 p# l. k3 P { //printf("%d %d.\n" , tp_dev.x[0] , tp_dev.y[0]);& I" k+ V. h' x/ W2 Q return true; }$ ~7 u* }) p; ^8 U" [( _3 [; I4 m return false;7 f- @' J8 J8 c- k+ q/ w }! s* ^3 F. ?$ h - c+ i6 ~" X4 D$ @ /*Get the x and y coordinates if the touchpad is pressed*/ static void touchpad_get_xy(int32_t * x, int32_t * y) { /*Your code comes here*/ (*x) = tp_dev.x[0]; (*y) = tp_dev.y[0];: f. [/ Q6 m" ^8 b4 X' f5 b }9 |( u* A% p+ i; c* r. D 搞定,然后看看刷屏效果: 可以看出来,使用FMC并口来刷屏,效果还是很丝滑顺畅的,可以满足图形化界面显示要求。0 Q0 G2 M9 W. K( y! f. { 然后是一些额外的内容,对DMA MEM2MEM机制的尝试,我们知道FMC刷屏其实也是对RAM(GRAM显存)进行操作,因此理论上可以用DMA MEM2MEM机制来实现对刷屏的加速(并非DMA2D,DMA2D是针对LTDC接口的屏幕),参考野火H743挑战者例程:
野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。/ ~8 }4 t X( i9 B2 |8 h9 g6 T4 ?$ ? 使用这个例程移植到我自己的LVGL例程中,DMA MEM2MEM也不能正常工作,原因未知,还在探索中。. K V+ I9 M" h1 L9 r* z( q& m |
STM32C542RC开发板PWM呼吸灯及多功能按键实验
NUCLEO-H5E5ZJ 移植 LVGL
NUCLEO-H5E5ZJ 移植 ST7735 SPI LCD 驱动
NUCLEO-H5E5ZJ 以太网(Ethernet)移植记录
【STM32H5 评测】1、移植记录(LED / Shell)
架构革新篇:单芯片 GUI 方案原理与核心优化技术
STM32C542RC开发板实现长短按键识别功能
STM32C542RC开发板PWM呼吸灯实验
STM32C542RC开发板的串口不定长数据接收实验
《STM32CubeMX2 实战课程》学习笔记——STM32C562RE开发测试
微信公众号
手机版