STM32:移植u8g2图形库(文末附项目开源地址)

硬件:STM32F103ZET6最小系统板,​​​​0.96寸OLED(4针IIC接口),

软件:keil5
注意:本例默认具有一定的开发经验,不介绍如何创建keil模板项目,请自备好可用的项目!!!

实在不会的可以参考一下鄙人的这篇文章:STM32单片机项目模板(基于Keil5,以STM32F10x为例)_stm32f10xfwlib-优快云博客

也可以在我分享的网盘里直接下载模板(来自正点原子例程模板)

1. 获取U8G2库文件并解压:

1. u8g2图形库Github链接

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

2. 笔者分享的百度网盘链接

链接:https://pan.baidu.com/s/1tk85bqkTAX51dfXhZMPCqg?pwd=3cko 
提取码:3cko 

3. 笔者分享的阿里云盘链接:(阿里云盘不支持压缩包,大家用其他链接获取吧)

分享
https://www.alipan.com/s/VbVV1EuARkw
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。

4. 笔者分享的夸克网盘链接

「教程资料」,复制整段内容,打开最新版「夸克APP」即可获取。
畅享原画,免费5倍速播放,支持AI字幕和投屏,更有网盘TV版。
/!95d4330ubQ!:/
链接:https://pan.quark.cn/s/566f5303e7ce
解压出来就是这一个u8g2-master(忽略其他文件,是我自己的文件,与本例无关,只需要关注这个即可)

2. 开始移植

1. 创建U8G2文件夹

在STM32的Keil项目中创建U8G2文件夹,用来存放U8G2库文件:

2. 移植库文件

1. 打开U8G2库文件->csrc:

2. 将文件按名称排序,复制以下文件到刚刚创建的U8G2文件夹:

  • 第一部分:前34个文件,也就是u8x8_d_开头的文件之前的文件,如图:

  • 第二部分:本例是0.96寸OLED,128*64的分辨率,所以选择这个文件:
u8x8_d_ssd1306_128x64_noname.c

  • 第三部分:以下文件,也就是所有u8x8_d_开头的文件之后的文件,如图:

3. 打开keil项目

1. 将文件夹里的文件和路径添加到项目,这一步默认大家会,就不教了(实在不会的话,又不嫌弃咱的话,可以看看鄙人的这一篇介绍如何创建keil项目模板的文章),添加后效果,如图:

2. 找到u8g2_setup_d.c打开,其他函数注释掉或者删掉,只保留头文件和下面的这个函数:

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. 找到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
}

4. 在项目目录下,创建一个专门放自己写的驱动代码的文件夹,然后再创建一个放具体驱动的文件夹,例如这里是OLED驱动,准确的说是模拟IIC的函数,你取名叫OLED.C或者IIC.C都可以,看你意愿,这里我取名OLED.C和OLED.H:

5. 然后依照惯例,将两个文件和这个文件夹的路径添加到keil项目里,这里不详说前面教过:

6. oled.c里添加以下代码:(里面的delay相关函数来自正点原子例程源码的delay.c和delay.h)

#include "stm32f10x.h"
#include "u8g2.h"
#include "oled.h"
#include "delay.h"

static void OLED_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;	//PB6:CLK, PB7:SDA
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	//GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 
}

uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  switch(msg)
  {
    case U8X8_MSG_GPIO_AND_DELAY_INIT:
      /* only support for software I2C*/
	  OLED_Init();
      break;
    case U8X8_MSG_DELAY_NANO:
      /* not required for SW I2C */
      break;
    
    case U8X8_MSG_DELAY_10MICRO:
      /* not used at the moment */
      break;
    
    case U8X8_MSG_DELAY_100NANO:
      /* not used at the moment */
      break;
   
    case U8X8_MSG_DELAY_MILLI:
      delay_ms(arg_int);
      break;
    case U8X8_MSG_DELAY_I2C:
      /* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
      delay_us(arg_int<=2?5:1);
      break;
    
    case U8X8_MSG_GPIO_I2C_CLOCK:
      
      if ( arg_int == 0 )
      {
			GPIO_ResetBits(GPIOB, GPIO_Pin_6);
      }
      else
      {
			GPIO_SetBits(GPIOB, GPIO_Pin_6);
      }
      break;
    case U8X8_MSG_GPIO_I2C_DATA:
      
      if ( arg_int == 0 )
      {
			GPIO_ResetBits(GPIOB, GPIO_Pin_7);
      }
      else
      {
			GPIO_SetBits(GPIOB, GPIO_Pin_7);
      }
      break;
/*
    case U8X8_MSG_GPIO_MENU_SELECT:
      u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
      break;
    case U8X8_MSG_GPIO_MENU_NEXT:
      u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
      break;
    case U8X8_MSG_GPIO_MENU_PREV:
      u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
      break;
    
    case U8X8_MSG_GPIO_MENU_HOME:
      u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
      break;
*/
    default:
      u8x8_SetGPIOResult(u8x8, 1);
      break;
  }
  return 1;
}

void u8g2_Init(u8g2_t *u8g2)
{
	u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0);
	u8g2_InitDisplay(u8g2);
	u8g2_SetPowerSave(u8g2, 0);
	u8g2_ClearBuffer(u8g2);
}


7. oled.h里要添加的文件,大家都很熟悉,如下:

#ifndef _OLED__H_
#define _OLED__H_

#include "u8g2.h"

void u8g2_Init(u8g2_t *u8g2);

#endif


8. main函数,测试移植结果:(懒得写注释了,一看就懂的代码,另外,u8g2各个函数的作用,自行学习,不介绍,因为我也还在学)

#include "stm32f10x.h"
#include "delay.h"
#include "u8g2.h"
#include "oled.h"

u8g2_t u8g2;

void Delay(u32 count)
{
	u32 i=0;
	for(;i<count;i++);
}

int main(void)
{	
	/* LED */	
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);	//ʹÄÜPB,PE¶Ë¿ÚʱÖÓ
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_5;			    					//LED0-->PB.5 ¶Ë¿ÚÅäÖÃ
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_Out_PP; 	 						//ÍÆÍìÊä³ö
	GPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz;	 							//IO¿ÚËÙ¶ÈΪ50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);			    							//³õʼ»¯GPIOB.5
	GPIO_SetBits(GPIOB, GPIO_Pin_5);												//PB.5 Êä³ö¸ß
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_5;	            					//LED1-->PE.5ÍÆÍìÊä³ö
	GPIO_Init(GPIOE, &GPIO_InitStructure);	  	        							//³õʼ»¯GPIO
	GPIO_SetBits(GPIOE, GPIO_Pin_5); 			 									//PE.5 Êä³ö¸ß 	 

	/* Init */
	delay_init();
	u8g2_Init(&u8g2);
	
	while(1)
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
		GPIO_SetBits(GPIOE,GPIO_Pin_5);
		Delay(3000000);
		GPIO_SetBits(GPIOB,GPIO_Pin_5);
		GPIO_ResetBits(GPIOE,GPIO_Pin_5);
		Delay(3000000);
		u8g2_FirstPage(&u8g2);
		do
		{
			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_inb24_mf);
			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, 32, 12);
			u8g2_SetFont(&u8g2, u8g2_font_5x7_tf);
			u8g2_DrawStr(&u8g2, 1, 54, "github.com/olikraus/u8g2");
		} while(u8g2_NextPage(&u8g2));
	}
}


4. 测试结果:

5. 总结,配合视频和图文,还是很简单的,有问题评论区见!

项目开源地址:https://github.com/MWD-IOT/stm32.git

 参考自视频:U8g2移植到stm32单片机,点亮OLED_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IorT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值