查看: 1841|回复: 0
收起左侧

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

[复制链接]

  离线 

  • TA的每日心情
    拍拍
    2022-6-27 11:09
  • 签到天数: 25 天

    [LV.4]

    发表于 2021-5-4 21:25:49 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 sky 于 2021-5-4 21:25 编辑

    1. 前言

    基于RVB2601的GUI程序是利用Lvgl开源组件实现在OLED屏幕上做字符和图形显示。开发者可以利用Lvgl组件在OLED屏幕上实现Label空间显示功能。

    建议在看本文之前,先详细看下RVB2601资源。本例程名为ch2601_gui_demo,可以通过CDK直接从OCC拉取。


    2. 硬件配置2.1 显示屏

    RVB2601开发板采用的是OLED显示屏, 位于开发板正面。
    CH2601 单片机芯片及应用-RVB2601应用开发实战系列三: GUI图形显示risc-v单片机中文社区(1)

    2.2 屏幕物理接口

    CH2601开发板采用单彩色图形显示面板,屏幕分辨率128x64 pixel,屏幕背景可选,该程序中采用的是一块黄色背景的屏幕。屏幕控制器采用SSD1309,通过4 wire SPI接口与主芯片连接, 原理图如下所示, 对应的pin引脚分别为PA27、PA28、PA29、PA30。 原理图如下:
    CH2601 单片机芯片及应用-RVB2601应用开发实战系列三: GUI图形显示risc-v单片机中文社区(2)
    软件通过对SPI进行读写操作来实现对OLED屏上的像素进行点缀操作,从而实现整个屏的点亮操作。


    3. 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后,打开工程可以看到以下目录:
    CH2601 单片机芯片及应用-RVB2601应用开发实战系列三: GUI图形显示risc-v单片机中文社区(3)
    3.3 LVGL移植接口

    Lvgl移植代码位于app/src/lvgl_porting文件夹内,其包含oled.c和oled.h。
    CH2601 单片机芯片及应用-RVB2601应用开发实战系列三: GUI图形显示risc-v单片机中文社区(4)
    • 以下功能接口位于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); //dc
    11.     csi_gpio_pin_dir(&pin_miso, GPIO_DIRECTION_OUTPUT);
    12. }
    13. static void lcd_cs(uint8_t d)
    14. {
    15.     if (d == 1) {
    16.         csi_gpio_pin_write(&pin_cs, GPIO_PIN_HIGH);
    17.     } else {
    18.         csi_gpio_pin_write(&pin_cs, GPIO_PIN_LOW);
    19.     }
    20. }
    21. static void lcd_dc(uint8_t d)
    22. {
    23.     if (d == 1) {
    24.         csi_gpio_pin_write(&pin_miso, GPIO_PIN_HIGH);
    25.     } else {
    26.         csi_gpio_pin_write(&pin_miso, GPIO_PIN_LOW);
    27.     }
    28. }
    29. static void lcd_sclk(uint8_t d)
    30. {
    31.     if (d == 1) {
    32.         csi_gpio_pin_write(&pin_clk, GPIO_PIN_HIGH);
    33.     } else {
    34.         csi_gpio_pin_write(&pin_clk, GPIO_PIN_LOW);
    35.     }
    36. }
    37. static void lcd_sdin(uint8_t d)
    38. {
    39.     if (d == 1) {
    40.         csi_gpio_pin_write(&pin_mosi, GPIO_PIN_HIGH);
    41.     } else {
    42.         csi_gpio_pin_write(&pin_mosi, GPIO_PIN_LOW);
    43.     }
    44. }
    复制代码

    • 以下功能函数位于app/src/lvgl_porting/oled.c,通过SPI实现对屏幕的命令和数据写操作。
    1. void Write_Command(unsigned char Data)
    2. {
    3.     unsigned char i;
    4.     lcd_cs(0);
    5.     lcd_dc(0);
    6.     for (i = 0; i < 8; i++) {
    7.         lcd_sclk(0);
    8.         lcd_sdin((Data & 0x80) >> 7);
    9.         Data = Data << 1;
    10.         lcd_sclk(1);
    11.     }
    12.     lcd_dc(1);
    13.     lcd_cs(1);
    14. }
    15. void Write_Data(unsigned char Data)
    16. {
    17.     unsigned char i;
    18.     lcd_cs(0);
    19.     lcd_dc(1);
    20.     for (i = 0; i < 8; i++) {
    21.         lcd_sclk(0);
    22.         lcd_sdin((Data & 0x80) >> 7);
    23.         Data = Data << 1;
    24.         lcd_sclk(1);
    25.     }
    26.     lcd_dc(1);
    27.     lcd_cs(1);
    28. }
    复制代码

    • 以下功能函数位于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 Mode
    4.                                   //   Default => 0x00
    5.     Write_Command(0x10 + d / 16); // Set Higher Column Start Address for Page Addressing Mode
    6.                                   //   Default => 0x10
    7. }
    8. void Set_Addressing_Mode(unsigned char d)
    9. {
    10.     Write_Command(0x20); // Set Memory Addressing Mode
    11.     Write_Command(d);    //   Default => 0x02
    12.                          //     0x00 => Horizontal Addressing Mode
    13.                          //     0x01 => Vertical Addressing Mode
    14.                          //     0x02 => Page Addressing Mode
    15. }
    16. void Set_Column_Address(unsigned char a, unsigned char b)
    17. {
    18.     Write_Command(0x21); // Set Column Address
    19.     Write_Command(a);    //   Default => 0x00 (Column Start Address)
    20.     Write_Command(b);    //   Default => 0x7F (Column End Address)
    21. }
    22. void Set_Page_Address(unsigned char a, unsigned char b)
    23. {
    24.     Write_Command(0x22); // Set Page Address
    25.     Write_Command(a);    //   Default => 0x00 (Page Start Address)
    26.     Write_Command(b);    //   Default => 0x07 (Page End Address)
    27. }
    28. void Set_Start_Line(unsigned char d)
    29. {
    30.     Write_Command(0x40 | d); // Set Display Start Line
    31.                              //   Default => 0x40 (0x00)
    32. }
    33. void Set_Contrast_Control(unsigned char d)
    34. {
    35.     Write_Command(0x81); // Set Contrast Control for Bank 0
    36.     Write_Command(d);    //   Default => 0x7F
    37. }
    38. void Set_Segment_Remap(unsigned char d)
    39. {
    40.     Write_Command(d); // Set Segment Re-Map
    41.                       //   Default => 0xA0
    42.                       //     0xA0 => Column Address 0 Mapped to SEG0
    43.                       //     0xA1 => Column Address 0 Mapped to SEG127
    44. }
    45. void Set_Entire_Display(unsigned char d)
    46. {
    47.     Write_Command(d); // Set Entire Display On / Off
    48.                       //   Default => 0xA4
    49.                       //     0xA4 => Normal Display
    50.                       //     0xA5 => Entire Display On
    51. }
    52. void Set_Inverse_Display(unsigned char d)
    53. {
    54.     Write_Command(d); // Set Inverse Display On/Off
    55.                       //   Default => 0xA6
    56.                       //     0xA6 => Normal Display
    57.                       //     0xA7 => Inverse Display On
    58. }
    59. void Set_Multiplex_Ratio(unsigned char d)
    60. {
    61.     Write_Command(0xA8); // Set Multiplex Ratio
    62.     Write_Command(d);    //   Default => 0x3F (1/64 Duty)
    63. }
    64. void Set_Display_On_Off(unsigned char d)
    65. {
    66.     Write_Command(d); // Set Display On/Off
    67.                       //   Default => 0xAE
    68.                       //     0xAE => Display Off
    69.                       //     0xAF => Display On
    70. }
    71. void Set_Start_Page(unsigned char d)
    72. {
    73.     Write_Command(0xB0 | d); // Set Page Start Address for Page Addressing Mode
    74.                              //   Default => 0xB0 (0x00)
    75. }
    76. void Set_Common_Remap(unsigned char d)
    77. {
    78.     Write_Command(d); // Set COM Output Scan Direction
    79.                       //   Default => 0xC0
    80.                       //     0xC0 => Scan from COM0 to 63
    81.                       //     0xC8 => Scan from COM63 to 0
    82. }
    83. void Set_Display_Offset(unsigned char d)
    84. {
    85.     Write_Command(0xD3); // Set Display Offset
    86.     Write_Command(d);    //   Default => 0x00
    87. }
    88. void Set_Display_Clock(unsigned char d)
    89. {
    90.     Write_Command(0xD5); // Set Display Clock Divide Ratio / Oscillator Frequency
    91.     Write_Command(d);    //   Default => 0x70
    92.                          //     D[3:0] => Display Clock Divider
    93.                          //     D[7:4] => Oscillator Frequency
    94. }
    95. void Set_Low_Power(unsigned char d)
    96. {
    97.     Write_Command(0xD8); // Set Low Power Display Mode
    98.     Write_Command(d);    //   Default => 0x04 (Normal Power Mode)
    99. }
    100. void Set_Precharge_Period(unsigned char d)
    101. {
    102.     Write_Command(0xD9); // Set Pre-Charge Period
    103.     Write_Command(d); //   Default => 0x22 (2 Display Clocks [Phase 2] / 2 Display Clocks [Phase 1])
    104.                       //     D[3:0] => Phase 1 Period in 1~15 Display Clocks
    105.                       //     D[7:4] => Phase 2 Period in 1~15 Display Clocks
    106. }
    107. void Set_Common_Config(unsigned char d)
    108. {
    109.     Write_Command(0xDA); // Set COM Pins Hardware Configuration
    110.     Write_Command(d);    //   Default => 0x12
    111.                          //     Alternative COM Pin Configuration
    112.                          //     Disable COM Left/Right Re-Map
    113. }
    114. void Set_NOP()
    115. {
    116.     Write_Command(0xE3); // Command for No Operation
    117. }
    118. void Set_Command_Lock(unsigned char d)
    119. {
    120.     Write_Command(0xFD); // Set Command Lock
    121.     Write_Command(d);    //   Default => 0x12
    122.                          //     0x12 => Driver IC interface is unlocked from entering command.
    123.                          //     0x16 => All Commands are locked except 0xFD.
    124. }
    复制代码

    • 该功能函数位于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/Sec
    6.     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 Current
    15.     Set_Precharge_Period(0x82);       // Set Pre-Charge as 8 Clocks & Discharge as 2 Clocks
    16.     Set_VCOMH(0x34);                  // Set VCOM Deselect Level
    17.     Set_Entire_Display(0xA4);         // Disable Entire Display On (0xA4/0xA5)
    18.     Set_Inverse_Display(0xA6);        // Disable Inverse Display On (0xA6/0xA7)
    19.     Fill_RAM(0x00); // Clear Screen
    20.     Set_Display_On_Off(0xAF); // Display On (0xAE/0xAF)
    21. }
    复制代码

    • 该功能函数位于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. }
    复制代码

    3.4. 编译运行

    编译通过后,点击下载成功,复位运行。可看屏上显示"THEAD RISC-V\nGUI\nDEMO" 字符串。
    CH2601 单片机芯片及应用-RVB2601应用开发实战系列三: GUI图形显示risc-v单片机中文社区(5)

    5. 总结

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






    上一篇:基于wujian100 SoC的智能五子棋设备的设计实现及其与QQ游戏
    下一篇:使用CDK在RVB2061上编写IIC软件驱动
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-11-26 10:00 , Processed in 0.398665 second(s), 49 queries .

    快速回复 返回顶部 返回列表