RVB2601应用开发实战系列三: GUI图形显示

作者阿里云代理 文章分类 分类:linux图文教程 阅读次数 已被围观 1762

编辑语:

技术解码栏目:是面向开发者详细解读芯片开放社区(OCC)上关于处理器、芯片、基础软件平台、集成开发环境及应用开发平台的相关技术,方便开发者学习及快速上手,提升开发效率。

. 前言

RVB2601基于平头哥RISC-V生态芯片的开发套件,开发者基于RVB2601可进行端云一体的物联网应用开发及音频方案开发。上周向大家推荐了RVB2601应用开发实战系列二: 跑马灯实例教程,基于RVB2601GUI程序是利用Lvgl开源组件实现在TFT LCD屏幕上做字符和图形显示。开发者可以利用Lvgl组件在TFT LCD屏幕上实现Label空间显示功能。

建议在看本文之前,先详细看下新手必看 | RVB2601开发板快速上手指南。本例程名为ch2601_gui_demo,可以通过集成开发环境剑池CDK下载获取相应资源。

. 硬件配置

2.1 显示屏

RVB2601开发板采用的是TFT LCD显示屏, 位于开发板正面。

2.2 屏幕物理接口

CH2601开发板采用单彩色图形显示面板,屏幕分辨率128x64 pixel,屏幕背景可选,该程序中采用的是一块黄色背景的屏幕。屏幕控制器采用SSD1309,通过4 wire SPI接口与主芯片连接, 原理图如下所示, 对应的pin引脚分别为PA27PA28PA29PA30。原理图如下:

软件通过对SPI进行读写操作来实现,对TFT LCD屏上的像素进行点缀操作,从而实现整个屏的点亮操作。

. GUI软件开发

3.1 LVGL介绍

LVGL全称Light and Versatile Graphics Library,是一个自由的,开源的GUI库,界面精美,资源消耗小,可移植度高,响应式布局等特点,全库采用纯 c 语言开发。

主要特性如下:

· 具有非常丰富的内置控件,buttons, charts, lists, sliders, images

· 高级图形效果:动画,反锯齿,透明度,平滑滚动

· 支持多种输入设备,touchpad, mouse, keyboard, encoder

· 支持多语言的 UTF-8 编码

· 支持多个和多种显示设备,例如同步显示在多个彩色屏或单色屏上

· 完全自定制的图形元素

· 硬件独立于任何微控制器或显示器

· 可以缩小到最小内存 (64 kB Flash, 16 kB RAM)

· 支持操作系统、外部储存和 GPU(非必须)

· 仅仅单个帧缓冲设备就可以呈现高级视觉特效

· 使用 C 编写以获得最大兼容性(兼容 C++)

· 支持 PC 模拟器

· 为加速 GUI 设计,提供教程,案例和主题,支持响应式布局

· 提供了在线和离线文档

· 基于自由和开源的 MIT 协议

· 支持MicroPython

3.2 例程下载

打开CDK,点击HOME图标,查找ch2601_gui_demo后,打开工程可以看下一下目录文件:

3.3 LVGL移植接口

Lvgl移植代码位于app/src/lvgl_porting文件夹内,其包含oled.coled.h

· 以下功能接口位于app/src/lvgl_porting/oled.c, 实现SPI管脚的初始化,主要针对CS, DATA, CLOCK, DATAIN管脚,同时实现了对不同管教的读写操作。

