移植 U8G2 到 GD32F350

u8g2 是一个在嵌入式中使用的开源的单色图形库,支持单色 OLED和 LCD,目前支持的设备有:SSD1305, SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, SH1107, SH1108, SH1122, T6963, RA8835, LC7981, PCD8544, PCF8812, HX1230, UC1601, UC1604, UC1608, UC1610, UC1611, UC1701, ST7565, ST7567, ST7588, ST75256, NT7534, IST3020, ST7920, LD7032, KS0108, SED1520, SBN1661, IL3820, MAX7219 等

官方资源有:

获取源码:

直接 git clone 获取:

git clone https://github.com/olikraus/u8g2

下载下来如下:

我用的屏是这个:

0.96 OLED,SSD1306 128X64,SPI 接口

把 u8g2 源码放到工程目录下面,然后开始移植。

添加源文件,u8g2 相关源码主要放在 u8g2 目录中 csrc 中,该目录中不止有 u8g2 图形相关源码,还有屏的驱动,添加源码的时候除了添加 u8g2 相关源码外,还需要添加所使用 屏的驱动,根据我所使用的屏,添加源码如下:

添加包含路径

这里使用模拟SPI,定义所使用 IO 口宏,并实现初始化函数:

#define U8G2_DC_PIN GPIO_PIN_10
#define U8G2_DC_PORT  GPIOB

#define U8G2_CS_PIN GPIO_PIN_11
#define U8G2_CS_PORT GPIOB

#define U8G2_RST_PIN GPIO_PIN_1
#define U8G2_RST_PORT  GPIOB

#define U8G2_D1_PIN GPIO_PIN_0
#define U8G2_D1_PORT GPIOB

#define U8G2_D0_PIN GPIO_PIN_7
#define U8G2_D0_PORT GPIOA


#define U8G2_D0_LOW()   gpio_bit_reset (U8G2_D0_PORT, U8G2_D0_PIN)
#define U8G2_D0_HIGH()  gpio_bit_set(U8G2_D0_PORT, U8G2_D0_PIN)

#define U8G2_D1_LOW()   gpio_bit_reset(U8G2_D1_PORT, U8G2_D1_PIN)
#define U8G2_D1_HIGH()  gpio_bit_set(U8G2_D1_PORT, U8G2_D1_PIN)


#define U8G2_DC_LOW()   gpio_bit_reset (U8G2_DC_PORT, U8G2_DC_PIN)
#define U8G2_DC_HIGH()  gpio_bit_set(U8G2_DC_PORT, U8G2_DC_PIN)

#define U8G2_CS_LOW()   gpio_bit_reset(U8G2_CS_PORT, U8G2_CS_PIN)
#define U8G2_CS_HIGH()  gpio_bit_set(U8G2_CS_PORT, U8G2_CS_PIN)

#define U8G2_RST_LOW()  gpio_bit_reset(U8G2_RST_PORT, U8G2_RST_PIN)
#define U8G2_RST_HIGH() gpio_bit_set(U8G2_RST_PORT, U8G2_RST_PIN)

void gd32_u8g2_io_init(void)
{
    gpio_mode_set(U8G2_D0_PORT,  GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, U8G2_D0_PIN);
    gpio_output_options_set(U8G2_D0_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, U8G2_D0_PIN);
    
    gpio_mode_set(U8G2_D1_PORT,  GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, U8G2_D1_PIN);
    gpio_output_options_set(U8G2_D1_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, U8G2_D1_PIN);

    gpio_mode_set(U8G2_DC_PORT,  GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, U8G2_DC_PIN);
    gpio_output_options_set(U8G2_DC_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, U8G2_DC_PIN);
    
    gpio_mode_set(U8G2_CS_PORT,  GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, U8G2_CS_PIN);
    gpio_output_options_set(U8G2_CS_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, U8G2_CS_PIN);

    gpio_mode_set(U8G2_RST_PORT,  GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, U8G2_RST_PIN);
    gpio_output_options_set(U8G2_RST_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, U8G2_RST_PIN);    
}

实现操作 IO 口的回调函数:

