基于以7920为核心的点阵型LCD12864成熟代码工程u8g2的移植——stm32单片机

0、前言

     一直以来都在寻找一个方便的、可靠的、丰富的点阵型LCD驱动库 ,因为大型的GUI解决方案并不适合像12864(基于7920)这种资源紧缺型的显示模组使用,而网络上充斥代码的资源都是简单实现了一个字符输出功能,达不到预期的目的。直到无意中看到了u8g2。通过学习后发现该显示库支持很多种字体 fonts (英文和数字),而且具有完整的驱动函数库(直线、圆形、斜线、字符旋转镜像反白、bitmap一应俱全)和丰富的演示demo。特别适合应用在嵌入式mcu上面。于是把它移植到了stm32上面,因此才有了这篇blog。

github地址:https://github.com/olikraus/u8g2 

U8g2: Library for monochrome displays, version 2

U8g2 is a monochrome graphics library for embedded devices. U8g2 supports controller based (for example SSD1306) monochrome OLEDs and LCDs (See the U8g2/U8x8 setup guide for a complete list of supported display controller). The Arduino library U8g2 can be installed from the library manager of the Arduino IDE. U8g2 also includes U8x8 library:

U8g2

  • Includes all graphics procedures (line/box/circle draw).
  • Supports many fonts. (Almost) no restriction on the font height.
  • Requires some memory in the microcontroller to render the display.

U8x8

  • Text output only (character) device.
  • Only fonts allowed with fixed size per character (8x8 pixel).
  • Writes directly to the display. No buffer in the microcontroller required.

     Setup Guide and Reference Manual

通过介绍(readme.md)可以知道u8g2是一个支持嵌入式设备的显示驱动库,它包含了两种驱动,其中u8g2支持像12864这种常见的点阵型LCD,u8x8支持像1602这种字符型LCD,此外它所支持的所以驱动IC如下所示:

Supported Display Controller: SSD1305, SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, T6963, RA8835, LC7981, PCD8544, PCF8812, UC1601, UC1604, UC1608, UC1610, UC1611, UC1701, ST7565, ST7567, ST7588, ST75256, NT7534, IST3020, ST7920, LD7032, KS0108, SED1520, SBN1661, IL3820, MAX7219 (see here for a full list)

查阅后确认:LCD ST7920 128X64 在支持的范围内,但是作者提供的demo都是基于Arduino使用,并没有直接在stm32上直接调用的实例。“U8g2 works nicely without C++/Arduino --by olikraus”。自己动手,丰衣足食,既然没有,那么接下来就自己动手移植!~

1、环境准备

  • Windows7 sp1
  • Keil MDK 5.24(armcc v5.06 update5)+ Jlink
  • MCU : STM32F103C8T6  (64k flash 、20k ram)
  • LCD :  ZXM12864F4 (controller st7920)
  • u8g2:  2017-12-09 v2.20.13
  • STM32Cube_FW_F1_V1.6.0  (STM32F1xx HAL Drivers v1.1.1  2017-5-12)

2、移植

      根据作者提供的移植说明《Porting-to-new-MCU-platform》,需要我们实现的函数主要有两个:

  • The "uC specific" GPIO and Delay callback (the last argument of the setup function)
  • The u8x8 byte communication callback (the second to last argument of the setup function)
     这两个函数主要被一个初始化setup函数调用,其函数原型(例子)如下所示:
     u8g2_Setup_st7920_s_128x64_f(  u8g2,   rotation,   u8x8_byte_4wire_sw_spi,   uC specific)
 
1、第一个参数 ,u8g2 : Pointer to an empty u8g2 structure 
     指向一个包含所有显示参数的结构体    a structure which will contain all the data for one display
     其定义方式如:u8g2_t u8g2;  具体成员说明,请参阅u8g2.h文件。
2、第二个参数 ,rotation:Rotation procedure
      用于处理字符旋转或者镜像的句柄,在显示库中已被定义,直接调用即可。
Rotation/MirrorDescription
U8G2_R0 No rotation, landscape
U8G2_R1 90 degree clockwise rotation
U8G2_R2 180 degree clockwise rotation
U8G2_R3 270 degree clockwise rotation
U8G2_MIRROR No rotation, landscape, display content is mirrored (v2.6.x)
3、第三个参数 ,u8x8_byte_4wire_sw_spi:Byte communication procedure
     字节传输控制,mcu(stm32)和lcd控制芯片(ST7920)的通讯函数,也是需要移植实现的函数之一。
 
     如果使用mcu片上外设(硬件SPI、I2C)的话,需要自行实现该函数的功能。
     函数的蓝本:
   typedef uint8_t (*u8x8_msg_cb)(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
     函数需要的处理的Message:
MessageDescription
U8X8_MSG_BYTE_INIT Send once during the init phase of the display.
U8X8_MSG_BYTE_SET_DC Set the level of the data/command pin. arg_intcontains the expected output level. Use u8x8_gpio_SetDC(u8x8, arg_int) to send a message to the GPIO procedure.
U8X8_MSG_BYTE_START_TRANSFER Set the chip select line here. u8x8->display_info->chip_enable_level contains the expected level. Use u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level) to call the GPIO procedure.
U8X8_MSG_BYTE_SEND Send one or more bytes, located at arg_ptrarg_intcontains the number of bytes.
U8X8_MSG_BYTE_END_TRANSFER Unselect the device. Use the CS level from here: u8x8->display_info->chip_disable_level.
     函数的样本(硬件SPI方式):
[cpp] view plain copy
 
  1. uint8_t u8x8_byte_arduino_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)   
  2. {  
  3.   uint8_t *data;  
  4.   uint8_t internal_spi_mode;   
  5.   switch(msg)   
  6.   {  
  7.     case U8X8_MSG_BYTE_SEND:  
  8.       data = (uint8_t *)arg_ptr;  
  9.       while( arg_int > 0 )   
  10.       {  
  11.         SPI.transfer((uint8_t)*data);  
  12.         data++;  
  13.         arg_int--;  
  14.       }    
  15.       break;  
  16.     case U8X8_MSG_BYTE_INIT:  
  17.       u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);  
  18.       SPI.begin();  
  19.       break;  
  20.     case U8X8_MSG_BYTE_SET_DC:  
  21.       u8x8_gpio_SetDC(u8x8, arg_int);  
  22.       break;  
  23.     case U8X8_MSG_BYTE_START_TRANSFER:  
  24.       internal_spi_mode =  0;  
  25.       switch(u8x8->display_info->spi_mode)   
  26.       {  
  27.         case 0: internal_spi_mode = SPI_MODE0; break;  
  28.         case 1: internal_spi_mode = SPI_MODE1; break;  
  29.         case 2: internal_spi_mode = SPI_MODE2; break;  
  30.         case 3: internal_spi_mode = SPI_MODE3; break;  
  31.        }  
  32.       SPI.beginTransaction(SPISettings(u8x8->display_info->sck_clock_hz, MSBFIRST, internal_spi_mode));  
  33.       u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);    
  34.       u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);  
  35.       break;  
  36.     case U8X8_MSG_BYTE_END_TRANSFER:        
  37.       u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);  
  38.       u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);  
  39.       SPI.endTransaction();  
  40.       break;  
  41.     default:  
  42.       return 0;  
  43.   }    
  44.   return 1;  
  45. }  
 
      如果使用者是用软件模拟串行协议的话,显示库提供以下几种模拟协议,可以直接使用。
    In order to interface to the communication port of the display controller you need to have a byte orientated interface i.e. SPI, I2C, etc. This interface may either be implemented as a bit-banged software interface or using the MCU specific hardware. Several software bit-banged interface are provided as part of the U8X8 library in u8x8_byte.c:
Byte ProcedureDescription
u8x8_byte_4wire_sw_spi Standard 8-bit SPI communication with "four pins" (SCK, MOSI, DC, CS)
u8x8_byte_3wire_sw_spi 9-bit communication with "three pins" (SCK, MOSI, CS)
u8x8_byte_8bit_6800mode Parallel interface, 6800 format
u8x8_byte_8bit_8080mode Parallel interface, 8080 format
u8x8_byte_sw_i2c Two wire, I2C communication
u8x8_byte_ks0108 Special interface for KS0108 controller
     上面列表中的函数还将调用第四个参数uC specific:gpio and delay functions。
4、第四个参数, uC specific:The "uC specific" GPIO and Delay callback
     函数的蓝本为:
   typedef uint8_t (*u8x8_msg_cb)(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
     该函数的功能在于:提供mcu的GPIO操作接口,用于实现软件模拟串行协议。需要处理来自HAL层的3种消息任务(message)。(注:如果使用mcu片上外设(硬件SPI、I2C),则不需要实现该函数,直接返回1即可)
  1. Delay messages of the form "U8X8_MSG_DELAY_". These messages are used to provide delay for the software implementation of I2C, SPI etc.
    In order for the software (aka. bit-banged) interfaces to work you need to implement the MCU specific busy-wait loop to provide a correct amount of delay.
    For the example implementation I used the Cypress PSoC specific delay functions of the form CyDelay*

  2. GPIO messages of the form "U8X*_MSG_GPIO". These messages are used to write 1s and 0s to the GPIOs which are being used to interface to the device. i.e. the SCL/SDA or Reset or CS etc.
    For the example implementation I used the Cypress pin write functions which all take the form of "pinname_Write()".

  3. GPIO menu pins are used to get the state of an input pin. These messages are only required for the build in menu function and can be ignored, if the U8G2/U8X8 menu functions are not used.

     函数的样板为:
[cpp] view plain copy
 
  1. uint8_t u8x8_gpio_and_delay_template(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)  
  2. {  
  3.   switch(msg)  
  4.   {  
  5.     case U8X8_MSG_GPIO_AND_DELAY_INIT:  // called once during init phase of u8g2/u8x8  
  6.       break;                // can be used to setup pins  
  7.     case U8X8_MSG_DELAY_NANO:       // delay arg_int * 1 nano second  
  8.       break;      
  9.     case U8X8_MSG_DELAY_100NANO:<span style="white-space:pre;"> </span>// delay arg_int * 100 nano seconds  
  10.       break;  
  11.     case U8X8_MSG_DELAY_10MICRO:    // delay arg_int * 10 micro seconds  
  12.       break;  
  13.     case U8X8_MSG_DELAY_MILLI:      // delay arg_int * 1 milli second  
  14.       break;  
  15.     case U8X8_MSG_DELAY_I2C:        // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz  
  16.       break;<span style="white-space:pre;">             </span>// arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us  
  17.     case U8X8_MSG_GPIO_D0:      // D0 or SPI clock pin: Output level in arg_int  
  18.   //case U8X8_MSG_GPIO_SPI_CLOCK:  
  19.       break;  
  20.     case U8X8_MSG_GPIO_D1:      // D1 or SPI data pin: Output level in arg_int  
  21.   //case U8X8_MSG_GPIO_SPI_DATA:  
  22.       break;  
  23.     case U8X8_MSG_GPIO_D2:      // D2 pin: Output level in arg_int  
  24.       break  
  25.     case U8X8_MSG_GPIO_D3:      // D3 pin: Output level in arg_int  
  26.       break;  
  27.     case U8X8_MSG_GPIO_D4:      // D4 pin: Output level in arg_int  
  28.       break;  
  29.     case U8X8_MSG_GPIO_D5:      // D5 pin: Output level in arg_int  
  30.       break;  
  31.     case U8X8_MSG_GPIO_D6:      // D6 pin: Output level in arg_int  
  32.       break;  
  33.     case U8X8_MSG_GPIO_D7:      // D7 pin: Output level in arg_int  
  34.       break;  
  35.     case U8X8_MSG_GPIO_E:       // E/WR pin: Output level in arg_int  
  36.       break;  
  37.     case U8X8_MSG_GPIO_CS:      // CS (chip select) pin: Output level in arg_int  
  38.       break;  
  39.     case U8X8_MSG_GPIO_DC:<span style="white-space:pre;">       </span>// DC (data/cmd, A0, register select) pin: Output level in arg_int  
  40.       break;  
  41.     case U8X8_MSG_GPIO_RESET:       // Reset pin: Output level in arg_int  
  42.       break;  
  43.     case U8X8_MSG_GPIO_CS1:     // CS1 (chip select) pin: Output level in arg_int  
  44.       break;  
  45.     case U8X8_MSG_GPIO_CS2:     // CS2 (chip select) pin: Output level in arg_int  
  46.       break;  
  47.     case U8X8_MSG_GPIO_I2C_CLOCK:   // arg_int=0: Output low at I2C clock pin  
  48.       break;                // arg_int=1: Input dir with pullup high for I2C clock pin  
  49.     case U8X8_MSG_GPIO_I2C_DATA:    // arg_int=0: Output low at I2C data pin  
  50.       break;                // arg_int=1: Input dir with pullup high for I2C data pin  
  51.     case U8X8_MSG_GPIO_MENU_SELECT:  
  52.       u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);  
  53.       break;  
  54.     case U8X8_MSG_GPIO_MENU_NEXT:  
  55.       u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);  
  56.       break;  
  57.     case U8X8_MSG_GPIO_MENU_PREV:  
  58.       u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);  
  59.       break;  
  60.     case U8X8_MSG_GPIO_MENU_HOME:  
  61.       u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);  
  62.       break;  
  63.     default:  
  64.       u8x8_SetGPIOResult(u8x8, 1);<span style="white-space:pre;">   </span>// default return value  
  65.       break;  
  66.   }  
  67.   return 1;  
  68. }  
    并不是所有的case都需要实现,只需实现和mcu的GPIO连接相关的case和Delay Message。

