u8g2库移植stm32f103c8t6(0.96英寸oled屏)

准备材料

  • 一个正常运行的keil5工程模版
  • 下载U8g2的Stm32实例模版(下载链接

stm32实例模版获取

  1. 点击上文超链接进入github,点击Code下的Download ZIP,下载u8g2的源码,如下图

下载stm32U8g2示图
2. 点击“WiKi”,向下滑动选择“Porting to new MCR platform”,向下滑动选择“stm32”,之后点击Code下的Download ZIP,下载工程示例。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/在这里插入图片描述
3. 解压下载的“u8g2-master”文件夹,选择csrc文件夹,将其移动到keil工程下。(该文件夹为u8g2的c语言文件)

4. 去掉无用的驱动文件,只保留u8x8_d_ssd1306_128x64_noname。剩下的_d文件如下图
在这里插入图片描述

  1. 解压“u8g2_template_stm32f103c8t6-master”取出文件中的main.c文件备用
    在这里插入图片描述

源码移植

  1. 将上述精简之后的csrc文件加入工程中,千万不要忘记在魔术棒加入路径。
    在这里插入图片描述
  2. 精简U8g2_d_setup.c,只保留u8g2_Setup_ssd1306_i2c_128x64_noname_f函数(370行)。

在这里插入图片描述

  1. 精简U8g2_d_memory.c,只保留u8g2_m_16_8_f(61行)

在这里插入图片描述
4. 编译修改报错至0 error,这一步根据自己的编译器环境不同会有不同的报错,主流的报错有变量定义位置报错,和最后一行非空行警告。
2

编写初始化函数

oled管脚初始化代码

/*oled.c*/
#include "oled.h"

//SDA = PB7     结合自身硬件确定SDA管脚号
//SCL = PB6     结合自身硬件确定SCL管脚号

/*引脚配置*/
#define IIC_OLED_SDA_Pin        GPIO_Pin_7
#define IIC_OLED_SDA_GPIO       GPIOB
#define IIC_OLED_SDA_GPIO_CLK   RCC_APB2Periph_GPIOB

#define IIC_OLED_SCL_Pin        GPIO_Pin_6
#define IIC_OLED_SCL_GPIO       GPIOB
#define IIC_OLED_SCL_GPIO_CLK   RCC_APB2Periph_GPIOB

/*引脚初始化*/
void OLED_I2C_Init(void)
{
  RCC_APB2PeriphClockCmd(IIC_OLED_SDA_GPIO_CLK, ENABLE);
  RCC_APB2PeriphClockCmd(IIC_OLED_SCL_GPIO_CLK, ENABLE);

	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = IIC_OLED_SDA_Pin;
 	GPIO_Init(IIC_OLED_SDA_GPIO, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = IIC_OLED_SCL_Pin;
 	GPIO_Init(IIC_OLED_SCL_GPIO, &GPIO_InitStructure);
	
}

void IIC_OLED_SDA_HIGH(void)
{
	GPIO_SetBits(IIC_OLED_SDA_GPIO,IIC_OLED_SDA_Pin);
}

void IIC_OLED_SDA_LOW(void)
{
		GPIO_ResetBits(IIC_OLED_SDA_GPIO,IIC_OLED_SDA_Pin);
}

void IIC_OLED_SCL_HIGH(void)
{
	GPIO_SetBits(IIC_OLED_SCL_GPIO,IIC_OLED_SCL_Pin);
}

void IIC_OLED_SCL_LOW(void)
{
	GPIO_ResetBits(IIC_OLED_SCL_GPIO,IIC_OLED_SCL_Pin);
}
/*oled.h*/
#ifndef __OLED_H
#define __OLED_H 

#include "stm32f10x.h"                 

void OLED_I2C_Init(void);
void IIC_OLED_SDA_HIGH(void);
void IIC_OLED_SDA_LOW(void);
void IIC_OLED_SCL_HIGH(void);
void IIC_OLED_SCL_LOW(void);

#endif

编写主函数

主函数由官方示例中给的HAL库代码等效移植到库函数下。
打开准备文件中所准备的main.c函数,示例中
在131行,定义了结构体u8g2;
在156行,调用了setup中的函数,我们找到U8g2_d_setup.c文件调用(在上述精简函数中剩下的那一个);
在54行,有u8g2_Setup_ssd1306_i2c_128x64_noname_f的回调函数,需要将其转化为标准库下对应代码。

//定义结构体 131行
	u8g2_t u8g2;
	
//调用setup中的函数 156行
	u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_3wire_sw_spi, u8g2_gpio_and_delay_stm32);
	//&u8g2:定义的结构体参数   
	//U8G2_R0:屏幕方向   
	//u8x8_byte_3wire_sw_spi:屏幕与MCU通讯方式这里我们所用的为软件i2c需要将参数改为u8x8_byte_sw_i2c
	//u8g2_gpio_and_delay_stm32:回调函数,函数定义在第54行

//回调函数
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){
		//Initialize SPI peripheral
		case U8X8_MSG_GPIO_AND_DELAY_INIT:
			/* HAL initialization contains all what we need so we can skip this part. */

		break;

		//Function which implements a delay, arg_int contains the amount of ms
		case U8X8_MSG_DELAY_MILLI:
		HAL_Delay(arg_int);

		break;
		//Function which delays 10us
		case U8X8_MSG_DELAY_10MICRO:
		for (uint16_t n = 0; n < 320; n++)
		{
			__NOP();
		}

		break;
		//Function which delays 100ns
		case U8X8_MSG_DELAY_100NANO:
		__NOP();

		break;
		//Function to define the logic level of the clockline
		case U8X8_MSG_GPIO_SPI_CLOCK:
			if (arg_int) HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, RESET);
			else HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, SET);

		break;
		//Function to define the logic level of the data line to the display
		case U8X8_MSG_GPIO_SPI_DATA:
			if (arg_int) HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, SET);
			else HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, RESET);

		break;
		// Function to define the logic level of the CS line
		case U8X8_MSG_GPIO_CS:
			if (arg_int) HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, RESET);
			else HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, SET);

		break;
		//Function to define the logic level of the Data/ Command line
		case U8X8_MSG_GPIO_DC:
//			if (arg_int) HAL_GPIO_WritePin(CD_LCD_PORT, CD_LCD_PIN, SET);
//			else HAL_GPIO_WritePin(CD_LCD_PORT, CD_LCD_PIN, RESET);

		break;
		//Function to define the logic level of the RESET line
		case U8X8_MSG_GPIO_RESET:
			if (arg_int) HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, SET);
			else HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, RESET);

		break;
		default:
			return 0; //A message was received which is not implemented, return 0 to indicate an error
	}

	return 1; // command processed successfully.
}

更改主函数后的代码:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "LED.h"
#include "EXTI_Key.h"
#include "U8g2.h"

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) IIC_OLED_SCL_HIGH();
				else IIC_OLED_SCL_LOW();
		break;
		
		case U8X8_MSG_GPIO_I2C_DATA:
				if (arg_int) IIC_OLED_SDA_HIGH();
				else IIC_OLED_SDA_LOW();
		break;
		
		default:
			return 0; 
	}
	return 1; 
}
int main(void)
{
	
	u8g2_t u8g2;
	OLED_I2C_Init();
	LED_Init();

	u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8g2_gpio_and_delay_stm32);
    u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
    u8g2_SetPowerSave(&u8g2, 0); // wake up display
	Delay_ms(1000);
	
    u8g2_DrawLine(&u8g2, 0,0, 127, 63);//划线,前两位为起点的横纵坐标,后两位为终点的横纵坐标
    u8g2_DrawLine(&u8g2, 127,0 , 0,63);
    u8g2_SendBuffer(&u8g2);
	
	while (1)
	{

	}
}

}

结语

至此u8g2对stm32的库函数移植就完成了,u8g2的部分主要函数用法会在下篇文章中总结给出,下面还会给出用于测试移植效果的主函数代码。小白入门学习总结,有任何意见欢迎+Q:1825912434讨论。

测试代码

//main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "LED.h"
#include "EXTI_Key.h"
#include "U8g2.h"


void draw(u8g2_t *u8g2);

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) IIC_OLED_SCL_HIGH();
				else IIC_OLED_SCL_LOW();
		break;
		
		case U8X8_MSG_GPIO_I2C_DATA:
				if (arg_int) IIC_OLED_SDA_HIGH();
				else IIC_OLED_SDA_LOW();
		break;
		
		default:
			return 0; 
	}
	return 1; 
}


int main(void)
{
	
	u8g2_t u8g2;
	OLED_I2C_Init();
	LED_Init();
	
	
	u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8g2_gpio_and_delay_stm32);
  u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
  u8g2_SetPowerSave(&u8g2, 0); // wake up display
	u8g2_ClearBuffer(&u8g2);
	Delay_ms(1000);
	
	u8g2_DrawLine(&u8g2, 0,0, 127, 63);//划线,前两位为起点的横纵坐标,后两位为终点的横纵坐标
	u8g2_DrawLine(&u8g2, 127,0 , 0,63);
	
	u8g2_ClearBuffer(&u8g2);
	draw(&u8g2);
	
	while (1)
	{

	}
}

void draw(u8g2_t *u8g2)
{
   	u8g2_ClearBuffer(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");
	
	  u8g2_SendBuffer(u8g2);
	  Delay_ms(1000);
}

测试效果展示

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值