立创梁山派GD32F450ZGT6--0.96IIC屏移植u8g2

一、硬件准备

使用的主控是:立创梁山派GD32F450ZGT6

使用的OLED是:0.96寸4针IIC通信的OLED屏

二、u8g2介绍

U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306等多种类型的OLED驱动,显示丝滑。

三、精简u8g2

首先去下载u8g2的源码

U8g2源码的开源库地址:https://github.com/olikraus/u8g2

(因为是外网,所以会有一点慢)

源码下载下来之后,我们只需要关注文件夹里面的【csrc】文件夹下的文件。

因为u8g2支持很多的驱动芯片,所以整个文件对我们的工程来说非常大。我们只需要我们屏幕的驱动文件,其他无用的文件可以删除。

3.1删除其他不需要的驱动文件

这些驱动文件通常是u8x8_d_xxx.c,xxx包括驱动的型号和屏幕分辨率。我们使用的是ssd1306驱动芯片的OLED,分辨率是128*64。在u8g2里使用的是u8x8_ssd1306_128x64_noname.c这个文件,其它的屏幕驱动和分辨率的文件可以删掉。(我这里已经把其他的驱动文件删除,只剩下需要的)

3.2 删除其他的驱动入口函数

在u8g2_d_setup.c里,因为我们的OLED是IIC的接口,所以只留一个我们要用到的【u8g2_Setup_ssd1306_i2c_128x64_noname_f】函数就好,其他的可以删除或者注释

在函数结尾加上

/* 注意要加上这一句 不然无法显示*/

u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);

(如果你嫌弃删除麻烦,可以直接复制下面的代码)

/*该文件属于 u8g2_d_setup.c */
#include "u8g2.h"

/*
 * 给IIC接口的OLED用的
 * 函数最后的数字或字母,代表显示时的buf大小:
    1:128字节
    2:256字节
    f:1024字节
*/
void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
  uint8_t tile_buf_height;
  uint8_t *buf;
  u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
  buf = u8g2_m_16_8_f(&tile_buf_height);
/* 注意要加上这一句 不然无法显示*/
  u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}

3.3删除内存文件中的其他函数

由于用到的u8g2_Setup_ssd1306_i2c_128x64_noname_f函数中,只调用了u8g2_m_16_8_f这个函数,这个函数在【u8g2_d_memory.c】里面,留下这个函数,其它的函数一定要删掉或注释掉,否则编译时很可能会提示内存不足。

#include "u8g2.h"
/*该文件属于 u8g2_d_memory.c */

uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{
  #ifdef U8G2_USE_DYNAMIC_ALLOC
  *page_cnt = 8;
  return 0;
  #else
  static uint8_t buf[1024];
  *page_cnt = 8;
  return buf;
  #endif
}
//记得给新行,不然有警告

3.4 IIC初始化及回调函数编写

我们的屏幕是需要IIC进行通信的,这里选择使用的是软件IIC。因为u8g2里自带了软件IIC代码,我们只需要提供用的是哪一个引脚,还有提供IIC需要的延时函数即可。

/*该代码位于oled.c 和 oled.h */
//需要修改的引脚时钟
#define     RCU_SCL                     RCU_GPIOF
#define     RCU_SDA                     RCU_GPIOC

//需要修改的引脚  SCL SDA
#define     GPIO_periph_SCL      GPIOF                        
#define     GPIO_pin_SCL          GPIO_PIN_8            

#define      GPIO_periph_SDA      GPIOC                        
#define      GPIO_pin_SDA          GPIO_PIN_3            

void IIC_software_init(void)
{
    rcu_periph_clock_enable(RCU_SCL);
    rcu_periph_clock_enable(RCU_SDA);
    //SCL
    gpio_mode_set(GPIO_periph_SCL, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_pin_SCL);
    gpio_output_options_set(GPIO_periph_SCL, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_pin_SCL);
    //SDA
    gpio_mode_set(GPIO_periph_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_pin_SDA);
    gpio_output_options_set(GPIO_periph_SDA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_pin_SDA);    
    gpio_bit_write(GPIO_periph_SCL, GPIO_pin_SCL, SET);
    gpio_bit_write(GPIO_periph_SDA, GPIO_pin_SDA, SET);
}

回调函数的主要功能有

1、赋予U8g2相应的延时函数,比如下面的delay_ms和delay_us

2、为U8g2提供IIC接口的高低电平调用:

U8X8_MSG_GPIO_I2C_CLOCK:IIC的SCL

U8X8_MSG_GPIO_I2C_DATA:IIC的SDA