1. static void oled_gpio_init()2. {3. //4. csi_gpio_pin_init(&pin_clk, PA28);5. csi_gpio_pin_dir(&pin_clk, GPIO_DIRECTION_OUTPUT);6. csi_gpio_pin_init(&pin_mosi, PA29);7. csi_gpio_pin_dir(&pin_mosi, GPIO_DIRECTION_OUTPUT);8. csi_gpio_pin_init(&pin_cs, PA27);9. csi_gpio_pin_dir(&pin_cs, GPIO_DIRECTION_OUTPUT);10. csi_gpio_pin_init(&pin_miso, PA30); //dc11. csi_gpio_pin_dir(&pin_miso, GPIO_DIRECTION_OUTPUT);12. }13. 14. static void lcd_cs(uint8_t d)15. {16. if (d == 1) {17. csi_gpio_pin_write(&pin_cs, GPIO_PIN_HIGH);18. } else {19. csi_gpio_pin_write(&pin_cs, GPIO_PIN_LOW);20. }21. }22. 23. static void lcd_dc(uint8_t d)24. {25. if (d == 1) {26. csi_gpio_pin_write(&pin_miso, GPIO_PIN_HIGH);27. } else {28. csi_gpio_pin_write(&pin_miso, GPIO_PIN_LOW);29. }30. }31. 32. static void lcd_sclk(uint8_t d)33. {34. if (d == 1) {35. csi_gpio_pin_write(&pin_clk, GPIO_PIN_HIGH);36. } else {37. csi_gpio_pin_write(&pin_clk, GPIO_PIN_LOW);38. }39. }40. 41. static void lcd_sdin(uint8_t d)42. {43. if (d == 1) {44. csi_gpio_pin_write(&pin_mosi, GPIO_PIN_HIGH);45. } else {46. csi_gpio_pin_write(&pin_mosi, GPIO_PIN_LOW);47. }48. }c

· 以下功能函数位于app/src/lvgl_porting/oled.c,通过SPI实现对屏幕的命令和数据写操作。

1. void Write_Command(unsigned char Data)2. {3. unsigned char i;4. 5. lcd_cs(0);6. lcd_dc(0);7. for (i = 0; i < 8; i++) {8. lcd_sclk(0);9. lcd_sdin((Data & 0x80) >> 7);10. Data = Data << 1;11. lcd_sclk(1);12. }13. lcd_dc(1);14. lcd_cs(1);15. }16. 17. void Write_Data(unsigned char Data)18. {19. unsigned char i;20. 21. lcd_cs(0);22. lcd_dc(1);23. for (i = 0; i < 8; i++) {24. lcd_sclk(0);25. lcd_sdin((Data & 0x80) >> 7);26. Data = Data << 1;27. lcd_sclk(1);28. }29. lcd_dc(1);30. lcd_cs(1);31. }c

· 以下功能函数位于app/src/lvgl_porting/oled.c,实现对屏幕的基本命令操作,例如设置屏幕行列地址,屏幕的亮度控制等。

1. void Set_Start_Column(unsigned char d)2. {3. Write_Command(0x00 + d % 16); // Set Lower Column Start Address for Page Addressing Mode4. //   Default => 0x005. Write_Command(0x10 + d / 16); // Set Higher Column Start Address for Page Addressing Mode6. //   Default => 0x107. }8. 9. void Set_Addressing_Mode(unsigned char d)10. {11. Write_Command(0x20); // Set Memory Addressing Mode12. Write_Command(d);    //   Default => 0x0213. //     0x00 => Horizontal Addressing Mode14. //     0x01 => Vertical Addressing Mode15. //     0x02 => Page Addressing Mode16. }17. 18. void Set_Column_Address(unsigned char a, unsigned char b)19. {20. Write_Command(0x21); // Set Column Address21. Write_Command(a);    //   Default => 0x00 (Column Start Address)22. Write_Command(b);    //   Default => 0x7F (Column End Address)23. }24. 25. void Set_Page_Address(unsigned char a, unsigned char b)26. {27. Write_Command(0x22); // Set Page Address28. Write_Command(a);    //   Default => 0x00 (Page Start Address)29. Write_Command(b);    //   Default => 0x07 (Page End Address)30. }31. 32. void Set_Start_Line(unsigned char d)33. {34. Write_Command(0x40 | d); // Set Display Start Line35. //   Default => 0x40 (0x00)36. }37. 38. void Set_Contrast_Control(unsigned char d)39. {40. Write_Command(0x81); // Set Contrast Control for Bank 041. Write_Command(d);    //   Default => 0x7F42. }43. 44. void Set_Segment_Remap(unsigned char d)45. {46. Write_Command(d); // Set Segment Re-Map47. //   Default => 0xA048. //     0xA0 => Column Address 0 Mapped to SEG049. //     0xA1 => Column Address 0 Mapped to SEG12750. }51. 52. void Set_Entire_Display(unsigned char d)53. {54. Write_Command(d); // Set Entire Display On / Off55. //   Default => 0xA456. //     0xA4 => Normal Display57. //     0xA5 => Entire Display On58. }59. 60. void Set_Inverse_Display(unsigned char d)61. {62. Write_Command(d); // Set Inverse Display On/Off63. //   Default => 0xA664. //     0xA6 => Normal Display65. //     0xA7 => Inverse Display On66. }67. 68. void Set_Multiplex_Ratio(unsigned char d)69. {70. Write_Command(0xA8); // Set Multiplex Ratio71. Write_Command(d);    //   Default => 0x3F (1/64 Duty)72. }73. 74. void Set_Display_On_Off(unsigned char d)75. {76. Write_Command(d); // Set Display On/Off77. //   Default => 0xAE78. //     0xAE => Display Off79. //     0xAF => Display On80. }81. 82. void Set_Start_Page(unsigned char d)83. {84. Write_Command(0xB0 | d); // Set Page Start Address for Page Addressing Mode85. //   Default => 0xB0 (0x00)86. }87. 88. void Set_Common_Remap(unsigned char d)89. {90. Write_Command(d); // Set COM Output Scan Direction91. //   Default => 0xC092. //     0xC0 => Scan from COM0 to 6393. //     0xC8 => Scan from COM63 to 094. }95. 96. void Set_Display_Offset(unsigned char d)97. {98. Write_Command(0xD3); // Set Display Offset99. Write_Command(d);    //   Default => 0x00100. }101. 102. void Set_Display_Clock(unsigned char d)103. {104. Write_Command(0xD5); // Set Display Clock Divide Ratio / Oscillator Frequency105. Write_Command(d);    //   Default => 0x70106. //     D[3:0] => Display Clock Divider107. //     D[7:4] => Oscillator Frequency108. }109. 110. void Set_Low_Power(unsigned char d)111. {112. Write_Command(0xD8); // Set Low Power Display Mode113. Write_Command(d);    //   Default => 0x04 (Normal Power Mode)114. }115. 116. void Set_Precharge_Period(unsigned char d)117. {118. Write_Command(0xD9); // Set Pre-Charge Period119. Write_Command(d); //   Default => 0x22 (2 Display Clocks [Phase 2] / 2 Display Clocks [Phase 1])120. //     D[3:0] => Phase 1 Period in 1~15 Display Clocks121. //     D[7:4] => Phase 2 Period in 1~15 Display Clocks122. }123. 124. void Set_Common_Config(unsigned char d)125. {126. Write_Command(0xDA); // Set COM Pins Hardware Configuration127. Write_Command(d);    //   Default => 0x12128. //     Alternative COM Pin Configuration129. //     Disable COM Left/Right Re-Map130. }131. 132. void Set_VCOMH(unsigned char d)133. {134. Write_Command(0xDB); // Set VCOMH Deselect Level135. Write_Command(d);    //   Default => 0x34 (0.78*VCC)136. }137. 138. void Set_NOP()139. {140. Write_Command(0xE3); // Command for No Operation141. }142. 143. void Set_Command_Lock(unsigned char d)144. {145. Write_Command(0xFD); // Set Command Lock146. Write_Command(d);    //   Default => 0x12147. //     0x12 => Driver IC interface is unlocked from entering command.148. //     0x16 => All Commands are locked except 0xFD.149. }c

· 该功能函数位于app/src/lvgl_porting/oled.c,实现对屏幕的初始化。

1. static void oled_initialize()2. {3. Set_Command_Lock(0x12);           // Unlock Driver IC (0x12/0x16)4. Set_Display_On_Off(0xAE);         // Display Off (0xAE/0xAF)5. Set_Display_Clock(0xA0);          // Set Clock as 116 Frames/Sec6. Set_Multiplex_Ratio(0x3F);        // 1/64 Duty (0x0F~0x3F)7. Set_Display_Offset(0x00);         // Shift Mapping RAM Counter (0x00~0x3F)8. Set_Start_Line(0x00);             // Set Mapping RAM Display Start Line (0x00~0x3F)9. Set_Low_Power(0x04);              // Set Normal Power Mode (0x04/0x05)10. Set_Addressing_Mode(0x02);        // Set Page Addressing Mode (0x00/0x01/0x02)11. Set_Segment_Remap(0xA1);          // Set SEG/Column Mapping (0xA0/0xA1)12. Set_Common_Remap(0xC8);           // Set COM/Row Scan Direction (0xC0/0xC8)13. Set_Common_Config(0x12);          // Set Alternative Configuration (0x02/0x12)14. Set_Contrast_Control(Brightness); // Set SEG Output Current15. Set_Precharge_Period(0x82);       // Set Pre-Charge as 8 Clocks & Discharge as 2 Clocks16. Set_VCOMH(0x34);                  // Set VCOM Deselect Level17. Set_Entire_Display(0xA4);         // Disable Entire Display On (0xA4/0xA5)18. Set_Inverse_Display(0xA6);        // Disable Inverse Display On (0xA6/0xA7)19. 20. Fill_RAM(0x00); // Clear Screen21. 22. Set_Display_On_Off(0xAF); // Display On (0xAE/0xAF)23. }c

· 该功能函数位于app/src/main.c,实现在屏幕固定处画一个label, 显示一串字符串。

1. static void gui_label_create(void)2. {3. lv_obj_t *p = lv_label_create(lv_scr_act(), NULL);4. lv_label_set_long_mode(p, LV_LABEL_LONG_BREAK);5. lv_label_set_align(p, LV_LABEL_ALIGN_CENTER);6. lv_obj_set_pos(p, 0, 4);7. lv_obj_set_size(p, 128, 60);8. lv_label_set_text(p, "THEAD RISC-V\nGUI\nDEMO");9. }c

3.4. 编译运行

编译通过后,点击下载成功,复位运行。可看屏上显示"THEAD RISC-V\nGUI\nDEMO" 字符串。

. 总结

本例程介绍了如何通过SPI接口来实现对TFT LCD屏幕的图形显示。后续还有更多的开发例程,敬请期待!

版权声明:本文内容转发自阿里云社区,由阿里云实名注册用户自发贡献版权归原作者所有本站不拥有其著作权,亦不承担相应法律责任。如果您发现本中有涉嫌抄袭的内容,请联系站内客服,本将立刻删除涉嫌侵权内容。

本公司销售:阿里云新/老客户,只要购买阿里云,即可享受折上折优惠!>

我有话说: