最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:
0 q/ L: P/ p J/ M * Y' m6 {' ]& E STM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。 要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:9 }- v- ~. ^! w) T3 G0 q: G! k
$ r! M O7 L6 d: w6 I% ^ 其实就是要调通LCD刷入缓存和触摸坐标读取的功能: void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color) { uint16_t height, width; uint16_t i, j; ; ~5 J7 k% h; t/ M width = ex - sx + 1;9 d3 y7 u+ w9 i0 x0 P' W$ `# ~ height = ey - sy + 1; ( b4 _5 l4 l' e' p8 U for (i = 0; i < height; i++) {, R. e8 a+ }2 E: F9 @5 | lcd_set_cursor(sx, sy + i);. p, ^ c; G3 z3 N0 J6 u! o lcd_write_ram_prepare();2 S/ N4 W$ }" M$ x* V , @, I0 s+ W! a/ }: @ for (j = 0; j < width; j++) { LCD->LCD_RAM = color[i * width + j];0 [& g& q' y# L. b! }7 M* {- s } } }& b) ~/ b4 Z: Y8 E6 x$ ` / }7 I: t+ R; J% b# L3 J; ] ' H: {9 n0 J' T 8 U. _7 D; |: s" V$ K 8 j. }3 J# n( N$ M8 N) z& t uint8_t tp_scan(uint8_t mode) { if (T_PEN == 0) /* 有按键按下 */ { if (mode) /* 读取物理坐标, 无需转换 */8 k% p5 L1 y) P4 R# b { ` f' ?: h: m- C4 l tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]);( g6 x; L3 y) k2 L" S( t } o& r& F6 H' ` else if (tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0])) /* 读取屏幕坐标, 需要转换 */$ R6 d) c4 L! | y+ ~" ?4 W1 p* R {# }. r* E; Q' g- U$ ~5 ? /* 将X轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的X坐标值) */ tp_dev.x[0] = (signed short)(tp_dev.x[0] - tp_dev.xc) / tp_dev.xfac + lcddev.width / 2;$ H2 F* K; ~: v b! Y /* 将Y轴 物理坐标转换成逻辑坐标(即对应LCD屏幕上面的Y坐标值) */8 ?( s9 R( G2 s/ |9 K( [ tp_dev.y[0] = (signed short)(tp_dev.y[0] - tp_dev.yc) / tp_dev.yfac + lcddev.height / 2;" j' v& i B2 E1 O. `9 N }, A/ \& e! q" G& M 0 I5 ~: Z5 i; j5 [ 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]; /* 记录第一次按下时的坐标 */6 p% s% a S' Z1 i( p, \ tp_dev.y[CT_MAX_TOUCH - 1] = tp_dev.y[0]; } }* d: N0 a% q% E2 i* N! l: d5 n4 { else {5 a8 W6 @- Q2 [! X$ ` if (tp_dev.sta & TP_PRES_DOWN) /* 之前是被按下的 */ { tp_dev.sta &= ~TP_PRES_DOWN; /* 标记按键松开 */ w M! D S. g& [2 t7 s } else /* 之前就没有被按下 */) R8 G* [/ q- a& p9 u! a. R! D { tp_dev.x[CT_MAX_TOUCH - 1] = 0;1 i# G* k9 {- T% p1 V/ b' ~ tp_dev.y[CT_MAX_TOUCH - 1] = 0;/ A' b# N5 i" ]& y tp_dev.x[0] = 0xffff;6 H, A0 d9 U) w6 R; L+ O1 f tp_dev.y[0] = 0xffff; } }% Z; I4 H0 l6 `7 N6 Z- }, |! W return tp_dev.sta & TP_PRES_DOWN; /* 返回当前的触屏状态 */ }3 T8 | @ {. O8 ~# I- V 然后是从Github官网下载LVGL9.5:% y. w8 o: f$ |* @' s4 `" R
3 K2 B$ j O, X$ w5 }9 U+ ^ 可以看出来,LVGL9.5相比起LVGL9.3,更新了很多内容,主目录有疑似Zephyr的更新,libs目录也加入了3dmaths和webp的支持,也就是后续可能支持3D图形算法和网页端应用,很让人期待!将LVGL9.5代码放进单片机工程,并依次添加支持文件即可:3 X; d6 p H* x5 _" D/ \; H- e
! M5 Z5 f% `' g5 N o- V 然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:
extern void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color); static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map). Y8 k! r- L0 b { if(disp_flush_enabled) { int32_t x; int32_t y;' A% T: p( d- O FMCTFTLCD_ST7796_Fill(area->x1 , area->y1 , area->x2 , area->y2 , px_map); // for(y = area->y1; y <= area->y2; y++) & l+ O7 \7 [, u2 e; v N9 a // {# O: {+ f" s* \7 v, Q" F0 e // for(x = area->x1; x <= area->x2; x++) 9 M/ u! q7 ?; J9 G& T$ u // {0 x" G; `$ M4 P+ ` X% S" e0 k9 } // px_map++; // }1 ?/ p8 B8 R v2 X2 K // } } /*IMPORTANT!!!/ B3 @) u8 R6 p; Y' N *Inform the graphics library that you are ready with the flushing*/ lv_display_flush_ready(disp_drv); }2 y$ o; I4 x6 {6 a 在indev_disp文件中添加触摸的支持:
. j- ^3 ?2 Q( q; \: o1 z& ? static bool touchpad_is_pressed(void) {8 v7 G' A w7 j9 z* e# d7 r tp_dev.scan(0); if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480)8 X1 {0 H0 s. m- Z) \, D2 H {% G" s7 k s: G //printf("%d %d.\n" , tp_dev.x[0] , tp_dev.y[0]); return true;7 q [: N! G4 s( v, } } return false;. t% Y |. N1 n1 _/ M3 q }- O2 T, ~0 Y/ O) a2 k , B. _' j' |$ E' D /*Get the x and y coordinates if the touchpad is pressed*/ static void touchpad_get_xy(int32_t * x, int32_t * y)/ U5 P( h9 w9 q# D {" y! K- {) q" R, ]" s/ d /*Your code comes here*/; k* g$ Q3 L; M+ |- x/ M % t' V i+ S/ X" M7 ]7 {: y (*x) = tp_dev.x[0]; (*y) = tp_dev.y[0];- S L4 l2 E% I1 q9 Q! Y } 搞定,然后看看刷屏效果:8 q+ Q2 B9 {0 f' S 可以看出来,使用FMC并口来刷屏,效果还是很丝滑顺畅的,可以满足图形化界面显示要求。 0 g6 A: w! r% v6 V 然后是一些额外的内容,对DMA MEM2MEM机制的尝试,我们知道FMC刷屏其实也是对RAM(GRAM显存)进行操作,因此理论上可以用DMA MEM2MEM机制来实现对刷屏的加速(并非DMA2D,DMA2D是针对LTDC接口的屏幕),参考野火H743挑战者例程:+ V @8 A4 _. X5 s, U
野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。 $ a1 o- V; t6 ~" B! C b 使用这个例程移植到我自己的LVGL例程中,DMA MEM2MEM也不能正常工作,原因未知,还在探索中。 b, K4 o$ ]' J; ?/ n 0 }0 x( f7 z4 K# j B! i |
【STM32H735G-DK测评】lvgl移植
【STM32H735G-DK 测评】STM32H735G-DK External Loder 编译和测试
[GPIO] 使用新型抽象开始C++嵌入式编程,从GPIO开始
M24LR-discovery测试小结
STM32L562DK探索板——串口通讯的再测试
STM32L562DK探索板——串口通讯的测试
STM32L562DK探索板——运动传感器测试
STM32L562DK探索板——继续深入了解Audio Play的工作流程
STM32L562DK探索板——触摸菜单实验之触摸测试
STM32L562DK探索板——触摸菜单实验之LED闪烁
微信公众号
手机版