STM32移植U8G2库驱动0.96寸IIC屏幕

前言

        偶然发现U8G2这个图像库,发现这个库能实现许多好玩有趣的动画,因此花了一晚上时间将其移植到STM32中,趁着还有些印象记录一下。

准备

        1、U8G2源码下载:https://github.com/olikraus/u8g2 下载压缩包

        2、准备一个可以运行的代码,功能不需要复杂

移植

        将压缩包解压之后,打开csrc文件夹,其中包含了许多驱动文件,我们只需要保留我们使用屏幕的驱动代码即可,我使用的是一般的0.96寸的OLED屏幕,保留u8x8_d_ssd1306_128x64_noname.c 文件即可

       删减之后,将csrc文件夹重命名为U8g2,复制到你准备的工程中

        打开u8g2_d_setup.c文件,发现其中有许多函数,但是我们只需要保留其中一个:若使用的屏幕是iic接口,保留u8g2_Setup_ssd1306_i2c_128x64_noname_f函数,若使用的是spi接口,则保留u8g2_Setup_ssd1306_128x64_noname_f函数,这里我使用的是iic接口

        打开u8g2_d_memory.c文件,只保留u8g2_m_16_8_f函数

打开你的工程文件,将u8g2库添加进去(U8g2文件中全选添加即可)

别忘了魔术棒也需要添加文件地址

修改完毕即可将头文件添加到main.c中,#include "u8g2.h"

        运行后发现有10个报错和5个警告,其中5个警告均是由于文件末尾没有多打一个回车键,根据他的提示找到文件将回车添加上即可,修改后5个警告都没了。

        10个报错有两种解决办法:最简便的就是点开魔术棒的C/C++选项,将其中的C99 Mode勾选上

第二种方法是点开报错具体的语句,将其移到函数的前面去,以其中一个为例:

可以发现10个报错现在只剩9个报错了,其他报错的地方都是这样修改即可。这里我为了简便一点,采用第一种方法。

没有报错了。

接着需要编写U8G2接口程序了:新建一个Hardware文件

再添加OLED.c和OLED.h

OLED.C代码如下:

#include "OLED.h"

/*
	SDA = PB9;
	SCL = PB8;	
*/
#define IIC_OLED_SDA_Pin        	GPIO_Pin_9
#define IIC_OLED_SDA_GPIO       	GPIOB
#define IIC_OLED_SDA_GPIO_CLK		RCC_APB2Periph_GPIOB

#define IIC_OLED_SCL_Pin        	GPIO_Pin_8
#define IIC_OLED_SCL_GPIO       	GPIOB
#define IIC_OLED_SCL_GPIO_CLK		RCC_APB2Periph_GPIOB

/*引脚初始化*/
void OLED12864_I2C_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(IIC_OLED_SDA_GPIO_CLK,ENABLE);			//开启GPIO模块的时钟
	RCC_APB2PeriphClockCmd(IIC_OLED_SCL_GPIO_CLK,ENABLE);
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_InitStructure.GPIO_Pin = IIC_OLED_SCL_Pin;
 	GPIO_Init(IIC_OLED_SCL_GPIO, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = IIC_OLED_SDA_Pin;
 	GPIO_Init(IIC_OLED_SDA_GPIO, &GPIO_InitStructure);
}

void I2C_OLED_SDA_H(void)
{
	GPIO_SetBits(IIC_OLED_SDA_GPIO,IIC_OLED_SDA_Pin);
}
	
void I2C_OLED_SDA_L(void)
{
	GPIO_ResetBits(IIC_OLED_SDA_GPIO,IIC_OLED_SDA_Pin);
}
void I2C_OLED_SCL_H(void)
{
	GPIO_SetBits(IIC_OLED_SCL_GPIO,IIC_OLED_SCL_Pin);
}
	
void I2C_OLED_SCL_L(void)
{
	GPIO_ResetBits(IIC_OLED_SCL_GPIO,IIC_OLED_SCL_Pin);
}




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)
{
	switch(msg)
		{
			case U8X8_MSG_DELAY_MILLI:
				Delay_ms(arg_int);
				break;
		
			case U8X8_MSG_DELAY_10MICRO:
				Delay_us(10);
				break;
		
			case U8X8_MSG_DELAY_100NANO:
				__NOP();
				break;
			
			case U8X8_MSG_GPIO_I2C_CLOCK:
				if (arg_int) I2C_OLED_SCL_H();
				else I2C_OLED_SCL_L();
				break;
			
			case U8X8_MSG_GPIO_I2C_DATA:
				if (arg_int) I2C_OLED_SDA_H();
				else I2C_OLED_SDA_L();
				break;
			default:
				return 0;
	}
	return 1;
}

void u8g2Init(u8g2_t *u8g2)
{
	OLED12864_I2C_Init();
	u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8g2_gpio_and_delay_stm32);
	u8g2_InitDisplay(u8g2);     //初始化
	u8g2_SetPowerSave(u8g2, 0);
	u8g2_ClearBuffer(u8g2);//清屏
}

/*U8g2官方logo*/
void draw(u8g2_t *u8g2)
{
    u8g2_SetFontMode(u8g2, 1); /*字体模式选择*/
    u8g2_SetFontDirection(u8g2, 0); /*字体方向选择*/
	
    u8g2_SetFont(u8g2, u8g2_font_wqy16_t_chinese2); /*字库选择*/    
    u8g2_DrawUTF8(u8g2, 90, 20, "你好啊");

    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");
		u8g2_SendBuffer(u8g2);
		u8g2_ClearBuffer(u8g2);

}

OLED.h代码如下:

#ifndef __OLED_H
#define __OLED_H

#include "stm32f10x.h"
#include "u8g2.h"
#include "Delay.h"
void OLED12864_I2C_Init(void);
void I2C_OLED_SDA_H(void);
void I2C_OLED_SDA_L(void);
void I2C_OLED_SCL_H(void);
void I2C_OLED_SCL_L(void);
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);
void u8g2Init(u8g2_t *u8g2);
void draw(u8g2_t *u8g2);

#endif

main.c代码如下:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

int main(void)
{
		u8g2_t u8g2;
		u8g2Init(&u8g2);
    while(1)
		{
			draw(&u8g2);
		}
}

运行:

发现报了许多错误,原因是u8g2_fonts.c中的字库太庞大,解决办法有两种,其一是删除或者注释掉u8g2_fonts.c中不需要的字库

办法二是直接将编译器的优化等级拉到最大。

配置修改完毕之后重新运行,可能会遇到编译错误,中文乱码的情况

这时点击魔术棒,切换到C/C++选项栏,Misc Controls 中添加编译选项:

--no-multibyte-chars

提醒: 若使用中文显示那些不常见的字,可能会导致编译不报错但不显示的问题,为正常现象,因为字库中没有该字,这种情况请自行百度解决。

运行结果

重新运行不报任何错误了,烧写代码,移植成功!

代码参考

Keil MDK 工程输入中文汉字编译报错解决办法_lvgl guider 中文 在keil中编译错误-CSDN博客

Keil-MDK版本中的C99 mode功能-CSDN博客

stm32移植U8G2图像库指南_u8g2图像框架-CSDN博客

U8g2库的STM32硬件SPI(DMA)移植教程(HAL、OLED显示、四线SPI、DMA)_cubexmx-CSDN博客

玩转u8g2 OLED库,一篇就够——基于SMT32、HAL-CSDN博客

作者:starry night10

物联沃分享整理
物联沃-IOTWORD物联网 » STM32移植U8G2库驱动0.96寸IIC屏幕

发表评论