MM32F3273G8P火龙果开发板MindSDK开发教程17 -U8g2库的移植

MM32F3273G8P火龙果开发板MindSDK开发教程17 -U8g2 OLED库的移植

1、U8g2简介

手头正好有一块0.96寸的OLED屏,驱动芯片为ssd1306,心想怎么才能显示更为炫彩的图像。无意间,接触到U8g2图形库,遂决定将其移植到自己的工程中。
U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306等多种类型的OLED驱动。
github下载地址

2、准备工作

我这块屏是i2c接口的,u8g2即支持软件模拟i2c,也支持硬件i2c。之前的工程里关于PC6 PC7软硬件i2c都有适配,这里用模拟i2c,因为简单,bug少啊。
软件i2c pc6 pc7gpio的配置代码如下:

void BOARD_I2C1_Init(void)
{
#if I2C_MODE == USE_HARD_I2C    
    GPIO_Init_Type gpio_init;
    /* PC6 - I2C1_SCL. */
    gpio_init.Pins  = GPIO_PIN_6;
    gpio_init.PinMode  = GPIO_PinMode_AF_OpenDrain;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, gpio_init.Pins, GPIO_AF_4);

    /* PC7 - I2C1_SDA. */
    gpio_init.Pins  = GPIO_PIN_7;
    gpio_init.PinMode  = GPIO_PinMode_AF_OpenDrain;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, gpio_init.Pins, GPIO_AF_4);

    /* Setup I2C initialization values. */
    I2C_Master_Init_Type i2c_init;
    i2c_init.ClockFreqHz = CLOCK_APB1_FREQ;
    i2c_init.BaudRate = I2C_BaudRate_100K;

    /* Initialize I2C master. */
    I2C_InitMaster(I2C1, &i2c_init);

    /* The target device address needs to be configured before enabling. */
    I2C_SetTargetAddr(I2C1, MSA311_I2CADDR_DEFAULT_7);

    /* Enable I2C. */
    I2C_Enable(I2C1, true);

#elif I2C_MODE == USER_SW_I2C 
    GPIO_Init_Type gpio_init;
    gpio_init.Pins  = SWI2C1_SCL_PIN;
    gpio_init.PinMode  = GPIO_PinMode_Out_OpenDrain;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(SWI2C1_SCL_PORT, &gpio_init);
    GPIO_PinAFConf(SWI2C1_SCL_PORT, gpio_init.Pins, GPIO_AF_15); /* disable the alternative functions. */

    /* PC7 - I2C1_SDA. */
    gpio_init.Pins  = SWI2C1_SDA_PIN;
    gpio_init.PinMode  = GPIO_PinMode_Out_OpenDrain;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(SWI2C1_SDA_PORT, &gpio_init);
    GPIO_PinAFConf(SWI2C1_SDA_PORT, gpio_init.Pins, GPIO_AF_15); /* disable the alternative functions. */

    SWI2C1_SDA_HIGH; 
	SWI2C1_SCL_HIGH;
#endif    
}

.h文件

#define I2C_MODE        USER_SW_I2C

#if I2C_MODE == USER_SW_I2C
// PC6 scl PC7 sda
#define SWI2C1_SCL_PORT     GPIOC
#define SWI2C1_SCL_PIN      GPIO_PIN_6
#define SWI2C1_SCL_HIGH 	GPIO_WriteBit(SWI2C1_SCL_PORT,SWI2C1_SCL_PIN,1u)
#define SWI2C1_SCL_LOW 		GPIO_WriteBit(SWI2C1_SCL_PORT,SWI2C1_SCL_PIN,0u)

#define SWI2C1_SDA_PORT     GPIOC
#define SWI2C1_SDA_PIN      GPIO_PIN_7
#define SWI2C1_SDA_HIGH 	GPIO_WriteBit(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN,1u)
#define SWI2C1_SDA_LOW		GPIO_WriteBit(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN,0u)
#define SWI2C1_SDA_READ     GPIO_ReadInDataBit(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN)
#define BIT0     0x01
#define BIT7     0x80
#endif

注意将gpio设置为开漏模式。

3、移植u8g2

将下载的u8g2解压,我们只需要csrc文件夹的文件,其余可以先不关注。
由于u8g2支持的驱动种类繁多,所以我们只需要找到我们对应的驱动文件即可。

a、我们的驱动芯片是ssd1306,128*64,所以我们对应的驱动文件为u8x8_d_ssd1306_128x64_noname.c,其余以u8xu8_d_xxx命名的文件都全部是删除掉。