3、实践

     经过移植分析后,结合现有的硬件条件,可以得出:

  • 使用软件模拟4线spi方式来驱动LCD12864(st7920)引脚对应方式如下:

PB10      - CLK          - E
PB11      - SPI data   - R/W
PB9        - RST          - RST
  -           - CS           - PSB                (已经外接下拉电阻,默认为串行模式)
PB12      - CD           - RS

  • 使用Full screen buffer mode模式,调用 u8g2_Setup_st7920_s_128x64_f 函数
  • 使用u8g2库自带的函数u8x8_byte_4wire_sw_spi, 软件模拟spi串行协议
  • 需要实现 u8g2_gpio_and_delay_stm32 函数


    具体步骤:

  1. 下载u8g2库源文件,将所有相关的c文件(csrc文件夹)添加到keil工程中,keil工程使用STM32Cube_FW_F1_V1.6.0下的f103分支的temple模板。
  2. 添加u8g2_gpio_and_delay_stm32支持,具体代码如下:
[cpp] view plain copy
 
  1. uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)  
  2. {  
  3.         GPIO_InitTypeDef  gpioinitstruct;  
  4.       
  5.         switch(msg){  
  6.   
  7.         //Function which implements a delay, arg_int contains the amount of ms  
  8.         case U8X8_MSG_GPIO_AND_DELAY_INIT:  
  9.   
  10.         __HAL_RCC_GPIOB_CLK_ENABLE();  
  11.         /* Configure the GPIO_LED pin */  
  12.         gpioinitstruct.Pin    = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9;  
  13.         gpioinitstruct.Mode   = GPIO_MODE_OUTPUT_PP;  
  14.         gpioinitstruct.Pull   = GPIO_NOPULL;  
  15.         gpioinitstruct.Speed  = GPIO_SPEED_FREQ_HIGH;  
  16.         HAL_GPIO_Init(GPIOB, &gpioinitstruct);  
  17.           
  18.         HAL_GPIO_WritePin(LED_GPIO_PORT, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9, GPIO_PIN_SET);   
  19.   
  20.         break;  
  21.         //Function which implements a delay, arg_int contains the amount of ms  
  22.         case U8X8_MSG_DELAY_MILLI:  
  23.         HAL_Delay(arg_int);  
  24.         break;  
  25.         //Function which delays 10us  
  26.         case U8X8_MSG_DELAY_10MICRO:  
  27.         delay_us(10);  
  28.         break;  
  29.         //Function which delays 100ns  
  30.         case U8X8_MSG_DELAY_100NANO:  
  31.         __NOP();  
  32.   
  33.         break;  
  34.         //Function to define the logic level of the clockline  
  35.         case U8X8_MSG_GPIO_SPI_CLOCK:  
  36.             if (arg_int) LCD_SCLK_1;  
  37.             else LCD_SCLK_0;  
  38.   
  39.         break;  
  40.         //Function to define the logic level of the data line to the display  
  41.         case U8X8_MSG_GPIO_SPI_DATA:  
  42.             if (arg_int) LCD_SID_1;  
  43.             else LCD_SID_0;  
  44.   
  45.         break;  
  46.   
  47.         // Function to define the logic level of the CS line  
  48.         case U8X8_MSG_GPIO_CS1:  
  49.             if (arg_int) LCD_RS_1   ;  
  50.             else LCD_RS_0;  
  51.   
  52.         break;  
  53.         //Function to define the logic level of the Data/ Command line  
  54.         case U8X8_MSG_GPIO_DC:  
  55.   
  56.         break;  
  57.         //Function to define the logic level of the RESET line  
  58.         case U8X8_MSG_GPIO_RESET:  
  59.             if (arg_int) LCD_RST_1;  
  60.             else LCD_RST_0;  
  61.   
  62.         break;  
  63.           
  64.         default:  
  65.             return 0; //A message was received which is not implemented, return 0 to indicate an error  
  66.     }  
  67.   
  68.     return 1; // command processed successfully.  
  69. }  

      3. 裁剪  u8g2_d_setup.c   u8g2_d_memory.c 文件中与st7920无关的代码,减小代码体积,ram用量。

      4. 修改 u8x8.h 文件,添加u8g2显示库对 keil setction(armcc) 的支持。