回调函数:

/*
u8x8回调函数
/*该代码属于 u8g2_d_setup.c */
*/
uint8_t u8x8_gpio_and_delay_gd32f450(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

        IIC_software_init();
  
      break;                                                        // can be used to setup pins
    case U8X8_MSG_DELAY_MILLI:                    // delay arg_int * 1 milli second
  
        delay_1ms(1);
            
      break;
    case U8X8_MSG_DELAY_I2C:       // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
            if(arg_int == 1)delay_us(5);
            else if(arg_int == 4){;}
      break;                  // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
        case U8X8_MSG_GPIO_RESET:     // Reset pin: Output level in arg_int
      break;
    case U8X8_MSG_GPIO_I2C_CLOCK:    // arg_int=0: Output low at I2C clock pin
          //SCL输出
          gpio_bit_write(GPIO_periph_SCL, GPIO_pin_SCL, (bit_status)arg_int);

      break;     // arg_int=1: Input dir with pullup high for I2C clock pin
    case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
        //SDA输出
        gpio_bit_write(GPIO_periph_SDA, GPIO_pin_SDA, (bit_status)arg_int);

      break;         // arg_int=1: Input dir with pullup high for I2C data pin
//下面是按键设置
//    case U8X8_MSG_GPIO_MENU_SELECT:
//      u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ key_state_get(BSP_KEY1_PIN));
//            //printf("u8g2 get key sel\r\n");
//      break;
//    case U8X8_MSG_GPIO_MENU_NEXT:
//      u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ key_state_get(BSP_KEY2_PIN));
//            //printf("u8g2 get key next\r\n");
//      break;
//    case U8X8_MSG_GPIO_MENU_PREV:
//      u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ key_state_get(BSP_KEY3_PIN));
//            //printf("u8g2 get key prev\r\n");
//      break;
//    case U8X8_MSG_GPIO_MENU_HOME:
//      u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ key_state_get(BSP_KEY4_PIN));
//            //printf("u8g2 get key home\r\n");
      break;
    default:
      u8x8_SetGPIOResult(u8x8, 1);            // default return value
      break;
  }
  return 1;
}

四、显示测试

将改好的文件复制到过程文件夹里。(我放在工程目录APP里的u8g2文件夹下)

打开工程导入u8g2的.c文件(创建一个新目录)

导入完成的样子

main.c

#include "gd32f4xx.h"
#include "systick.h"
#include "led.h"
#include "oled.h"
#include "u8g2.h"
#include "stdio.h"//请在魔法棒处,勾选 Use MicroLIB

u8g2_t u8g2;

void u8g2Init(u8g2_t *u8g2)
{
     // 初始化 u8g2 结构体
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_gd32f450); 
    u8g2_InitDisplay(u8g2);         //根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
    u8g2_SetPowerSave(u8g2, 0);    //打开显示器
    
    u8g2_SetFont(u8g2, u8g2_font_unifont_t_chinese2); //设置字体
    u8g2_SetFontDirection(u8g2, 0);                   //字体方向向右
} 
  
int main(void)
{
    char temp[20], i = 0, j = 0, k = 0;
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);  // 中断分组3
    systick_config();                                  //系统滴答定时器   定时1us    
    LED_Init();             //LED初始化
    IIC_software_init();    //IIC的GPIO初始化
    u8g2Init(&u8g2);        //u8g2初始化
    
    while(1)
    {
        u8g2_ClearBuffer((u8g2_t*)&u8g2);//先清除缓冲区数据

        u8g2_DrawRFrame(&u8g2, 5, 10, 128-(12*1),40, 5);//显示圆角空心矩形
        sprintf(temp,"i = %d",i++);
        u8g2_DrawStr(&u8g2,6,29,temp);               //显示字符串
        sprintf(temp,"j = %d",j+=2);
        u8g2_DrawStr(&u8g2,62,29,temp);              //显示字符串
        sprintf(temp,"k = %d",k+=3);
        u8g2_DrawStr(&u8g2,38,43,temp);              //显示字符串

        u8g2_SendBuffer((u8g2_t*)&u8g2);//发送缓冲区数据到屏幕
        delay_1ms(50);  
  }
}

如果编译后发现有几百个的错误,像下面。

那么需要开启优化,最少开1级。

开启后重新编译即可。

实际效果:

实测效果视频展示

代码链接:

链接:https://pan.baidu.com/s/1DU0uHcqeBtcHSRBLjOJLxQ?pwd=1234

提取码:1234

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老怪.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值