删掉后的代码视图:
MM32F3273G8P火龙果开发板MindSDK开发教程17 -U8g2库的移植_第1张图片

b、精剪u8g2_d_setup.c文件,只保留u8g2_Setup_ssd1306_i2c_128x64_noname_f这一个函数。

如图:
MM32F3273G8P火龙果开发板MindSDK开发教程17 -U8g2库的移植_第2张图片

c、精剪u8g2_d_memory.c,因为u8g2_Setup_ssd1306_i2c_128x64_noname_f,只调用了u8g2_m_16_8_f函数,所以u8g2_d_memory.c只保留着一个函数。

如图:
MM32F3273G8P火龙果开发板MindSDK开发教程17 -U8g2库的移植_第3张图片

d、添加u8x8_gpio_and_delay函数,软件模拟i2c按照下面这样填充这个函数

uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
    switch (msg) {
        case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
            __NOP();
            break;
        case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
            for (uint16_t n = 0; n < 320; n++)
                __NOP();
            break;
        case U8X8_MSG_DELAY_MILLI:   // delay arg_int * 1 milli second
            BOARD_Delay1Ms(1);
            break;
        case U8X8_MSG_DELAY_I2C:     // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
            BOARD_Delay1Us(3);
            break;                    // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
        case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
            arg_int ? GPIO_WriteBit(SWI2C1_SCL_PORT,SWI2C1_SCL_PIN,1u) : GPIO_WriteBit(SWI2C1_SCL_PORT,SWI2C1_SCL_PIN,0u);  
            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
            arg_int ? GPIO_WriteBit(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN,1u) : GPIO_WriteBit(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN,0u);  
            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 */ 0);
            break;
        case U8X8_MSG_GPIO_MENU_NEXT:
            u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
            break;
        case U8X8_MSG_GPIO_MENU_PREV:
            u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
            break;
        case U8X8_MSG_GPIO_MENU_HOME:
            u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
            break;
        default:
            u8x8_SetGPIOResult(u8x8, 1); // default return value
            break;
    }
    return 1;
}

主要是延时函数,以及scl sda对应的gpio的控制。

e、最后将裁减的文件放到device/u8g2文件下,并在Makefile里添加u8g2的编译选项。

4、u8g2的使用

void u8g2Init(u8g2_t *u8g2)
{
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay);  // 初始化 u8g2 结构体
    u8g2_InitDisplay(u8g2); // 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
    u8g2_SetPowerSave(u8g2, 0); // 打开显示器
    u8g2_ClearBuffer(u8g2);
}

void draw(u8g2_t *u8g2)
{
    u8g2_SetFontMode(u8g2, 1); /*字体模式选择*/
    u8g2_SetFontDirection(u8g2, 0); /*字体方向选择*/
    u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /*字库选择*/
    u8g2_DrawStr(u8g2, 0, 20, "U");
    
    u8g2_SetFontDirection(u8g2, 1);
    u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
    u8g2_DrawStr(u8g2, 21,8,"8");
        
    u8g2_SetFontDirection(u8g2, 0);
    u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
    u8g2_DrawStr(u8g2, 51,30,"g");
    u8g2_DrawStr(u8g2, 67,30,"\xb2");
    
    u8g2_DrawHLine(u8g2, 2, 35, 47);
    u8g2_DrawHLine(u8g2, 3, 36, 47);
    u8g2_DrawVLine(u8g2, 45, 32, 12);
    u8g2_DrawVLine(u8g2, 46, 33, 12);
  
    u8g2_SetFont(u8g2, u8g2_font_4x6_tr);
    u8g2_DrawStr(u8g2, 1,54,"github.com/olikraus/u8g2");
}

main函数调用:

// BOARD_InitPins();
	u8g2_t u8g2;
    u8g2Init(&u8g2);	

	while(1)
	{
		// Msa311_GetXYZData();
        // BOARD_Delay1Ms(1000);
		u8g2_FirstPage(&u8g2);
		do
		{
				draw(&u8g2);
		} while (u8g2_NextPage(&u8g2));
	}	

烧录后,可以看见u8g2官方的logo了。

5、现象

MM32F3273G8P火龙果开发板MindSDK开发教程17 -U8g2库的移植_第4张图片

6、代码

移植好的代码

你可能感兴趣的:(火龙果MM32F3273G8P,单片机,嵌入式硬件,stm32,mm32,mm32F3273G8p)