[cpp] view plain copy
 
  1. #define SECTION(x)   __attribute__((section(x)))  
  2. #ifndef U8X8_FONT_SECTION  
  3. #  define U8X8_FONT_SECTION(name) SECTION(".font." name)  
  4. #endif  

      5.修改 main() 函数,初始化u8g2显示库,增加显示代码。

[cpp] view plain copy
 
  1. int main(void)  
  2. {  
  3.  /* This sample code shows how to configure The HAL time base source base with a  
  4.     dedicated  Tick interrupt priority. 
  5.     A general purpose timer (TIM2) is used instead of Systick as source of time base.   
  6.     Time base duration is fixed to 1ms since PPP_TIMEOUT_VALUEs are defined and  
  7.     handled in milliseconds basis. 
  8.     */  
  9.   
  10.   /* STM32F1xx HAL library initialization: 
  11.        - Configure the Flash prefetch 
  12.        - Configure timer (TIM2) to generate an interrupt each 1 msec 
  13.        - Set NVIC Group Priority to 4 
  14.        - Low Level Initialization 
  15.      */  
  16.   HAL_Init();  
  17.     
  18.   /* Configure the system clock to 72 MHz */  
  19.   SystemClock_Config();  
  20.     
  21.   /* Configure LED */  
  22.   BSP_LED_Init();    
  23.       
  24.   u8g2_Setup_st7920_s_128x64_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8g2_gpio_and_delay_stm32);   
  25.   u8g2_InitDisplay(&u8g2);  
  26.   u8g2_SetPowerSave(&u8g2, 0);   
  27.       
  28.     HAL_Delay(1000);  
  29.   
  30.   /* Insert a Delay of 1000 ms and toggle LED2, in an infinite loop */    
  31.   while (1)  
  32.   {  
  33.     /* Insert a 1s delay */  
  34.     HAL_Delay(1000);    
  35.     BSP_LED2_Toggle();  
  36.     BSP_LED1_Toggle();  
  37.           
  38.     u8g2_ClearBuffer(&u8g2);  
  39.     u8g2_SetFontMode(&u8g2, 1);  
  40.     u8g2_SetFontDirection(&u8g2, 0);  
  41.     u8g2_SetFont(&u8g2, u8g2_font_helvB18_te);  
  42.     u8g2_DrawStr(&u8g2,  0, 24, "hello world");  
  43.     u8g2_DrawStr(&u8g2,  0, 50, "i am Re.");  
  44.     u8g2_SetFont(&u8g2, u8g2_font_u8glib_4_tf);  
  45.     u8g2_DrawStr(&u8g2,  0, 60, "2018-01-18");  
  46.     u8g2_SendBuffer(&u8g2);  
  47.   }   
  48. }  

      6.修改与工程相关的其他代码,编译,下载。

     7.测试

4、后记

      u8g2库支持的函数如下:u8g2reference

      u8x8库支持的函数如下:u8x8reference

      该显示库基于c编写,在修改相关的GPIO操作函数后,本keil工程理论上支持所有的stm32单片机驱动st7920 12864系列lcd。如需移植到其他lcd,请参考移植步骤。
 
      关于中文字库:因为普遍的中文字库都比较大,不适合直接添加到显示库中,建议需要的时候,将需要的中文转成fonts文件,然后编译、链接进工程,具体的fonts转换,请参阅github的描述。Rebuild Fonts 
    
      一个中文的u8g2可以使用的汉字库,来自larryli/u8g2_wqy :https://github.com/larryli/u8g2_wqy
      
      本blog相关的代码(stm32 keil工程)已经上传至我的github: https://github.com/refugeer/stm32_st7920_u8g2

5、其他

接口说明 Wiring
 
