最新的评测中有一个需求,需要用一块性价比高,RAM够大,支持快速刷屏的单片机开发板做图形显示,因此我这边选用手头现成的惠勤致远STM32H743VI开发板,并搭载一个并口的ST7796彩屏:
, g4 T: ~! f8 ]# s4 n# x' t! T3 N STM32H743VI使用FMC16位8080并口给ST7796彩屏发送数据和指令,并使用FMC自带的时钟线提供时钟信号,效率相比SPI_DMA是快很多的,整套设备的成本是120出头。; Z) ~- }0 N6 B1 ~/ F 要使用开发板移植LVGL,需要用官方例程里面的触摸屏实验例程:
) T9 p. s/ s* [3 @% L( q& R 其实就是要调通LCD刷入缓存和触摸坐标读取的功能:0 M3 m* O; G( w5 n- Q 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; width = ex - sx + 1;$ |+ R" s! i+ l2 Y height = ey - sy + 1; for (i = 0; i < height; i++)" A- y6 [2 y! |7 @# v3 t' ]3 I# c { 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++) {. 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 } } 3 E) z c9 w7 B4 T/ b , Z3 i. q2 L+ B+ C& R ( 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) /* 有按键按下 */ { if (mode) /* 读取物理坐标, 无需转换 */ { tp_read_xy2(&tp_dev.x[0], &tp_dev.y[0]);1 F( I, y/ Q" B+ A2 J: P" X } 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 { /* 将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 /* 将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 } if ((tp_dev.sta & TP_PRES_DOWN) == 0) /* 之前没有被按下 */ {, x( j( Z& d# B6 ^3 @: x( W- v1 `3 F4 \ 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];9 |( {9 X$ L4 @5 { G& B% E }4 C0 E' ]" w q- |& n) J! k# O }, R* o$ n1 ~# ^- W1 g else { if (tp_dev.sta & TP_PRES_DOWN) /* 之前是被按下的 */ { tp_dev.sta &= ~TP_PRES_DOWN; /* 标记按键松开 */ } else /* 之前就没有被按下 */, X4 d4 f9 o% V) U {- o5 W( d4 z2 L$ v' R5 R/ D 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;, 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; /* 返回当前的触屏状态 */ } 然后是从Github官网下载LVGL9.5:
, 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
+ U1 m/ z% e" n$ @+ @ , H+ P, ]" E( ^ h9 m l( g0 Y 然后在port_disp文件中添加局部刷新机制,经常移植LVGL的对此应该会很熟练了:
extern void FMCTFTLCD_ST7796_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color); % 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 { int32_t x;+ t. A5 r3 j5 j P4 m2 ` int32_t y; 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++) // {1 r- b& ]; _' o: t" \ // for(x = area->x1; x <= area->x2; x++) // { // px_map++; V0 i1 n# q' l6 ]4 o // }4 i) S1 p0 h& P, I& E // } } /*IMPORTANT!!! *Inform the graphics library that you are ready with the flushing*/ A# ^) R* D l8 B: L+ o lv_display_flush_ready(disp_drv); } 在indev_disp文件中添加触摸的支持:
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); if (tp_dev.sta && tp_dev.x[0] < 320 && tp_dev.y[0] < 480) { //printf("%d %d.\n" , tp_dev.x[0] , tp_dev.y[0]);+ y2 |) S3 T- b8 p' f& ~ return true; }; Q& y, z& W- M$ w7 W return false;- A0 s& @4 }( L1 r: A/ \+ c: @0 c } /*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) {+ m& M% W" x; u /*Your code comes here*/ (*x) = tp_dev.x[0];+ s9 y6 |/ e( f (*y) = tp_dev.y[0]; } 搞定,然后看看刷屏效果:" j) a7 \. @1 a. ^( b 可以看出来,使用FMC并口来刷屏,效果还是很丝滑顺畅的,可以满足图形化界面显示要求。 ( 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( ~
野火H743挑战者例程DMA MEM2MEM例程里面,对aDST_Buffer是限定了0x30000000即SRAM1区域的地址进行分配,但实际上,使用%p打印出来,地址并不在这个范围里,还是在0x2000000的DTCM和0x24000000的用户RAM区域中。/ p% g& T$ {0 m9 j 使用这个例程移植到我自己的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 |
STM32C542RC开发板PWM呼吸灯及多功能按键实验
NUCLEO-H5E5ZJ 移植 LVGL
NUCLEO-H5E5ZJ 移植 ST7735 SPI LCD 驱动
NUCLEO-H5E5ZJ 以太网(Ethernet)移植记录
【STM32H5 评测】1、移植记录(LED / Shell)
架构革新篇:单芯片 GUI 方案原理与核心优化技术
STM32C542RC开发板实现长短按键识别功能
STM32C542RC开发板PWM呼吸灯实验
STM32C542RC开发板的串口不定长数据接收实验
《STM32CubeMX2 实战课程》学习笔记——STM32C562RE开发测试
微信公众号
手机版