u8g2_t u8g2;

void delay_ns(uint32_t delay)
{
  uint32_t i=0,j=0;
  for(i=0;i<delay;i++)
    for(j=0;j<10;j++)
    __NOP();

}

uint8_t u8x8_gd32_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
	switch(msg)
	{
		case U8X8_MSG_DELAY_MILLI:      // delay arg_int * 1 milli second
              delay_1ms(arg_int);
			break;
		default:
			return 0;
	}
	return 1;
}


uint8_t u8x8_gd32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
	switch(msg)
	{
		case U8X8_MSG_GPIO_AND_DELAY_INIT:  // called once during init phase of u8g2/u8x8
             gd32_u8g2_io_init();
			break;              // can be used to setup pins
		case U8X8_MSG_GPIO_SPI_CLOCK:        // Clock pin: Output level in arg_int
			if(arg_int)
				U8G2_D0_HIGH();
			else
				U8G2_D0_LOW();
			break;
		case U8X8_MSG_GPIO_SPI_DATA:        // MOSI pin: Output level in arg_int
			if(arg_int)
				U8G2_D1_HIGH();
			else
				U8G2_D1_LOW();
			break;
		case U8X8_MSG_GPIO_CS:        // CS (chip select) pin: Output level in arg_int
			if(arg_int)
				U8G2_CS_HIGH();
			else
				U8G2_CS_LOW();
			break;
		case U8X8_MSG_GPIO_DC:        // DC (data/cmd, A0, register select) pin: Output level in arg_int
			if(arg_int)
				U8G2_DC_HIGH();
			else
				U8G2_DC_LOW();
			break;
		
		case U8X8_MSG_GPIO_RESET:     // Reset pin: Output level in arg_int
			if(arg_int)
				U8G2_RST_HIGH();
			else
				U8G2_RST_LOW();
			break;
		default:
			if (u8x8_gd32_delay(u8x8, msg, arg_int, arg_ptr))	// check for any delay msgs
				return 1;
			u8x8_SetGPIOResult(u8x8, 1);      // default return value
			break;
	}
	return 1;
}

调用相关初始化函数,并写个测试程序:

                                 
void ssd1306_128X64_u8g2_init(void)
{
  u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi , u8x8_gd32_gpio_and_delay);
  u8g2_InitDisplay(&u8g2);
  u8g2_SetPowerSave(&u8g2, 0);

  /* full buffer example, setup procedure ends in _f */
  u8g2_ClearBuffer(&u8g2);
  u8g2_SetFont(&u8g2, u8g2_font_helvR12_tf);
  u8g2_DrawStr(&u8g2, 0,32, "U8g2 on GD32");
  u8g2_DrawStr(&u8g2, 60, 56, "By Halin");
  u8g2_SendBuffer(&u8g2);
}

编译运行:

再来个,在 OLED 上显示计数,先实现个显示 2 位数的程序:

#define X_P  45
#define Y_P 49
//55 49
void show_num(uint8_t Num)
{
  char buf[2] = {0};
  uint8_t temp =0;
  temp = (Num) / 10;
  buf[0] = temp +'0';
  temp = (Num) % 10;
  buf[1] = temp +'0';
  u8g2_ClearBuffer(&u8g2);
  u8g2_DrawStr(&u8g2, X_P,Y_P, buf);
  u8g2_SendBuffer(&u8g2);
}

然后在主循环里面计数,并显示:

int main(void)
{
  uint8_t counter = 0;
    /* configure systick */
    systick_config();
    rcu_periph_clock_enable(RCU_GPIOB);
    /* initilize the LEDs, USART and key */
    led_init();

    u8g2_sw_spi_io_init();

    ssd1306_128X64_u8g2_init();
    while (1){

      GPIO_TG(GPIOF) = GPIO_PIN_6;
      delay_1ms(500);
      
      show_num(counter);
      counter ++;
      if(counter > 100)
        counter = 0;

    }
}

效果为:

posted @ 2022-07-08 14:52  哈拎  阅读(569)  评论(0编辑  收藏  举报