Pin ArgumentDescriptionDatasheet Names
clock SPI or I2C clock line SCL, SCLK, ...
data SPI or I2C data line SDA, MOSI, SDIN, ...
d0 ... d7 Data lines of the parallel interface D0 ... D7
cs Chip select line CS
dc Data/command selection line (register select) D/C, A0, RS, ...
enable "Write" for the 8080 interface, "enable" for the 6800 interface 8080: WR, 6800: E
reset Reset line

串行协议说明

  • 3SPI, 3-wire SPI: Serial Peripheral Interface with three signals: Clock, Data and Chip-Select.
  • 4SPI, 4-Wire SPI: Same as 3SPI, but with one additional line for commands and data (often labeled as D/C, RS or A0)
  • I2C, IIC or TWI: Inter-Integrated Circuit Bus which has two signals: Clock (SCL) and Data (SDA).
  • 8080: A 8-Bit bus which requires 8 data lines, chip select and a write strobe signal.
  • 6800: Another 8-Bit bus, but with a different protocol.

setup中buffersize的说明

asda

Controller "st7920", Display "128x64"Descirption
u8g2_Setup_st7920_128x64_1(u8g2, rotation, u8x8_byte_8bit_6800mode, uC specific) page buffer, size = 128 bytes
u8g2_Setup_st7920_128x64_2(u8g2, rotation, u8x8_byte_8bit_6800mode, uC specific) page buffer, size = 256 bytes
u8g2_Setup_st7920_128x64_f(u8g2, rotation, u8x8_byte_8bit_6800mode, uC specific) full framebuffer, size = 1024 bytes
 Description
Buffer Description
1 Only one page of the display memory is stored in the microcontroller RAM. Use a firstPage()/nextPage() loop for drawing on the display.
2 Same as 1, but maintains two pages in the microcontroller RAM. This will up to two times faster than 1.
F Keep a copy of the full display frame buffer in the microcontroller RAM. Use clearBuffer() to clear the RAM and sendBuffer() to transfer the microcontroller RAM to the display.

The full buffer F option can be used only, if there is sufficient RAM available in the microcontroller. Use option 1 or 2 on a microcontroller with small amount of RAM. The u8x8 APIcan be used if there is not even RAM for one page.

U8g2 绘制模式说明

U8g2 supports three different drawing modes:

  • Full screen buffer mode
  • Page mode (This is the U8glib picture loop)
  • U8x8, character only mode

Full screen buffer mode

Pros and Cons

  • Fast
  • All graphics procedures can be used
  • Requires a lot of RAM

Setup

Use the U8g2 constructor from here. The constructor must include the "F" character. For example:

u8g2_Setup_st7920_128x64_f(u8g2, rotation, u8x8_byte_8bit_6800mode, uC specific)

Usage

  1. Clear the buffer with u8g2.clearBuffer().
  2. Draw something with the usual draw commands.
  3. Send the buffer to the display with u8g2.sendBuffer().

Example

void setup(void) {
  u8g2.begin();
}

void loop(void) {
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.drawStr(0,20,"Hello World!");
  u8g2.sendBuffer();
}

Page buffer mode (Picture Loop)

Pros and Cons

  • All graphics procedures can be used
  • Only a little bit of RAM is required
  • Slow

Setup

Use the U8g2 constructor from here. The constructor must include the "1" or "2" character. For example:

u8g2_Setup_st7920_128x64_1(u8g2, rotation, u8x8_byte_8bit_6800mode, uC specific)

Usage

  1. Call u8g2.firstPage().
  2. Start a do-while loop
  3. Inside the loop-body: Draw something with the usual draw commands.
  4. Loop as long as u8g2.nextPage() returns true.

Note: Always create the same picture inside the loop body. See details here.

Example

void setup(void) {
  u8g2.begin();
}

void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,24,"Hello World!");
  } while ( u8g2.nextPage() );
}

U8x8 character mode

Pros and Cons

  • Fast
  • No RAM required
  • No graphics possible
  • Not available for all displays

Setup

Use the U8x8 constructor from here. For example:

u8x8_Setup(u8x8_d_ssd1306_128x64_noname, u8x8_cad_001, u8x8_byte_4wire_sw_spi, uC specific)

Usage

All draw commands directly write to the display.

Example

void setup(void) {
  u8x8.begin();
}

void loop(void) {
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.drawString(0,1,"Hello World!");
}

 

嵌入式全新视频:www.makeru.com.cn/?t=12               嵌入式学习交流群:561213221

原文地址:https://www.cnblogs.com/huan-huan/p/8528307.html