最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:; N" j( ~$ q6 v5 ^, N2 [
4 y- m2 C: ?! \. I6 F O STM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。 要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:" z3 h- q, Z) b E! j) e
其实就是要调通LCD刷入缓存和触摸坐标读取的功能:# V9 y7 C' W5 T 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; ) m2 \. f E" E' ^+ d width = ex - sx + 1;! ~+ v0 d9 j5 f, q* G height = ey - sy + 1; for (i = 0; i < height; i++)# }+ n7 H f* H% X+ v# L { 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++) { LCD->LCD_RAM = color[i * width + j]; }% j' U z: o8 o1 r* f! b } }+ k) t. l; b2 k; C1 g% H, U , B1 H! C6 r* s1 y2 v" k / F4 q! N8 n9 K& w) @1 { / N- a" G6 u. }0 s# h! P1 F uint8_t tp_scan(uint8_t mode) { if (T_PEN == 0) /* 有按键按下 */ {2 \3 P8 Y$ X$ c1 P if (mode) /* 读取物理坐标, 无需转换 */ {- Q# ?: b6 w# K0 W tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]);8 w( f2 B l5 @$ J( Z \/ u } else if (tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0])) /* 读取屏幕坐标, 需要转换 */) ^+ c, v# a% p- E c { /* 将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 /* 将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; }$ 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; /* 按键按下 */ 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]; } }5 m9 ~2 C- \5 D* m2 }# P, p else9 M8 f. Q n- H N { 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: | } else /* 之前就没有被按下 */) S, F4 N6 P. O. |( ]2 S. v- Q! C, g { 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 } return tp_dev.sta & TP_PRES_DOWN; /* 返回当前的触屏状态 */+ a# {1 f! ^! @, z* g }% u) k/ x( m) X# R" @0 o8 s+ \ 然后是从Github官网下载LVGL9.5:
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; [
2 p! P, Y; q+ ^4 q3 r0 M) i 然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:
extern 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 static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map) { j' L0 \7 v$ C2 h. \& ~7 Y if(disp_flush_enabled) . u2 u* _) d' M& T, ~# ` { 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% ? // { // for(x = area->x1; x <= area->x2; x++) // { // px_map++; // } // } }4 D+ T3 c; F3 C. L, z /*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); } 6 }8 d: F: d( P. g 在indev_disp文件中添加触摸的支持:, y* R- M2 Q; u3 G* @; d% Q9 q
4 G/ Y3 T/ n" t" | static bool touchpad_is_pressed(void) { tp_dev.scan(0); if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480)- ]: N( A) Z& q3 H4 d { //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 } return false; }- t" ]8 `3 T. a) R" ~5 q. P /*Get the x and y coordinates if the touchpad is pressed*/ static void touchpad_get_xy(int32_t * x, int32_t * y)$ N, c9 F! q0 O& s" |- I0 R! C { /*Your code comes here*/% k. p( n! {* A! S & h6 N) R5 z" R$ Q" d (*x) = tp_dev.x[0]; (*y) = tp_dev.y[0]; }, f5 N0 O/ c, @8 l # f; k( [3 u& W2 y- N 搞定,然后看看刷屏效果: 可以看出来,使用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挑战者例程:
野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。 O' Q; V9 A2 @$ P0 _1 T 使用这个例程移植到我自己的LVGL例程中,DMA MEM2MEM也不能正常工作,原因未知,还在探索中。 |
STM32C542RC开发板的按键控制LED闪烁实验
【 逢7发帖赢大礼】1、利用CubeMX生成正点原子H7R7开发板的STM32CubeIDE工程
《STM32CubeMX2 实战课程》学习笔记--课程1:STM32CubeMX2安装
【STM32H735G-DK测评】ADC3+TIMER1+DMA 采样模拟信号
【STM32H735DK测评】Ethernet+lwip DHCP获取IP地址
STM32H743基于CubeMx5.0配置手册
STM32L562DK探索板——串口通讯测试成功
【STM32H735G-DK测评】lvgl移植
【STM32H735G-DK 测评】STM32H735G-DK External Loder 编译和测试
[GPIO] 使用新型抽象开始C++嵌入式编程,从GPIO开始
微信公众号
手机版